Skip to content

when mixing Scala and Java, scalac doesn't recognize unqualified name of inherited enum #1211

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

Closed
scabug opened this issue Aug 11, 2008 · 11 comments · Fixed by scala/scala#10565

Comments

@scabug
Copy link

scabug commented Aug 11, 2008

compilation fails if all source files are passed to scalac:

  ~/newbug> cat I.java 
interface I { public enum E { E1 } }
  ~/newbug> cat J.java 
class J implements I {
	public void foo(E e) { }
}
  ~/newbug> cat S.scala 
object S { (new J).foo(null) }
  ~/newbug> ~/scala/dists/latest/bin/scalac I.java J.java S.scala 
J.java:2: error: not found: type E
	public void foo(E e) { }
                        ^
one error found

but succeeds if javac is run first:

  ~/newbug> javac *.java
  ~/newbug> ~/scala/dists/latest/bin/scalac S.scala

the bug is very easy to work around by writing out the name more fully:

  ~/newbug> cat J.java 
class J implements I {
	public void foo(I.E e) { }
}
  ~/newbug> ~/scala/dists/latest/bin/scalac I.java J.java S.scala

I'm running r15746.

@scabug
Copy link
Author

scabug commented Aug 11, 2008

Imported From: https://issues.scala-lang.org/browse/SI-1211?orig=1
Reporter: @SethTisue

@scabug
Copy link
Author

scabug commented Nov 1, 2008

@SethTisue said:
the bug is still present in 2.7.2.RC6.

@scabug
Copy link
Author

scabug commented Feb 28, 2009

@paulp said:
This is fixed in trunk.

@scabug
Copy link
Author

scabug commented Apr 18, 2013

John Sirois (jsirois) said:
This issue still exists, or exists in a very similar form in scalac 2.9.2:

$ scalac -version
Scala compiler version 2.9.2 -- Copyright 2002-2011, LAMP/EPFL
$ cat I.java 
abstract class I { public enum E { E1 } }
$ cat J.java 
class J extends I {
  public void foo(E e) { }
}
$ cat S.scala 
object S { (new J).foo(null) }
$ scalac I.java J.java S.scala
J.java:2: error: not found: type E
  public void foo(E e) { }
                  ^
one error found

The only changes from the initial bug example are s/interface/abstract class/ in I.java and scalac 2.9.2.

Things test fine when I is an interface. I have not checked the scalac 2.8 variable.

@scabug
Copy link
Author

scabug commented Apr 21, 2013

John Sirois (jsirois) said:
The issue exists in 2.10.1 as well:

$ cat I.java 
abstract class I { public enum E { E1 } }
$ cat J.java 
class J extends I {
  public void foo(E e) { }
}
$ cat S.scala 
object S { (new J).foo(null) }
$ ./bin/scalac -version
Scala compiler version 2.10.1 -- Copyright 2002-2013, LAMP/EPFL
$ ./bin/scalac I.java J.java S.scala 
J.java:2: error: not found: type E
  public void foo(E e) { }
                  ^
one error found

@scabug
Copy link
Author

scabug commented Apr 21, 2013

John Sirois (jsirois) said:
And finally this appears to have been an issue even with the initial fix - happy to file a new bug if thats helpful:

$ /opt/scala-2.8.0.final/bin/scalac -version
Scala compiler version 2.8.0.final -- Copyright 2002-2010, LAMP/EPFL
$ /opt/scala-2.8.0.final/bin/scalac I.java J.java S.scala 
J.java:2: error: not found: type E
  public void foo(E e) { }
                  ^
one error found
$ /opt/scala-2.8.2.final/bin/scalac -version
Scala compiler version 2.8.2.final -- Copyright 2002-2010, LAMP/EPFL
$ /opt/scala-2.8.2.final/bin/scalac I.java J.java S.scala 
J.java:2: error: not found: type E
  public void foo(E e) { }
                  ^
one error found

@scabug
Copy link
Author

scabug commented Apr 21, 2013

John Sirois (jsirois) said (edited on Apr 21, 2013 11:54:58 PM UTC):
The parser phase output for I.java as interface and abstract class give a clue (using scalac 2.10.1) - note the abstract class has no type forwarder for the enum:

Interface:

[[syntax trees at end of                    parser]] // I.java
package <empty> {
  private[<empty>] object I extends  {
    def <init>() = _;
    object E extends  {
      def <init>() = _;
      <stable> <static> val E1: E = _;
      <static> def values(): scala.Array[E] = _;
      <static> def valueOf(x: String): E = _
    };
    <static> class E extends _root_.java.lang.Enum[E] {
      import E._;
      def <init>() = _
    }
  };
  abstract private[<empty>] trait I extends _root_.java.lang.Object {
    import I._;
    def <init>() = _;
    protected type E = I.E
  }
}

Abstract class:

[[syntax trees at end of                    parser]] // I.java
package <empty> {
  private[<empty>] object I extends  {
    def <init>() = _;
    object E extends  {
      def <init>() = _;
      <stable> <static> val E1: E = _;
      <static> def values(): scala.Array[E] = _;
      <static> def valueOf(x: String): E = _
    };
    <static> class E extends _root_.java.lang.Enum[E] {
      import E._;
      def <init>() = _
    }
  };
  abstract private[<empty>] class I extends _root_.java.lang.Object {
    import I._;
    def <init>() = _
  }
}

@scabug
Copy link
Author

scabug commented Apr 22, 2013

John Sirois (jsirois) said:
Need to spend some time to add a test case - looks like test/files/jvm/nest.* is the right place, but simply adding forwarders for classes and interfaces seems like the right idea, certainly fixes this case:
{code}[jsirois@gill ~/dev/3rdparty/scala] (master *) $ git log -1
commit cde1c93197e85806a743ddbae190f2a78a43014e
Merge: 2e0cef0 47b626e
Author: Jason Zaugg [email protected]
Date: Sun Apr 21 15:04:26 2013 -0700

Merge pull request #2398 from huitseeker/silence_scaladoc_better

Change unrecognized scaladoc comments to C-style

[jsirois@gill ~/dev/3rdparty/scala] (master *) $ git diff
diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
index f1b1d1a..0603be4 100644
--- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
+++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
@@ -732,7 +732,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
}
}
def forwarders(sdef: Tree): List[Tree] = sdef match {

  •    case ClassDef(mods, name, tparams, _) if (parentToken == INTERFACE) =>
    
  •    case ClassDef(mods, name, tparams, _) if (parentToken == INTERFACE || parentToken == CLASS) =>
         val tparams1: List[TypeDef] = tparams map (_.duplicate)
         var rhs: Tree = Select(Ident(parentName.toTermName), name)
         if (!tparams1.isEmpty) rhs = AppliedTypeTree(rhs, tparams1 map (tp => Ident(tp.name)))
    

{code}

@scabug
Copy link
Author

scabug commented Dec 17, 2013

@soc said:
Is this by chance also related to the fact that nested enums are implicitly static?

@som-snytt
Copy link

We have a nice warning when selecting an element that appears to be a non-inherited Java static member.

It should warn if the element name pops up as a static in any of the interfaces selected from.

It doesn't warn for random symbol not found, however.

@SethTisue
Copy link
Member

@som-snytt Thank you for fixing the bug I reported in 2008 (!!!)

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

Successfully merging a pull request may close this issue.

3 participants