Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Byte conforms to Char when comes from public static final field in Java #8338

Closed
scabug opened this issue Feb 25, 2014 · 8 comments
Closed

Comments

@scabug
Copy link

scabug commented Feb 25, 2014

Java code:

public class R {
    public static final byte z = 123;
}

Scala code:

object A {
  val x: Char = R.z
}

Scala code shouldn't compile. Moreover in case of static method in Java code won't compile.

@scabug
Copy link
Author

scabug commented Feb 25, 2014

Imported From: https://issues.scala-lang.org/browse/SI-8338?orig=1
Reporter: @Alefas
Affected Versions: 2.10.3

@scabug
Copy link
Author

scabug commented Mar 3, 2014

@adriaanm said (edited on Mar 3, 2014 6:26:37 PM UTC):
The R.z is constant-folded (inlined by the type checker), and then the following implicit conversion is implied (from the spec):

Numeric Literal Narrowing. If the expected type is Byte, Short or Char, and the expression e is an integer literal fitting in the range of that type, it is converted to the same literal in that type.

@scabug
Copy link
Author

scabug commented Mar 4, 2014

@Alefas said:
It's reasonable for computer, but looks not obvious for human. I think it should be inlined with appropriate type annotation. For example if compiler will be able to inline functions, then compiler will not be able to compile such code, because inline phase will be after type checking phase. So it will be inconsistency. Or vice versa, depending on inlining it will be or not compilable, that's weird.

@scabug
Copy link
Author

scabug commented Mar 4, 2014

@adriaanm said (edited on Mar 4, 2014 5:26:30 PM UTC):
I'm not arguing this isn't a little surprising, but this is the correct behavior.
This kind of inlining happens during type checking and types are preserved. It just happens in two steps: fold the constant (R.z -> 123), widen the type (byte --> Char).

@scabug
Copy link
Author

scabug commented Mar 7, 2014

@paulp said:
Um, Byte doesn't widen to Char. Where would you like to put (-5: Byte)?

Nothing widens to Char. It's a bug.

@scabug
Copy link
Author

scabug commented Mar 7, 2014

@adriaanm said:
Sorry, I meant "narrow" (not "widen") as in my original comment, which I still think is correct. R.z is considered a constant because its definition in java is a "constant value definition " (spec: 4.1, implementation: widenIfNecessary), and it fits in a Char. You can't write this in Scala source because you can't express a Byte ConstantType. ((5: Byte).type?)

@scabug
Copy link
Author

scabug commented Mar 7, 2014

@paulp said:
So 5/6 of these can successfully be assigned to a byte:

    public static final byte z1  = 123;
    public static final short z2 = 123;
    public static final char z3  = 123;
    public static final int z4   = 123;
    public static final long z5  = 123;
    public static final byte z6  = -123;

Why stop at 5? Squeeze the long in too, that 123 is just as 123 as the other 123s.

It's funny to think that one could change a static final java int from 127 to 128, and this would break the scala code which makes use of it, and it would all be by design. I hope things keep getting weirder.

@scabug
Copy link
Author

scabug commented Mar 7, 2014

@adriaanm said:
It's still Not a Bug. There may be an Improvement here somewhere. final vals are our #defines. Maybe we should require a @define annotation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant