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

Kotlin interop: reporting wrong type for inner classes appearing in Kotlin method types #12086

Closed
jbwheatley opened this issue Apr 13, 2021 · 35 comments · Fixed by #14426
Closed
Assignees
Milestone

Comments

@jbwheatley
Copy link

Compiler version

3.0.0-RC2

Minimized code

I'm working with a library that is written in kotlin, and running into a compilation error on 3.0.0-RC2 that doesn't happen on 2.13.5. The decompiled .class file looks like:

public abstract class VerificationResult {
  public static final class Ok extends VerificationResult {...}
  public static final class Failed extends VerificationResult {...}
  ...
}

and then there is a method on another class like:

public void displayFailures(@NotNull List<Failed> failures)

I then get this compiler error when calling the method:

Output

[error] 16 |            verifier.displayFailures(List(failed).asJava)
[error]    |                                     ^^^^^^^^^^^^^^^^^^^
[error]    |Found:    java.util.List[au.com.dius.pact.provider.VerificationResult.Failed]
[error]    |Required: java.util.List[au.com.dius.pact.provider.VerificationResult$Failed]

Expectation

Should compile.

@smarter
Copy link
Member

smarter commented Apr 13, 2021

We need a way (ideally minimized) to reproduce the problem, otherwise there's not much we can do about it.

@jbwheatley
Copy link
Author

jbwheatley commented Apr 13, 2021

Foo.java as:

package foo;
import foo.Foo.Bar1;
import java.util.List;

public abstract class Foo {
    public static final class Bar1 extends Foo {}
    public static final class Bar2 extends Foo {}
}

class Baz {
    public void bars(List<Bar1> bs) {
        bs.clear();
    }
}

FooScala.scala as:

package foo
import Foo._
import scala.jdk.CollectionConverters._

object FooScala {
  def doThings(foo: Foo): Unit =
    foo match {
      case b: Foo.Bar1 => new Baz().bars(List(b).asJava)
      case _: Foo.Bar2 => ()
    }
}

will recreate the issue

@smarter
Copy link
Member

smarter commented Apr 13, 2021

Thank you for the minimization, I just tried it but I can't reproduce the issue (the code compiles fine), can you list the steps you use to reproduce the problem and the version of javac you have?

@jbwheatley
Copy link
Author

Running sbt +compile at my project route. sbt is using java 14.0.1, presumably that is the issue?

@smarter
Copy link
Member

smarter commented Apr 13, 2021

I don't have java 14 here, but I can't reproduce with either java 8 or 15 locally, could you try using a different version?

@jbwheatley
Copy link
Author

oh I'm an idiot, I was getting my errors all mixed up (sorry, end of the day here in UK). My minimized example isn't causing the error for me 🤦 I'm stuck for a way to reproduce this for you besides having you try it with the library I am using

@smarter
Copy link
Member

smarter commented Apr 13, 2021

I know that feeling :). if you can minimize it to a scala file that depends on a publicly available library that would be useful already.

@jbwheatley
Copy link
Author

Finally got something for you! 😁 https://scastie.scala-lang.org/e4TAeoEISaeDFNE4HqbrnQ

@smarter
Copy link
Member

smarter commented Apr 13, 2021

Thank you! This can be reproduced using coursier with:

scalac -classpath "$(cs fetch -p au.com.dius.pact:provider:4.2.0)" Test.scala

@prolativ You've worked on inner classes recently, so you might be able to figure out what's going on here

@smarter smarter added compat:java stat:needs minimization Needs a self contained minimization and removed stat:needs info labels Apr 13, 2021
@griggt
Copy link
Contributor

griggt commented Apr 13, 2021

Minimized:

Result.kt

sealed class Result {
  class Failed : Result()
}

class Verifier {
  fun displayFailure(failure: Result.Failed) {}
}

Test.scala

object Test {
  def foo(verifier: Verifier, failed: Result.Failed): Unit =
    verifier.displayFailure(failed)
}
$ kotlinc -version
info: kotlinc-jvm 1.4.31 (JRE 1.8.0_282-b08)

$ dotc -version
Scala compiler version 3.0.0-RC2 -- Copyright 2002-2021, LAMP/EPFL

$ kotlinc Result.kt && dotc Test.scala
Result.kt:6:22: warning: parameter 'failure' is never used
  fun displayFailure(failure: Result.Failed) {}
                     ^
-- [E007] Type Mismatch Error: Test.scala:3:28 ------------------------------------------
3 |    verifier.displayFailure(failed)
  |                            ^^^^^^
  |                            Found:    (failed : Result.Failed)
  |                            Required: Result$Failed

I tried translating the Kotlin to Java but was unable to reproduce the issue, compilation was successful.

@griggt griggt removed the stat:needs minimization Needs a self contained minimization label Apr 13, 2021
@smarter
Copy link
Member

smarter commented Apr 13, 2021

Very interesting, could you paste the output of javap -p -v Result.class for both the kotlin and java version?

@smarter
Copy link
Member

smarter commented Apr 13, 2021

@lrytz are you aware of any special handling of inner classes in kotlin that required changes in scalac?

@griggt
Copy link
Contributor

griggt commented Apr 13, 2021

Kotlin Result.class

Classfile /src/dotty-issues/i12086/standalone/kt/Result.class
  Last modified Apr 13, 2021; size 740 bytes
  MD5 checksum f7bfd03cae50ec69aa999d753ed05c8f
  Compiled from "Result.kt"
public abstract class Result
  minor version: 0
  major version: 50
  flags: ACC_PUBLIC, ACC_SUPER, ACC_ABSTRACT
Constant pool:
   #1 = Utf8               Result
   #2 = Class              #1             // Result
   #3 = Utf8               java/lang/Object
   #4 = Class              #3             // java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = NameAndType        #5:#6          // "<init>":()V
   #8 = Methodref          #4.#7          // java/lang/Object."<init>":()V
   #9 = Utf8               this
  #10 = Utf8               LResult;
  #11 = Utf8               (Lkotlin/jvm/internal/DefaultConstructorMarker;)V
  #12 = Methodref          #2.#7          // Result."<init>":()V
  #13 = Utf8               $constructor_marker
  #14 = Utf8               Lkotlin/jvm/internal/DefaultConstructorMarker;
  #15 = Utf8               Lkotlin/Metadata;
  #16 = Utf8               mv
  #17 = Integer            1
  #18 = Integer            4
  #19 = Integer            2
  #20 = Utf8               bv
  #21 = Integer            0
  #22 = Integer            3
  #23 = Utf8               k
  #24 = Utf8               d1
  #25 = Utf8               
  #26 = Utf8               d2
  #27 = Utf8
  #28 = Utf8               Failed
  #29 = Utf8               LResult$Failed;
  #30 = Utf8               Result$Failed
  #31 = Class              #30            // Result$Failed
  #32 = Utf8               Result.kt
  #33 = Utf8               Code
  #34 = Utf8               LineNumberTable
  #35 = Utf8               LocalVariableTable
  #36 = Utf8               InnerClasses
  #37 = Utf8               SourceFile
  #38 = Utf8               RuntimeVisibleAnnotations
{
  private Result();
    descriptor: ()V
    flags: ACC_PRIVATE
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #8                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 1: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   LResult;

  public Result(kotlin.jvm.internal.DefaultConstructorMarker);
    descriptor: (Lkotlin/jvm/internal/DefaultConstructorMarker;)V
    flags: ACC_PUBLIC, ACC_SYNTHETIC
    Code:
      stack=1, locals=2, args_size=2
         0: aload_0
         1: invokespecial #12                 // Method "<init>":()V
         4: return
      LineNumberTable:
        line 1: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   LResult;
            0       5     1 $constructor_marker   Lkotlin/jvm/internal/DefaultConstructorMarker;
}
InnerClasses:
     public static final #28= #31 of #2; //Failed=class Result$Failed of class Result
SourceFile: "Result.kt"
RuntimeVisibleAnnotations:
  0: #15(#16=[I#17,I#18,I#19],#20=[I#17,I#21,I#22],#23=I#17,#24=[s#25],#26=[s#10,s#27,s#6,s#28,s#29])           

#25 in the constant pool contained a bunch of unprintable characters which GitHub did not allow me to paste, here is a hexdump if it's relevant:

00000000  20 20 23 32 35 20 3d 20  55 74 66 38 20 20 20 20  |  #25 = Utf8    |
00000010  20 20 20 20 20 20 20 20  20 20 20 00 10 5c 6e 02  |           ..\n.|
00000020  18 02 5c 6e 02 10 00 5c  6e 02 08 02 5c 6e 02 18  |..\n...\n...\n..|
00000030  02 08 36 18 00 32 02 30  01 3a 01 03 42 07 08 02  |..6..2.0.:..B...|
00000040  c2 a2 06 02 10 02 c2 82  01 01 04 0a              |............|

Java Result.class

Classfile /src/dotty-issues/i12086/standalone/Result.class
  Last modified Apr 13, 2021; size 245 bytes
  MD5 checksum d2bc7d517566b8a0795d50cdf4ebbb44
  Compiled from "Result.java"
public abstract class Result
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER, ACC_ABSTRACT
Constant pool:
   #1 = Methodref          #3.#13         // java/lang/Object."<init>":()V
   #2 = Class              #14            // Result
   #3 = Class              #15            // java/lang/Object
   #4 = Class              #16            // Result$Failed
   #5 = Utf8               Failed
   #6 = Utf8               InnerClasses
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               SourceFile
  #12 = Utf8               Result.java
  #13 = NameAndType        #7:#8          // "<init>":()V
  #14 = Utf8               Result
  #15 = Utf8               java/lang/Object
  #16 = Utf8               Result$Failed
{
  public Result();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 1: 0
}
SourceFile: "Result.java"
InnerClasses:
     public static final #5= #4 of #2; //Failed=class Result$Failed of class Result

which was compiled from

public abstract class Result {
    public static final class Failed extends Result {}
}

by javac 1.8.0_282.

@smarter
Copy link
Member

smarter commented Apr 13, 2021

Hmm that looks identical, could you do the same for Result$Failed.class ?

@griggt
Copy link
Contributor

griggt commented Apr 13, 2021

Kotlin Result$Failed.class

Classfile /src/dotty-issues/i12086/standalone/kt/Result$Failed.class
  Last modified Apr 13, 2021; size 549 bytes
  MD5 checksum 9434210661057601cc960cebc40beb0e
  Compiled from "Result.kt"
public final class Result$Failed extends Result
  minor version: 0
  major version: 50
  flags: ACC_PUBLIC, ACC_FINAL, ACC_SUPER
Constant pool:
   #1 = Utf8               Result$Failed
   #2 = Class              #1             // Result$Failed
   #3 = Utf8               Result
   #4 = Class              #3             // Result
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Utf8               (Lkotlin/jvm/internal/DefaultConstructorMarker;)V
   #8 = NameAndType        #5:#7          // "<init>":(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
   #9 = Methodref          #4.#8          // Result."<init>":(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
  #10 = Utf8               this
  #11 = Utf8               LResult$Failed;
  #12 = Utf8               Lkotlin/Metadata;
  #13 = Utf8               mv
  #14 = Integer            1
  #15 = Integer            4
  #16 = Integer            2
  #17 = Utf8               bv
  #18 = Integer            0
  #19 = Integer            3
  #20 = Utf8               k
  #21 = Utf8               d1
  #22 = Utf8               
  #23 = Utf8               d2
  #24 = Utf8               LResult;
  #25 = Utf8               Failed
  #26 = Utf8               Result.kt
  #27 = Utf8               Code
  #28 = Utf8               LineNumberTable
  #29 = Utf8               LocalVariableTable
  #30 = Utf8               InnerClasses
  #31 = Utf8               SourceFile
  #32 = Utf8               RuntimeVisibleAnnotations
{
  public Result$Failed();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: aconst_null
         2: invokespecial #9                  // Method Result."<init>":(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
         5: return
      LineNumberTable:
        line 2: 0
        line 2: 2
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       6     0  this   LResult$Failed;
}
InnerClasses:
     public static final #25= #2 of #4; //Failed=class Result$Failed of class Result
SourceFile: "Result.kt"
RuntimeVisibleAnnotations:
  0: #12(#13=[I#14,I#15,I#16],#17=[I#14,I#18,I#19],#20=I#14,#21=[s#22],#23=[s#11,s#24,s#6])

More unprintable chars at #22

Java Result$Failed.class

Classfile /src/dotty-issues/i12086/standalone/Result$Failed.class
  Last modified Apr 13, 2021; size 223 bytes
  MD5 checksum ae33459e26326b921d56fd116fd641eb
  Compiled from "Result.java"
public final class Result$Failed extends Result
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_FINAL, ACC_SUPER
Constant pool:
   #1 = Methodref          #3.#10         // Result."<init>":()V
   #2 = Class              #11            // Result$Failed
   #3 = Class              #14            // Result
   #4 = Utf8               <init>
   #5 = Utf8               ()V
   #6 = Utf8               Code
   #7 = Utf8               LineNumberTable
   #8 = Utf8               SourceFile
   #9 = Utf8               Result.java
  #10 = NameAndType        #4:#5          // "<init>":()V
  #11 = Utf8               Result$Failed
  #12 = Utf8               Failed
  #13 = Utf8               InnerClasses
  #14 = Utf8               Result
{
  public Result$Failed();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method Result."<init>":()V
         4: return
      LineNumberTable:
        line 2: 0
}
SourceFile: "Result.java"
InnerClasses:
     public static final #12= #2 of #3; //Failed=class Result$Failed of class Result

@smarter
Copy link
Member

smarter commented Apr 13, 2021

Oh wait, the issue is probably in the Verifier class, I just found https://youtrack.jetbrains.com/issue/KT-27936 which indicates that kotlin isn't writing InnerClasses attributes for types that it references. So if I'm correct we need to figure out how Scala 2 bypasses the need for this (I guess it assumes everything with a $ in it is an inner class?)

@smarter
Copy link
Member

smarter commented Apr 13, 2021

Found it: scala/scala#5822

@griggt
Copy link
Contributor

griggt commented Apr 13, 2021

Yes, the Java version of Verifier.class has

InnerClasses:
     public static final #10= #9 of #18; //Failed=class Result$Failed of class Result

which is missing from the Kotlin version.

@smarter smarter changed the title Java interop: reporting wrong type for nested java classes Kotlin interop: reporting wrong type for nested java classes Apr 15, 2021
@smarter smarter changed the title Kotlin interop: reporting wrong type for nested java classes Kotlin interop: reporting wrong type for inner classes appearing in Kotlin method types Apr 15, 2021
@jbwheatley
Copy link
Author

hi, is there any update on this? I can't cross-build my library to scala 3 without it 🙁

@bbarker
Copy link
Contributor

bbarker commented Oct 1, 2021

Hi @Kordyjan - I just confirmed this is still an issue in recent versions of Scala and Kotlin (3.0.2 and 1.5.30 respectively). This is a bit out of my depth but if you are bogged down I can take a crack at it, since the relevant fix in Scala 2 has already been pointed out, any pointers on where to start in the dotty codebase would probably be a big help.

@smarter
Copy link
Member

smarter commented Oct 1, 2021

Thanks for stepping up!

@bbarker
Copy link
Contributor

bbarker commented Oct 2, 2021

@smarter thanks! One question regarding tests for this: as there are currently neither any .kt or .class files in the dotty source tree, it seems including either would set a new precedent, and for the former, the build would have to be altered to include a kotlin compiler just for this test. What seems a good approach?

@smarter
Copy link
Member

smarter commented Oct 2, 2021

If you look at the scala 2 pr, it doesn't add any kt or class file, instead it adds java files that mimic the behavior of kotlin.

@bbarker
Copy link
Contributor

bbarker commented Oct 13, 2021

One question regarding the test classes, in the Scala file we have:

val c = new C
assert(Test_2.acceptD(Test_1.mD(new c.D)) == 2)

But, Test_1.mD would somehow be allowed to take an instance of the "C.D" class defined in Test_2.java - it seems like there should be some sort of namespace collision issue between the C$D defined in the two Test_*.java files. Currently dotty emits an error, as others have seen, though this passes in Scala 2:

5 |    assert(Test_2.acceptD(Test_1.mD(new c.D)) == 2)
  |                                    ^^^^^^^
  |                                    Found:    c.D
  |                                    Required: C$D

If we instead change the argument from new c.D to new C$D, presumably referencing the class defined in Test_1.java, we get a slightly different error with dotty, indicating that the acceptD functions at least can tell they have been passed the wrong type:

4 |    assert(Test_2.acceptD(Test_1.mD(new C$D)) == 2)
  |                          ^^^^^^^^^^^^^^^^^^
  |                          Found:    C$D
  |                          Required: C#D

So my current major point of confusion, which may not be very related to the issue at hand, is just how Test_1.mD can seemingly accept values of two different classes; this probably comes down to my not understanding something about namespace collision or class loading.

@smarter
Copy link
Member

smarter commented Oct 13, 2021

is just how Test_1.mD can seemingly accept values of two different classes

If I'm understanding things correctly, it doesn't: in Scala 3 currently it only accepts the toplevel class C$D, whereas in Scala 2 it will only accept the class D defined in class C, because of the special casing added in ClassfileParser which changes how the class name C$D is resolved into a symbol.

@bbarker
Copy link
Contributor

bbarker commented Oct 14, 2021

In Scala 2.13.5, perplexingly I seem to get the same error as in dotty:

$ scalac --version
Scala compiler version 2.13.5 -- Copyright 2002-2020, LAMP/EPFL and Lightbend, Inc.
bbarker@beb82dell0-DevContainer:~/workspace/dotty/tests/pos/i12086
$ scalac Test_3.scala Test_*.java
Test_3.scala:7: error: type mismatch;
 found   : c.D
 required: C$D
     assert(Test_2.acceptD(Test_1.mD(new c.D)) == 2)
                                     ^
Test_3.scala:8: error: type mismatch;
 found   : C.E
 required: C$E
     assert(Test_2.acceptE(Test_1.mE(new C.E)) == 2)
                                     ^
Test_3.scala:9: error: type mismatch;
 found   : C.F.G
 required: C$F$G
     assert(Test_2.acceptG(Test_1.mG(new C.F.G)) == 2)
                                     ^
 3 errors

But, this is in the run tests directory for Scala 2, so i assume I've compiled this incorreclty

@smarter
Copy link
Member

smarter commented Oct 14, 2021

The _X suffixes are used for separate compilation, so Test_1 should be compiled with javac, then Test_2 with a separate call to javac, then Test_3 should be compiled by scalac with the result of the previous steps on the classpath. This is what the test framework does.

@bbarker
Copy link
Contributor

bbarker commented Oct 15, 2021

Thanks! baby steps 👶

I added a bit of logging to try to understand the situation in the dotty code a bit better:

  def debugPrint(name: Name, info: String): Unit =
    if (name.toString == "C" || name.toString == "D" || name.toString == "C.D" || name.toString == "C$D" || name.toString == "c.D" ) {
      System.err.println(info)
    }
  /** Return the class symbol of the given name. */
  def classNameToSymbol(name: Name)(using Context): Symbol = innerClasses.get(name.toString) match {
    case Some(entry) =>
      debugPrint(name, s"classNameToSymbol (with inner) name=$name has symbol ${innerClasses.classSymbol(entry)}")
      innerClasses.classSymbol(entry)
    case None =>
      debugPrint(name, s"classNameToSymbol (no inner) name=$name has symbol ${requiredClass(name)}")
      requiredClass(name)
  }

For the line assert(Test_2.acceptD(Test_1.mD(new c.D)) == 2) in Test_3.scala, this results in:

classNameToSymbol (no inner) name=C has symbol class C
classNameToSymbol (with inner) name=C$D has symbol class D
classNameToSymbol (no inner) name=C has symbol class C
classNameToSymbol (no inner) name=C$D has symbol class C$D
classNameToSymbol (no inner) name=C$D has symbol class C$D
classNameToSymbol (no inner) name=C has symbol class C

So if I understand right, the two lines:

classNameToSymbol (no inner) name=C$D has symbol class C$D
classNameToSymbol (no inner) name=C$D has symbol class C$D

should actually be reading

classNameToSymbol (no inner) name=C$D has symbol class C.D
classNameToSymbol (no inner) name=C$D has symbol class C.D

?

Thanks again

@bbarker
Copy link
Contributor

bbarker commented Oct 15, 2021

Ooops, no, I think it should actually be this:

Current:

classNameToSymbol (with inner) name=C$D has symbol class D

Desired:

classNameToSymbol (with inner) name=C$D has symbol class C.D

@smarter
Copy link
Member

smarter commented Oct 15, 2021

The toString on a class will print just the class name regardless of where it's defined, so it'll be "class D", not "class C.D", and it's the one whose currently interpreted as "class C$D" that needs to be seen as D inside C instead.

@bbarker
Copy link
Contributor

bbarker commented Oct 17, 2021

OK, getting a bit better grasp on this but wanted to check on my planned approach for manipulating the Name:

  1. Work with Strings directly as in the Scala 2 code (Name.toString)
  2. Convert the split strings into SimpleNames using def termName(s: String): SimpleName
  3. Map these back into the original name using something like (Name.mapParts).

@smarter
Copy link
Member

smarter commented Oct 17, 2021

I don't think you need to use mapParts, you can directly go from a String to a Name via toTypeName.

@bbarker
Copy link
Contributor

bbarker commented Oct 30, 2021

I have a branch with a couple of commits. The first commit attempted to demonstrate a very basic fix for the specific case of C$D; the second commit attempted to do things the right way (more or less) and port over the logic from Scala 2, but there are still some problems.

Primarily, on the following line, if I remove the requiredClass call and instead use what is commented, the compiler seems to break badly.

 case _ => requiredClass(localizedName).copy(owner = owner) // instanceScope.lookup(innerName)

As it is, there are still errors for some of the more heavily nested cases:

classNameToSymbol (no inner) name=C has symbol class C and loc=class C
classNameToSymbol (with inner) name=C$D has symbol class D and loc=class D in class C
classNameToSymbol (no inner) name=C$D has symbol class D and loc=class D in class C
classNameToSymbol (no inner) name=C$D has symbol class D and loc=class D in class C
classNameToSymbol (no inner) name=C has symbol class C and loc=class C
Bad symbolic reference. A signature
refers to D/T in package C which is not available.
It may be completely missing from the current classpath, or the version on
the classpath might be incompatible with the version used when compiling the signature.
Bad symbolic reference. A signature
refers to D/T in package C which is not available.
It may be completely missing from the current classpath, or the version on
the classpath might be incompatible with the version used when compiling the signature.
classNameToSymbol (no inner) name=C has symbol class C and loc=class C
-- [E007] Type Mismatch Error: tests/run/i12086/Test_3.scala:5:36 ------------------------------------------------------
5 |    assert(Test_2.acceptE(Test_1.mE(new C.E)) == 2)
  |                                    ^^^^^^^
  |                                    Found:    C.E
  |                                    Required: C#E?
  |
  |                                    where:    E  is a class in object C
  |                                              E? is a class in class C
Bad symbolic reference. A signature
refers to E/T in package C which is not available.
It may be completely missing from the current classpath, or the version on
the classpath might be incompatible with the version used when compiling the signature.
Bad symbolic reference. A signature
refers to E/T in package C which is not available.
It may be completely missing from the current classpath, or the version on
the classpath might be incompatible with the version used when compiling the signature.
classNameToSymbol (no inner) name=C has symbol class C and loc=class C
-- [E007] Type Mismatch Error: tests/run/i12086/Test_3.scala:6:36 ------------------------------------------------------
6 |    assert(Test_2.acceptG(Test_1.mG(new C.F.G)) == 2)
  |                                    ^^^^^^^^^
  |                                    Found:    C.F.G
  |                                    Required: C$F#G?
  |
  |                                    where:    G  is a class in object F
  |                                              G? is a class in class C$F

smarter added a commit to dotty-staging/dotty that referenced this issue Feb 7, 2022
This is a port of scala/scala#5822 which works
around a bug in Kotlin (https://youtrack.jetbrains.com/issue/KT-27936).

Fixes scala#12086.

Co-Authored-By: Lukas Rytz <lukas.rytz@gmail.com>
Co-Authored-By: Brandon Barker <beb82@cornell.edu>
smarter added a commit to dotty-staging/dotty that referenced this issue Feb 7, 2022
This is a port of scala/scala#5822 which works
around a bug in Kotlin (https://youtrack.jetbrains.com/issue/KT-27936).

Fixes scala#12086.

Co-Authored-By: Lukas Rytz <lukas.rytz@gmail.com>
Co-Authored-By: Brandon Barker <beb82@cornell.edu>
@smarter
Copy link
Member

smarter commented Feb 7, 2022

I've opened a PR which fixes this at #14426 based on the initial work by @bbarker, thanks a lot for the help!

@bbarker
Copy link
Contributor

bbarker commented Mar 4, 2022

Thank you @smarter !

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.

6 participants