-
Notifications
You must be signed in to change notification settings - Fork 21
Java parser/typer rejects import of Java inner class #7675
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
Comments
Imported From: https://issues.scala-lang.org/browse/SI-7675?orig=1 |
@paulp said: |
Donny Nadolny (dnadolny) said: Given this Scala: import javapkg.JavaClass object Main extends App { class SomeScala(str: String) { This compiles and runs when passed as source to scala:
{code:title=javapkg/JavaClass.java}
package javapkg;
import scalapkg.SomeScala;
public class JavaClass {
public void useInner(Object probablyInner) {
SomeScala.InnerClass inner = (SomeScala.InnerClass) probablyInner;
inner.printStr();
}
} This would be compiled by java to the exact same .class file as the one above, but it does not compile when passed to scala as source: import scalapkg.SomeScala.*; public class JavaClass { When you put "SomeScala.InnerClass" in the signature for "JavaClass.useInner", instead of Object, then the scala compiler complains (although the Java compiler allows it, and it runs and does what you expect). So maybe this is just a case of scala only rejecting method signatures that it doesn't like, rather than checking the body of the method. How are you supposed to use a scala inner class from java? |
@paulp said: The question presupposes that you're supposed to. It's sure to be unsound - there are good reasons you can't "new Foo#Bar" in scala - and plenty of scala features are effectively inaccessible from java. |
Donny Nadolny (dnadolny) said: but this java class shouldn't?
{code:title=java}
class JavaClass {
public void useInner(SomeScala.InnerClass inner) {
inner.printStr();
}
} They're equivalent, aren't they? Yet the scala compiler will reject the 2nd one. I don't understand why using scala inner classes from java is sure to be unsound. The example above should be fine, and the only unsound usage I can think of isn't prevented by the scala compiler: a.useMyInner(aa); //useMyInner is "def useMyInner(inner: InnerClass) = ???" If you're not convinced, this probably won't convince you but I'll voice my opinion anyway: I would prefer a scala compiler that didn't do extra checks on java code, unless they were just given as warnings. Rejecting java code that would compile with the java compiler means you can't convert your java project to a mixed scala/java project. To anyone who complained that they can use java to do unsound things with scala classes (eg the "b.useMyInner(aa)" example), I think a fair response would be "if you want the safety of the scala compiler, write in scala". |
@retronym said: In general, if the Java source can be separately compiled, scalac should also be able to jointly compile it. We've got this code in Typers which looks like it ought to apply to this case. We'll have to investigate why it doesn't. if (!reallyExists(sym)) {
def handleMissing: Tree = {
def errorTree = missingSelectErrorTree(tree, qual, name)
def asTypeSelection = (
if (context.unit.isJava && name.isTypeName) {
// SI-3120 Java uses the same syntax, A.B, to express selection from the
// value A and from the type A. We have to try both.
atPos(tree.pos)(gen.convertToSelectFromType(qual, name)) match {
case EmptyTree => None
case tree1 => Some(typed1(tree1, mode, pt))
}
}
else None
) |
@paulp said: |
@retronym said: https://github.com/retronym/scala/tree/ticket/7675 |
@retronym said: {code}package p1; This results in:
|
Uh oh!
There was an error while loading. Please reload this page.
If you have Scala code with an inner class and attempt to use a wildcard import in Java so that you can use that class name unqualified, the Scala compiler will give an error when reading in that Java source.
Here is an example:
Compile with:
This is valid Java code, and would work if SomeScala was compiled first, then JavaClass compiled depending on the SomeScala*.class files.
A workaround is using the partially qualified name "SomeScala.Inner" rather than "Inner"
(This came up on the mailing list, https://groups.google.com/forum/#!topic/scala-ide-user/zkGaA_-uig8 )
The text was updated successfully, but these errors were encountered: