From 16ceb373c0ee4970ef1e7fc9b1def41a8f033f20 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Wed, 14 Feb 2024 17:30:25 +0100 Subject: [PATCH 1/7] reproduce the issue [Cherry-picked 3e2a88e7288437a32a1595d1c0a2732002007530] --- tests/run/i19619/InnerClass.java | 67 ++++++++++++++++++++++++ tests/run/i19619/InnerClassGen.java | 80 +++++++++++++++++++++++++++++ tests/run/i19619/RawTypes.java | 18 +++++++ tests/run/i19619/Test.scala | 42 +++++++++++++++ 4 files changed, 207 insertions(+) create mode 100644 tests/run/i19619/InnerClass.java create mode 100644 tests/run/i19619/InnerClassGen.java create mode 100644 tests/run/i19619/RawTypes.java create mode 100644 tests/run/i19619/Test.scala diff --git a/tests/run/i19619/InnerClass.java b/tests/run/i19619/InnerClass.java new file mode 100644 index 000000000000..32bb1642a232 --- /dev/null +++ b/tests/run/i19619/InnerClass.java @@ -0,0 +1,67 @@ +// InnerClass.java + +package lib; + +public class InnerClass { + + public class Inner { + public U innerField; + + public Inner(U innerField) { + this.innerField = innerField; + } + + public U getInnerField() { + return innerField; + } + } + + public class Outer { + + public class Nested { + + public U outerField; + public V innerField; + + public Nested(U outerField, V innerField) { + this.outerField = outerField; + this.innerField = innerField; + } + + public U getOuterField() { + return outerField; + } + + public V getInnerField() { + return innerField; + } + } + } + + public Inner createInner(U innerField) { + return new Inner<>(innerField); + } + + public Outer.Nested createNested(U outerField, V innerField) { + Outer outer = new Outer<>(); + return outer.new Nested<>(outerField, innerField); + } + + public static InnerClass.Inner createInnerStatic(U innerField) { + InnerClass innerClass = new InnerClass(); + return innerClass.new Inner<>(innerField); + } + + public static InnerClass.Outer.Nested createNestedStatic(U outerField, V innerField) { + InnerClass innerClass = new InnerClass(); + InnerClass.Outer outer = innerClass.new Outer<>(); + return outer.new Nested<>(outerField, innerField); + } + + public static void consumeNestedStatic(InnerClass.Outer.Nested nested) { + } + + public static void consumeNestedStatic2(Outer.Nested nested) { + } + +} diff --git a/tests/run/i19619/InnerClassGen.java b/tests/run/i19619/InnerClassGen.java new file mode 100644 index 000000000000..3a691aa0608f --- /dev/null +++ b/tests/run/i19619/InnerClassGen.java @@ -0,0 +1,80 @@ +// InnerClassGen.java + +package lib; + +public class InnerClassGen { + + public class Inner { + public T rootField; + public U innerField; + + public Inner(T rootField, U innerField) { + this.rootField = rootField; + this.innerField = innerField; + } + + public T getRootField() { + return rootField; + } + + public U getInnerField() { + return innerField; + } + } + + public class Outer { + + public class Nested { + public T rootField; + public U outerField; + public V innerField; + + public Nested(T rootField, U outerField, V innerField) { + this.rootField = rootField; + this.outerField = outerField; + this.innerField = innerField; + } + + public T getRootField() { + return rootField; + } + + public U getOuterField() { + return outerField; + } + + public V getInnerField() { + return innerField; + } + } + } + + public static class OuterStatic { + public static class NestedStatic { + } + } + + public Inner createInner(T rootField, U innerField) { + return new Inner<>(rootField, innerField); + } + + public Outer.Nested createNested(T rootField, U outerField, V innerField) { + Outer outer = new Outer<>(); + return outer.new Nested<>(rootField, outerField, innerField); + } + + public static InnerClassGen.Inner createInnerStatic(T rootField, U innerField) { + InnerClassGen innerClassGen = new InnerClassGen<>(); + return innerClassGen.new Inner<>(rootField, innerField); + } + + public static InnerClassGen.Outer.Nested createNestedStatic(T rootField, U outerField, V innerField) { + InnerClassGen innerClassGen = new InnerClassGen<>(); + InnerClassGen.Outer outer = innerClassGen.new Outer<>(); + return outer.new Nested<>(rootField, outerField, innerField); + } + + public static void consumeNestedStatic(InnerClassGen.Outer.Nested nested) { + } + +} diff --git a/tests/run/i19619/RawTypes.java b/tests/run/i19619/RawTypes.java new file mode 100644 index 000000000000..4373a04093eb --- /dev/null +++ b/tests/run/i19619/RawTypes.java @@ -0,0 +1,18 @@ +// RawTypes.java + +package lib; + +public class RawTypes { + + public class C { + public class D { + } + } + + public static void mii_Raw_Raw(RawTypes.C.D d) { + } + + public static void mii_Raw_Raw2(C.D d) { + } + +} diff --git a/tests/run/i19619/Test.scala b/tests/run/i19619/Test.scala new file mode 100644 index 000000000000..7e10950c6cfd --- /dev/null +++ b/tests/run/i19619/Test.scala @@ -0,0 +1,42 @@ +import lib.InnerClass +import lib.InnerClassGen +import lib.RawTypes + +@main def Test = + + locally: + val ici: InnerClass = new InnerClass() + val ici_inner1: ici.Inner[Long] = ici.createInner[Long](47L) // ok, but should error + val ici_inner2: InnerClass#Inner[Long] = ici.createInner[Long](47L) + val ici_inner3: InnerClass#Inner[Long] = InnerClass.createInnerStatic[Long](47L) + + val ici_outer: InnerClass#Outer[Long] = new ici.Outer[Long]() + val ici_nested1: InnerClass#Outer[Long]#Nested[Int] = new ici_outer.Nested[Int](47L, 23) + val ici_nested2: InnerClass#Outer[Long]#Nested[Int] = ici.createNested[Long, Int](47L, 23) + val ici_nested3: InnerClass#Outer[Long]#Nested[Int] = InnerClass.createNestedStatic[Long, Int](47L, 23) + + InnerClass.consumeNestedStatic(ici_nested3) + InnerClass.consumeNestedStatic2(ici_nested3) // error: dotty is inferring static selection when there is no explicit prefix + + locally: + val ici: InnerClassGen[String] = new InnerClassGen() + val ici_inner1: ici.Inner[Long] = ici.createInner[Long]("Hello", 47L) // ok, but should error + val ici_inner2: InnerClassGen[String]#Inner[Long] = ici.createInner[Long]("Hello", 47L) + val ici_inner3: InnerClassGen[String]#Inner[Long] = InnerClassGen.createInnerStatic[String, Long]("Hello", 47L) + + val ici_outer: InnerClassGen[String]#Outer[Long] = new ici.Outer[Long]() + val ici_nested1: InnerClassGen[String]#Outer[Long]#Nested[Int] = new ici_outer.Nested[Int]("Hello", 47L, 23) + val ici_nested2: InnerClassGen[String]#Outer[Long]#Nested[Int] = ici.createNested[Long, Int]("Hello", 47L, 23) + val ici_nested3: InnerClassGen[String]#Outer[Long]#Nested[Int] = InnerClassGen.createNestedStatic[String, Long, Int]("Hello", 47L, 23) + + InnerClassGen.consumeNestedStatic(ici_nested3) + + locally: + val rt: RawTypes = new RawTypes() + val c: RawTypes#C[String] = new rt.C[String]() + + val cd_ii: RawTypes#C[String]#D[String] = new c.D[String]() + val cd_ii_Raw: RawTypes#C[?]#D[?] = cd_ii + + RawTypes.mii_Raw_Raw(cd_ii_Raw) + RawTypes.mii_Raw_Raw2(cd_ii_Raw) // error: dotty is inferring static selection when there is no explicit prefix From 57124048a692f5e911531d57315cd1c0c092a52d Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Fri, 16 Feb 2024 17:36:50 +0100 Subject: [PATCH 2/7] do not look in companion in javaFindMember in typedSelect [Cherry-picked b3501a67402e80cac5a87b7cb90d3d93625ae1db] --- .../src/dotty/tools/dotc/core/ContextOps.scala | 15 ++++++++++++--- .../src/dotty/tools/dotc/typer/TypeAssigner.scala | 5 ++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/ContextOps.scala b/compiler/src/dotty/tools/dotc/core/ContextOps.scala index 920da377f9b4..55fb31fd1916 100644 --- a/compiler/src/dotty/tools/dotc/core/ContextOps.scala +++ b/compiler/src/dotty/tools/dotc/core/ContextOps.scala @@ -34,7 +34,10 @@ object ContextOps: if (elem.name == name) return elem.sym.denot // return self } val pre = ctx.owner.thisType - if ctx.isJava then javaFindMember(name, pre, required, excluded) + if ctx.isJava then + // Note: I didn't verify if there exists a code path that would require `lookInCompanion = true`, + // it is just to preserve the original behavior. + javaFindMember(name, pre, lookInCompanion = true, required, excluded) else pre.findMember(name, pre, required, excluded) } else // we are in the outermost context belonging to a class; self is invisible here. See inClassContext. @@ -43,7 +46,13 @@ object ContextOps: ctx.scope.denotsNamed(name).filterWithFlags(required, excluded).toDenot(NoPrefix) } - final def javaFindMember(name: Name, pre: Type, required: FlagSet = EmptyFlags, excluded: FlagSet = EmptyFlags): Denotation = + /** Look in the prefix with Java semantics. + * @param lookInCompanion If true, try in the companion class of a module as a fallback. + * Note: originally this was used to type Select nodes in Java code, + * but that is no longer the case. + * It is preserved in case it is necessary for denotNamed, but this is unverified. + */ + final def javaFindMember(name: Name, pre: Type, lookInCompanion: Boolean, required: FlagSet = EmptyFlags, excluded: FlagSet = EmptyFlags): Denotation = assert(ctx.isJava) inContext(ctx) { @@ -53,7 +62,7 @@ object ContextOps: val directSearch = pre.findMember(name, pre, required, excluded) // 2. Try to search in companion class if current is an object. - def searchCompanionClass = if preSym.is(Flags.Module) then + def searchCompanionClass = if lookInCompanion && preSym.is(Flags.Module) then preSym.companionClass.thisType.findMember(name, pre, required, excluded) else NoDenotation diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 0896d78c7229..02d8c2f51bf4 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -150,7 +150,10 @@ trait TypeAssigner { val pre = maybeSkolemizePrefix(qualType, name) val mbr = if ctx.isJava then - ctx.javaFindMember(name, pre) + // don't look in the companion class here if qual is a module, + // we use backtracking to instead change the qual to the companion class + // if this fails. + ctx.javaFindMember(name, pre, lookInCompanion = false) else qualType.findMember(name, pre) From 243894121042fe379dac5c4b1321ace69363304b Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Fri, 16 Feb 2024 19:11:21 +0100 Subject: [PATCH 3/7] Widen prefix in findRef of class from Java sources. potential TODO: tree's of Raw types from Java are still incorrect once they are serialized to TASTy, however it is debateable if we care to support them. [Cherry-picked 3ab29995e1571c6f19dea41d47b143f4895a8cac] --- .../tools/dotc/core/SymDenotations.scala | 7 ++ .../src/dotty/tools/dotc/typer/Typer.scala | 4 + .../Yjava-tasty-paths/a/InnerClass.java | 65 +++++++++++++++ .../Yjava-tasty-paths/a/InnerClassGen.java | 78 ++++++++++++++++++ .../Yjava-tasty-paths/a/RawTypes.java | 16 ++++ .../Yjava-tasty-paths/a/package.scala | 2 + .../pipelining/Yjava-tasty-paths/b/Test.scala | 50 ++++++++++++ .../pipelining/Yjava-tasty-paths/build.sbt | 31 +++++++ .../project/DottyInjectedPlugin.scala | 12 +++ sbt-test/pipelining/Yjava-tasty-paths/test | 5 ++ tests/neg/i19619/InnerClass.java | 67 ++++++++++++++++ tests/neg/i19619/InnerClassGen.java | 80 +++++++++++++++++++ tests/neg/i19619/Test.scala | 12 +++ tests/run/i19619/Test.scala | 8 +- 14 files changed, 433 insertions(+), 4 deletions(-) create mode 100644 sbt-test/pipelining/Yjava-tasty-paths/a/InnerClass.java create mode 100644 sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassGen.java create mode 100644 sbt-test/pipelining/Yjava-tasty-paths/a/RawTypes.java create mode 100644 sbt-test/pipelining/Yjava-tasty-paths/a/package.scala create mode 100644 sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala create mode 100644 sbt-test/pipelining/Yjava-tasty-paths/build.sbt create mode 100644 sbt-test/pipelining/Yjava-tasty-paths/project/DottyInjectedPlugin.scala create mode 100644 sbt-test/pipelining/Yjava-tasty-paths/test create mode 100644 tests/neg/i19619/InnerClass.java create mode 100644 tests/neg/i19619/InnerClassGen.java create mode 100644 tests/neg/i19619/Test.scala diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index a8a1be309b0c..d18f88dabfd8 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1501,6 +1501,13 @@ object SymDenotations { def namedType(using Context): NamedType = if (isType) typeRef else termRef + /** Like typeRef, but the prefix is widened. + * + * See tests/neg/i19619/Test.scala + */ + def javaTypeRef(using Context) = + TypeRef(maybeOwner.reachablePrefix.widen, symbol) + /** Like typeRef, but objects in the prefix are represented by their singleton type, * this means we output `pre.O.member` rather than `pre.O$.this.member`. * diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 55adda0505ae..f0be4ac75b9f 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -453,6 +453,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer if (isSelfDenot(defDenot)) curOwner.enclosingClass.thisType else if (ctx.isJava && defDenot.symbol.isStatic) { defDenot.symbol.namedType + } + else if (ctx.isJava && defDenot.symbol.isClass) { + // in a java context a raw identifier to a class should have a widened prefix. + defDenot.symbol.javaTypeRef } else { val effectiveOwner = if (curOwner.isTerm && defDenot.symbol.maybeOwner.isType) diff --git a/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClass.java b/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClass.java new file mode 100644 index 000000000000..c23bc54397dd --- /dev/null +++ b/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClass.java @@ -0,0 +1,65 @@ +package a; + +public class InnerClass { + + public class Inner { + public U innerField; + + public Inner(U innerField) { + this.innerField = innerField; + } + + public U getInnerField() { + return innerField; + } + } + + public class Outer { + + public class Nested { + + public U outerField; + public V innerField; + + public Nested(U outerField, V innerField) { + this.outerField = outerField; + this.innerField = innerField; + } + + public U getOuterField() { + return outerField; + } + + public V getInnerField() { + return innerField; + } + } + } + + public Inner createInner(U innerField) { + return new Inner<>(innerField); + } + + public Outer.Nested createNested(U outerField, V innerField) { + Outer outer = new Outer<>(); + return outer.new Nested<>(outerField, innerField); + } + + public static InnerClass.Inner createInnerStatic(U innerField) { + InnerClass innerClass = new InnerClass(); + return innerClass.new Inner<>(innerField); + } + + public static InnerClass.Outer.Nested createNestedStatic(U outerField, V innerField) { + InnerClass innerClass = new InnerClass(); + InnerClass.Outer outer = innerClass.new Outer<>(); + return outer.new Nested<>(outerField, innerField); + } + + public static void consumeNestedStatic(InnerClass.Outer.Nested nested) { + } + + public static void consumeNestedStatic2(Outer.Nested nested) { + } + +} diff --git a/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassGen.java b/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassGen.java new file mode 100644 index 000000000000..4011cf2fc244 --- /dev/null +++ b/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassGen.java @@ -0,0 +1,78 @@ +package a; + +public class InnerClassGen { + + public class Inner { + public T rootField; + public U innerField; + + public Inner(T rootField, U innerField) { + this.rootField = rootField; + this.innerField = innerField; + } + + public T getRootField() { + return rootField; + } + + public U getInnerField() { + return innerField; + } + } + + public class Outer { + + public class Nested { + public T rootField; + public U outerField; + public V innerField; + + public Nested(T rootField, U outerField, V innerField) { + this.rootField = rootField; + this.outerField = outerField; + this.innerField = innerField; + } + + public T getRootField() { + return rootField; + } + + public U getOuterField() { + return outerField; + } + + public V getInnerField() { + return innerField; + } + } + } + + public static class OuterStatic { + public static class NestedStatic { + } + } + + public Inner createInner(T rootField, U innerField) { + return new Inner<>(rootField, innerField); + } + + public Outer.Nested createNested(T rootField, U outerField, V innerField) { + Outer outer = new Outer<>(); + return outer.new Nested<>(rootField, outerField, innerField); + } + + public static InnerClassGen.Inner createInnerStatic(T rootField, U innerField) { + InnerClassGen innerClassGen = new InnerClassGen<>(); + return innerClassGen.new Inner<>(rootField, innerField); + } + + public static InnerClassGen.Outer.Nested createNestedStatic(T rootField, U outerField, V innerField) { + InnerClassGen innerClassGen = new InnerClassGen<>(); + InnerClassGen.Outer outer = innerClassGen.new Outer<>(); + return outer.new Nested<>(rootField, outerField, innerField); + } + + public static void consumeNestedStatic(InnerClassGen.Outer.Nested nested) { + } + +} diff --git a/sbt-test/pipelining/Yjava-tasty-paths/a/RawTypes.java b/sbt-test/pipelining/Yjava-tasty-paths/a/RawTypes.java new file mode 100644 index 000000000000..4f97c45e7f90 --- /dev/null +++ b/sbt-test/pipelining/Yjava-tasty-paths/a/RawTypes.java @@ -0,0 +1,16 @@ +package a; + +public class RawTypes { + + public class C { + public class D { + } + } + + public static void mii_Raw_Raw(RawTypes.C.D d) { + } + + public static void mii_Raw_Raw2(C.D d) { + } + +} diff --git a/sbt-test/pipelining/Yjava-tasty-paths/a/package.scala b/sbt-test/pipelining/Yjava-tasty-paths/a/package.scala new file mode 100644 index 000000000000..93f99e9892fe --- /dev/null +++ b/sbt-test/pipelining/Yjava-tasty-paths/a/package.scala @@ -0,0 +1,2 @@ +// THIS FILE EXISTS SO THAT `A.java` WILL BE COMPILED BY SCALAC +package a diff --git a/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala b/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala new file mode 100644 index 000000000000..4f555d3b8ac9 --- /dev/null +++ b/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala @@ -0,0 +1,50 @@ +package b + +import a.InnerClass +import a.InnerClassGen +import a.RawTypes + +object B { + @main def test = { + locally { + val ici: InnerClass = new InnerClass() + // val ici_inner1: ici.Inner[Long] = ici.createInner[Long](47L) // error + val ici_inner2: InnerClass#Inner[Long] = ici.createInner[Long](47L) + val ici_inner3: InnerClass#Inner[Long] = InnerClass.createInnerStatic[Long](47L) + + val ici_outer: InnerClass#Outer[Long] = new ici.Outer[Long]() + val ici_nested1: InnerClass#Outer[Long]#Nested[Int] = new ici_outer.Nested[Int](47L, 23) + val ici_nested2: InnerClass#Outer[Long]#Nested[Int] = ici.createNested[Long, Int](47L, 23) + val ici_nested3: InnerClass#Outer[Long]#Nested[Int] = InnerClass.createNestedStatic[Long, Int](47L, 23) + + InnerClass.consumeNestedStatic(ici_nested3) + InnerClass.consumeNestedStatic2(ici_nested3) + } + + locally { + val ici: InnerClassGen[String] = new InnerClassGen() + // val ici_inner1: ici.Inner[Long] = ici.createInner[Long]("Hello", 47L) // error + val ici_inner2: InnerClassGen[String]#Inner[Long] = ici.createInner[Long]("Hello", 47L) + val ici_inner3: InnerClassGen[String]#Inner[Long] = InnerClassGen.createInnerStatic[String, Long]("Hello", 47L) + + val ici_outer: InnerClassGen[String]#Outer[Long] = new ici.Outer[Long]() + val ici_nested1: InnerClassGen[String]#Outer[Long]#Nested[Int] = new ici_outer.Nested[Int]("Hello", 47L, 23) + val ici_nested2: InnerClassGen[String]#Outer[Long]#Nested[Int] = ici.createNested[Long, Int]("Hello", 47L, 23) + val ici_nested3: InnerClassGen[String]#Outer[Long]#Nested[Int] = InnerClassGen.createNestedStatic[String, Long, Int]("Hello", 47L, 23) + + InnerClassGen.consumeNestedStatic(ici_nested3) + } + + locally { + val rt: RawTypes = new RawTypes() + val c: RawTypes#C[String] = new rt.C[String]() + + val cd_ii: RawTypes#C[String]#D[String] = new c.D[String]() + val cd_ii_Raw: RawTypes#C[?]#D[?] = cd_ii + + RawTypes.mii_Raw_Raw(cd_ii_Raw) + // RawTypes.mii_Raw_Raw2(cd_ii_Raw) // error: dotty still doesnt rewrite the tree of a raw type to a type with wildcards + } + } + +} diff --git a/sbt-test/pipelining/Yjava-tasty-paths/build.sbt b/sbt-test/pipelining/Yjava-tasty-paths/build.sbt new file mode 100644 index 000000000000..d63d1f9a3f7e --- /dev/null +++ b/sbt-test/pipelining/Yjava-tasty-paths/build.sbt @@ -0,0 +1,31 @@ +lazy val a = project.in(file("a")) + .settings( + scalacOptions += "-Yjava-tasty", // enable pickling of java signatures + scalacOptions ++= Seq("-Yjava-tasty-output", ((ThisBuild / baseDirectory).value / "a-paths-java-tasty.jar").toString), + scalacOptions += "-Ycheck:all", + Compile / classDirectory := ((ThisBuild / baseDirectory).value / "a-paths-classes"), // send classfiles to a different directory + ) + +lazy val b = project.in(file("b")) + .settings( + Compile / unmanagedClasspath := Seq(Attributed.blank((ThisBuild / baseDirectory).value / "a-paths-java-tasty.jar")), + scalacOptions += "-Ycheck:all", + scalacOptions += "-explain-cyclic", + scalacOptions += "-Ydebug-cyclic", + ) + .settings( + fork := true, // we have to fork the JVM if we actually want to run the code with correct failure semantics + Runtime / unmanagedClasspath += Attributed.blank((ThisBuild / baseDirectory).value / "a-paths-classes"), // make sure the java classes are visible at runtime + ) + +// same as b, but adds the real classes to the classpath instead of the tasty jar +lazy val bAlt = project.in(file("b-alt")) + .settings( + Compile / sources := (b / Compile / sources).value, + Compile / unmanagedClasspath := Seq(Attributed.blank((ThisBuild / baseDirectory).value / "a-paths-classes")), + scalacOptions += "-Ycheck:all", + ) + .settings( + fork := true, // we have to fork the JVM if we actually want to run the code with correct failure semantics + Runtime / unmanagedClasspath += Attributed.blank((ThisBuild / baseDirectory).value / "a-paths-classes"), // make sure the java classes are visible at runtime + ) diff --git a/sbt-test/pipelining/Yjava-tasty-paths/project/DottyInjectedPlugin.scala b/sbt-test/pipelining/Yjava-tasty-paths/project/DottyInjectedPlugin.scala new file mode 100644 index 000000000000..69f15d168bfc --- /dev/null +++ b/sbt-test/pipelining/Yjava-tasty-paths/project/DottyInjectedPlugin.scala @@ -0,0 +1,12 @@ +import sbt._ +import Keys._ + +object DottyInjectedPlugin extends AutoPlugin { + override def requires = plugins.JvmPlugin + override def trigger = allRequirements + + override val projectSettings = Seq( + scalaVersion := sys.props("plugin.scalaVersion"), + scalacOptions += "-source:3.0-migration" + ) +} diff --git a/sbt-test/pipelining/Yjava-tasty-paths/test b/sbt-test/pipelining/Yjava-tasty-paths/test new file mode 100644 index 000000000000..101a1b7cd2f1 --- /dev/null +++ b/sbt-test/pipelining/Yjava-tasty-paths/test @@ -0,0 +1,5 @@ +> a/compile +# test depending on variations of Java paths +> b/run +# double check against the real java classes +> bAlt/run diff --git a/tests/neg/i19619/InnerClass.java b/tests/neg/i19619/InnerClass.java new file mode 100644 index 000000000000..32bb1642a232 --- /dev/null +++ b/tests/neg/i19619/InnerClass.java @@ -0,0 +1,67 @@ +// InnerClass.java + +package lib; + +public class InnerClass { + + public class Inner { + public U innerField; + + public Inner(U innerField) { + this.innerField = innerField; + } + + public U getInnerField() { + return innerField; + } + } + + public class Outer { + + public class Nested { + + public U outerField; + public V innerField; + + public Nested(U outerField, V innerField) { + this.outerField = outerField; + this.innerField = innerField; + } + + public U getOuterField() { + return outerField; + } + + public V getInnerField() { + return innerField; + } + } + } + + public Inner createInner(U innerField) { + return new Inner<>(innerField); + } + + public Outer.Nested createNested(U outerField, V innerField) { + Outer outer = new Outer<>(); + return outer.new Nested<>(outerField, innerField); + } + + public static InnerClass.Inner createInnerStatic(U innerField) { + InnerClass innerClass = new InnerClass(); + return innerClass.new Inner<>(innerField); + } + + public static InnerClass.Outer.Nested createNestedStatic(U outerField, V innerField) { + InnerClass innerClass = new InnerClass(); + InnerClass.Outer outer = innerClass.new Outer<>(); + return outer.new Nested<>(outerField, innerField); + } + + public static void consumeNestedStatic(InnerClass.Outer.Nested nested) { + } + + public static void consumeNestedStatic2(Outer.Nested nested) { + } + +} diff --git a/tests/neg/i19619/InnerClassGen.java b/tests/neg/i19619/InnerClassGen.java new file mode 100644 index 000000000000..3a691aa0608f --- /dev/null +++ b/tests/neg/i19619/InnerClassGen.java @@ -0,0 +1,80 @@ +// InnerClassGen.java + +package lib; + +public class InnerClassGen { + + public class Inner { + public T rootField; + public U innerField; + + public Inner(T rootField, U innerField) { + this.rootField = rootField; + this.innerField = innerField; + } + + public T getRootField() { + return rootField; + } + + public U getInnerField() { + return innerField; + } + } + + public class Outer { + + public class Nested { + public T rootField; + public U outerField; + public V innerField; + + public Nested(T rootField, U outerField, V innerField) { + this.rootField = rootField; + this.outerField = outerField; + this.innerField = innerField; + } + + public T getRootField() { + return rootField; + } + + public U getOuterField() { + return outerField; + } + + public V getInnerField() { + return innerField; + } + } + } + + public static class OuterStatic { + public static class NestedStatic { + } + } + + public Inner createInner(T rootField, U innerField) { + return new Inner<>(rootField, innerField); + } + + public Outer.Nested createNested(T rootField, U outerField, V innerField) { + Outer outer = new Outer<>(); + return outer.new Nested<>(rootField, outerField, innerField); + } + + public static InnerClassGen.Inner createInnerStatic(T rootField, U innerField) { + InnerClassGen innerClassGen = new InnerClassGen<>(); + return innerClassGen.new Inner<>(rootField, innerField); + } + + public static InnerClassGen.Outer.Nested createNestedStatic(T rootField, U outerField, V innerField) { + InnerClassGen innerClassGen = new InnerClassGen<>(); + InnerClassGen.Outer outer = innerClassGen.new Outer<>(); + return outer.new Nested<>(rootField, outerField, innerField); + } + + public static void consumeNestedStatic(InnerClassGen.Outer.Nested nested) { + } + +} diff --git a/tests/neg/i19619/Test.scala b/tests/neg/i19619/Test.scala new file mode 100644 index 000000000000..85f9b3e529ac --- /dev/null +++ b/tests/neg/i19619/Test.scala @@ -0,0 +1,12 @@ +import lib.InnerClass +import lib.InnerClassGen + +@main def Test = + + locally: + val ici: InnerClass = new InnerClass() + val ici_inner1: ici.Inner[Long] = ici.createInner[Long](47L) // error + + locally: + val ici: InnerClassGen[String] = new InnerClassGen() + val ici_inner1: ici.Inner[Long] = ici.createInner[Long]("Hello", 47L) // error diff --git a/tests/run/i19619/Test.scala b/tests/run/i19619/Test.scala index 7e10950c6cfd..5d6f4d11c7a1 100644 --- a/tests/run/i19619/Test.scala +++ b/tests/run/i19619/Test.scala @@ -6,7 +6,7 @@ import lib.RawTypes locally: val ici: InnerClass = new InnerClass() - val ici_inner1: ici.Inner[Long] = ici.createInner[Long](47L) // ok, but should error + // val ici_inner1: ici.Inner[Long] = ici.createInner[Long](47L) // error val ici_inner2: InnerClass#Inner[Long] = ici.createInner[Long](47L) val ici_inner3: InnerClass#Inner[Long] = InnerClass.createInnerStatic[Long](47L) @@ -16,11 +16,11 @@ import lib.RawTypes val ici_nested3: InnerClass#Outer[Long]#Nested[Int] = InnerClass.createNestedStatic[Long, Int](47L, 23) InnerClass.consumeNestedStatic(ici_nested3) - InnerClass.consumeNestedStatic2(ici_nested3) // error: dotty is inferring static selection when there is no explicit prefix + InnerClass.consumeNestedStatic2(ici_nested3) locally: val ici: InnerClassGen[String] = new InnerClassGen() - val ici_inner1: ici.Inner[Long] = ici.createInner[Long]("Hello", 47L) // ok, but should error + // val ici_inner1: ici.Inner[Long] = ici.createInner[Long]("Hello", 47L) // error val ici_inner2: InnerClassGen[String]#Inner[Long] = ici.createInner[Long]("Hello", 47L) val ici_inner3: InnerClassGen[String]#Inner[Long] = InnerClassGen.createInnerStatic[String, Long]("Hello", 47L) @@ -39,4 +39,4 @@ import lib.RawTypes val cd_ii_Raw: RawTypes#C[?]#D[?] = cd_ii RawTypes.mii_Raw_Raw(cd_ii_Raw) - RawTypes.mii_Raw_Raw2(cd_ii_Raw) // error: dotty is inferring static selection when there is no explicit prefix + RawTypes.mii_Raw_Raw2(cd_ii_Raw) From 29dee5278e8bf651d535dbd511e413fdf3cd086a Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Mon, 1 Jul 2024 23:48:18 +0200 Subject: [PATCH 4/7] also cook the tree of a java raw type [Cherry-picked e8e295afe3bf1d0452ecf0a515346c5986f33da7][modified] --- .../src/dotty/tools/dotc/typer/Typer.scala | 18 ++++++++++-------- .../pipelining/Yjava-tasty-paths/b/Test.scala | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index f0be4ac75b9f..43e5d52d397a 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -4214,14 +4214,16 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer val tree1 = if ((pt eq AnyTypeConstructorProto) || tp.typeParamSymbols.isEmpty) tree else { - val tp1 = - if (ctx.isJava) - // Cook raw type - AppliedType(tree.tpe, tp.typeParams.map(Function.const(TypeBounds.empty))) - else - // Eta-expand higher-kinded type - tree.tpe.EtaExpand(tp.typeParamSymbols) - tree.withType(tp1) + if (ctx.isJava) + // Cook raw type + val typeArgs = tp.typeParams.map(Function.const(TypeBounds.empty)) + val tree1 = AppliedTypeTree(tree, typeArgs.map(TypeTree(_))) + val tp1 = AppliedType(tree.tpe, typeArgs) + tree1.withType(tp1) + else + // Eta-expand higher-kinded type + val tp1 = tree.tpe.EtaExpand(tp.typeParamSymbols) + tree.withType(tp1) } if (ctx.mode.is(Mode.Pattern) || ctx.mode.is(Mode.QuotedPattern) || tree1.tpe <:< pt) tree1 else err.typeMismatch(tree1, pt) diff --git a/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala b/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala index 4f555d3b8ac9..084469e76d8b 100644 --- a/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala +++ b/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala @@ -43,7 +43,7 @@ object B { val cd_ii_Raw: RawTypes#C[?]#D[?] = cd_ii RawTypes.mii_Raw_Raw(cd_ii_Raw) - // RawTypes.mii_Raw_Raw2(cd_ii_Raw) // error: dotty still doesnt rewrite the tree of a raw type to a type with wildcards + RawTypes.mii_Raw_Raw2(cd_ii_Raw) } } From 9d3d2f3dde361df50fed09e679b6d753d8d5ff12 Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Wed, 21 Feb 2024 18:02:42 +0100 Subject: [PATCH 5/7] In Java sources, allow a non-stable prefix for a class parent. (If we widen Foo.this.Inner in the parents of a class to AbstractFoo#Inner, i.e. an inherited class Inner prefixed by its owner abstract class AbstractFoo, this is not considered a stable prefix for a class parent type. But in Java this is the correct type so allow it.) [Cherry-picked d37857c1e1a921c865a285a377aa52d52d9152d5] --- .../src/dotty/tools/dotc/typer/Namer.scala | 12 +++-- .../Yjava-tasty-paths/a/InnerClassSub.java | 52 ++++++++++++++++++ .../pipelining/Yjava-tasty-paths/b/Test.scala | 18 +++++++ tests/run/i19619/InnerClassSub.java | 54 +++++++++++++++++++ tests/run/i19619/Test.scala | 17 ++++++ 5 files changed, 149 insertions(+), 4 deletions(-) create mode 100644 sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassSub.java create mode 100644 tests/run/i19619/InnerClassSub.java diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 9e4768922ad3..e9b00cf95cac 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -1539,17 +1539,19 @@ class Namer { typer: Typer => end parentType /** Check parent type tree `parent` for the following well-formedness conditions: - * (1) It must be a class type with a stable prefix (@see checkClassTypeWithStablePrefix) + * (1) It must be a class type with a stable prefix (unless `isJava`) (@see checkClassTypeWithStablePrefix) * (2) If may not derive from itself * (3) The class is not final * (4) If the class is sealed, it is defined in the same compilation unit as the current class + * + * @param isJava If true, the parent type is in Java mode, and we do not require a stable prefix */ - def checkedParentType(parent: untpd.Tree): Type = { + def checkedParentType(parent: untpd.Tree, isJava: Boolean): Type = { val ptype = parentType(parent)(using completerCtx.superCallContext).dealiasKeepAnnots if (cls.isRefinementClass) ptype else { val pt = checkClassType(ptype, parent.srcPos, - traitReq = parent ne parents.head, stablePrefixReq = true) + traitReq = parent ne parents.head, stablePrefixReq = !isJava) if (pt.derivesFrom(cls)) { val addendum = parent match { case Select(qual: Super, _) if Feature.migrateTo3 => @@ -1618,7 +1620,9 @@ class Namer { typer: Typer => val parentTypes = defn.adjustForTuple(cls, cls.typeParams, defn.adjustForBoxedUnit(cls, addUsingTraits( - ensureFirstIsClass(cls, parents.map(checkedParentType(_))) + locally: + val isJava = ctx.isJava + ensureFirstIsClass(cls, parents.map(checkedParentType(_, isJava))) ) ) ) diff --git a/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassSub.java b/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassSub.java new file mode 100644 index 000000000000..6441d71a4b20 --- /dev/null +++ b/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassSub.java @@ -0,0 +1,52 @@ +package a; + +public class InnerClassSub extends InnerClass { + + public class InnerSub extends Inner { + public InnerSub(U innerField) { + super(innerField); + } + } + + public class OuterSub extends Outer { + public OuterSub() { + super(); + } + } + + public Inner createInnerSub(U innerField) { + return new InnerSub<>(innerField); + } + + public Outer.Nested createNestedSub(U outerField, V innerField) { + OuterSub outer = new OuterSub<>(); + return outer.new Nested<>(outerField, innerField); + } + + public InnerClass.Inner createInnerSub2(U innerField) { + return new InnerSub<>(innerField); + } + + public InnerClass.Outer.Nested createNestedSub2(U outerField, V innerField) { + OuterSub outer = new OuterSub<>(); + return outer.new Nested<>(outerField, innerField); + } + + public static InnerClass.Inner createInnerStatic(U innerField) { + InnerClassSub innerClass = new InnerClassSub(); + return innerClass.new Inner<>(innerField); + } + + public static InnerClass.Outer.Nested createNestedStatic(U outerField, V innerField) { + InnerClassSub innerClass = new InnerClassSub(); + InnerClassSub.Outer outer = innerClass.new Outer<>(); + return outer.new Nested<>(outerField, innerField); + } + + public static void consumeNestedStatic(InnerClass.Outer.Nested nested) { + } + + public static void consumeNestedStatic2(Outer.Nested nested) { + } + +} diff --git a/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala b/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala index 084469e76d8b..bad55e361aa7 100644 --- a/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala +++ b/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala @@ -3,6 +3,7 @@ package b import a.InnerClass import a.InnerClassGen import a.RawTypes +import a.InnerClassSub object B { @main def test = { @@ -45,6 +46,23 @@ object B { RawTypes.mii_Raw_Raw(cd_ii_Raw) RawTypes.mii_Raw_Raw2(cd_ii_Raw) } + + locally { + val ici: InnerClassSub = new InnerClassSub() + // val ici_inner1: ici.Inner[Long] = ici.createInner[Long](47L) // error + val ici_inner2: InnerClass#Inner[Long] = ici.createInnerSub[Long](47L) + val ici_inner2_2: InnerClass#Inner[Long] = ici.createInnerSub2[Long](47L) + val ici_inner3: InnerClass#Inner[Long] = InnerClassSub.createInnerStatic[Long](47L) + + val ici_outer: InnerClassSub#Outer[Long] = new ici.Outer[Long]() + val ici_nested1: InnerClassSub#Outer[Long]#Nested[Int] = new ici_outer.Nested[Int](47L, 23) + val ici_nested2: InnerClass#Outer[Long]#Nested[Int] = ici.createNestedSub[Long, Int](47L, 23) + val ici_nested2_2: InnerClass#Outer[Long]#Nested[Int] = ici.createNestedSub2[Long, Int](47L, 23) + val ici_nested3: InnerClass#Outer[Long]#Nested[Int] = InnerClassSub.createNestedStatic[Long, Int](47L, 23) + + InnerClass.consumeNestedStatic(ici_nested3) + InnerClass.consumeNestedStatic2(ici_nested3) + } } } diff --git a/tests/run/i19619/InnerClassSub.java b/tests/run/i19619/InnerClassSub.java new file mode 100644 index 000000000000..5a1d1f4d3857 --- /dev/null +++ b/tests/run/i19619/InnerClassSub.java @@ -0,0 +1,54 @@ +// InnerClass.java + +package lib; + +public class InnerClassSub extends InnerClass { + + public class InnerSub extends Inner { + public InnerSub(U innerField) { + super(innerField); + } + } + + public class OuterSub extends Outer { + public OuterSub() { + super(); + } + } + + public Inner createInnerSub(U innerField) { + return new InnerSub<>(innerField); + } + + public Outer.Nested createNestedSub(U outerField, V innerField) { + OuterSub outer = new OuterSub<>(); + return outer.new Nested<>(outerField, innerField); + } + + public InnerClass.Inner createInnerSub2(U innerField) { + return new InnerSub<>(innerField); + } + + public InnerClass.Outer.Nested createNestedSub2(U outerField, V innerField) { + OuterSub outer = new OuterSub<>(); + return outer.new Nested<>(outerField, innerField); + } + + public static InnerClass.Inner createInnerStatic(U innerField) { + InnerClassSub innerClass = new InnerClassSub(); + return innerClass.new Inner<>(innerField); + } + + public static InnerClass.Outer.Nested createNestedStatic(U outerField, V innerField) { + InnerClassSub innerClass = new InnerClassSub(); + InnerClassSub.Outer outer = innerClass.new Outer<>(); + return outer.new Nested<>(outerField, innerField); + } + + public static void consumeNestedStatic(InnerClass.Outer.Nested nested) { + } + + public static void consumeNestedStatic2(Outer.Nested nested) { + } + +} diff --git a/tests/run/i19619/Test.scala b/tests/run/i19619/Test.scala index 5d6f4d11c7a1..8e8def4994db 100644 --- a/tests/run/i19619/Test.scala +++ b/tests/run/i19619/Test.scala @@ -1,6 +1,7 @@ import lib.InnerClass import lib.InnerClassGen import lib.RawTypes +import lib.InnerClassSub @main def Test = @@ -40,3 +41,19 @@ import lib.RawTypes RawTypes.mii_Raw_Raw(cd_ii_Raw) RawTypes.mii_Raw_Raw2(cd_ii_Raw) + + locally: + val ici: InnerClassSub = new InnerClassSub() + // val ici_inner1: ici.Inner[Long] = ici.createInner[Long](47L) // error + val ici_inner2: InnerClass#Inner[Long] = ici.createInnerSub[Long](47L) + val ici_inner2_2: InnerClass#Inner[Long] = ici.createInnerSub2[Long](47L) + val ici_inner3: InnerClass#Inner[Long] = InnerClassSub.createInnerStatic[Long](47L) + + val ici_outer: InnerClassSub#Outer[Long] = new ici.Outer[Long]() + val ici_nested1: InnerClassSub#Outer[Long]#Nested[Int] = new ici_outer.Nested[Int](47L, 23) + val ici_nested2: InnerClass#Outer[Long]#Nested[Int] = ici.createNestedSub[Long, Int](47L, 23) + val ici_nested2_2: InnerClass#Outer[Long]#Nested[Int] = ici.createNestedSub2[Long, Int](47L, 23) + val ici_nested3: InnerClass#Outer[Long]#Nested[Int] = InnerClassSub.createNestedStatic[Long, Int](47L, 23) + + InnerClass.consumeNestedStatic(ici_nested3) + InnerClass.consumeNestedStatic2(ici_nested3) From 543325a38e295ba56007caefdf7a74cb93dbbb3d Mon Sep 17 00:00:00 2001 From: Jamie Thompson Date: Thu, 22 Feb 2024 14:30:58 +0100 Subject: [PATCH 6/7] skip test on scala-js [Cherry-picked faf8547ecd0cdf4c50d7b789e8fba22c6b6efde3] --- tests/run/i19619/Test.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/run/i19619/Test.scala b/tests/run/i19619/Test.scala index 8e8def4994db..871e7a490ea0 100644 --- a/tests/run/i19619/Test.scala +++ b/tests/run/i19619/Test.scala @@ -1,3 +1,5 @@ +// scalajs: --skip + import lib.InnerClass import lib.InnerClassGen import lib.RawTypes From 5f7f0e4827e4fe62c3cba89f49b54693122eeef3 Mon Sep 17 00:00:00 2001 From: Wojciech Mazur Date: Mon, 1 Jul 2024 23:58:57 +0200 Subject: [PATCH 7/7] Remove not-applicable sbt-test/pipelining from LTS --- .../Yjava-tasty-paths/a/InnerClass.java | 65 ---------------- .../Yjava-tasty-paths/a/InnerClassGen.java | 78 ------------------- .../Yjava-tasty-paths/a/InnerClassSub.java | 52 ------------- .../Yjava-tasty-paths/a/RawTypes.java | 16 ---- .../Yjava-tasty-paths/a/package.scala | 2 - .../pipelining/Yjava-tasty-paths/b/Test.scala | 68 ---------------- .../pipelining/Yjava-tasty-paths/build.sbt | 31 -------- .../project/DottyInjectedPlugin.scala | 12 --- sbt-test/pipelining/Yjava-tasty-paths/test | 5 -- 9 files changed, 329 deletions(-) delete mode 100644 sbt-test/pipelining/Yjava-tasty-paths/a/InnerClass.java delete mode 100644 sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassGen.java delete mode 100644 sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassSub.java delete mode 100644 sbt-test/pipelining/Yjava-tasty-paths/a/RawTypes.java delete mode 100644 sbt-test/pipelining/Yjava-tasty-paths/a/package.scala delete mode 100644 sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala delete mode 100644 sbt-test/pipelining/Yjava-tasty-paths/build.sbt delete mode 100644 sbt-test/pipelining/Yjava-tasty-paths/project/DottyInjectedPlugin.scala delete mode 100644 sbt-test/pipelining/Yjava-tasty-paths/test diff --git a/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClass.java b/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClass.java deleted file mode 100644 index c23bc54397dd..000000000000 --- a/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClass.java +++ /dev/null @@ -1,65 +0,0 @@ -package a; - -public class InnerClass { - - public class Inner { - public U innerField; - - public Inner(U innerField) { - this.innerField = innerField; - } - - public U getInnerField() { - return innerField; - } - } - - public class Outer { - - public class Nested { - - public U outerField; - public V innerField; - - public Nested(U outerField, V innerField) { - this.outerField = outerField; - this.innerField = innerField; - } - - public U getOuterField() { - return outerField; - } - - public V getInnerField() { - return innerField; - } - } - } - - public Inner createInner(U innerField) { - return new Inner<>(innerField); - } - - public Outer.Nested createNested(U outerField, V innerField) { - Outer outer = new Outer<>(); - return outer.new Nested<>(outerField, innerField); - } - - public static InnerClass.Inner createInnerStatic(U innerField) { - InnerClass innerClass = new InnerClass(); - return innerClass.new Inner<>(innerField); - } - - public static InnerClass.Outer.Nested createNestedStatic(U outerField, V innerField) { - InnerClass innerClass = new InnerClass(); - InnerClass.Outer outer = innerClass.new Outer<>(); - return outer.new Nested<>(outerField, innerField); - } - - public static void consumeNestedStatic(InnerClass.Outer.Nested nested) { - } - - public static void consumeNestedStatic2(Outer.Nested nested) { - } - -} diff --git a/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassGen.java b/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassGen.java deleted file mode 100644 index 4011cf2fc244..000000000000 --- a/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassGen.java +++ /dev/null @@ -1,78 +0,0 @@ -package a; - -public class InnerClassGen { - - public class Inner { - public T rootField; - public U innerField; - - public Inner(T rootField, U innerField) { - this.rootField = rootField; - this.innerField = innerField; - } - - public T getRootField() { - return rootField; - } - - public U getInnerField() { - return innerField; - } - } - - public class Outer { - - public class Nested { - public T rootField; - public U outerField; - public V innerField; - - public Nested(T rootField, U outerField, V innerField) { - this.rootField = rootField; - this.outerField = outerField; - this.innerField = innerField; - } - - public T getRootField() { - return rootField; - } - - public U getOuterField() { - return outerField; - } - - public V getInnerField() { - return innerField; - } - } - } - - public static class OuterStatic { - public static class NestedStatic { - } - } - - public Inner createInner(T rootField, U innerField) { - return new Inner<>(rootField, innerField); - } - - public Outer.Nested createNested(T rootField, U outerField, V innerField) { - Outer outer = new Outer<>(); - return outer.new Nested<>(rootField, outerField, innerField); - } - - public static InnerClassGen.Inner createInnerStatic(T rootField, U innerField) { - InnerClassGen innerClassGen = new InnerClassGen<>(); - return innerClassGen.new Inner<>(rootField, innerField); - } - - public static InnerClassGen.Outer.Nested createNestedStatic(T rootField, U outerField, V innerField) { - InnerClassGen innerClassGen = new InnerClassGen<>(); - InnerClassGen.Outer outer = innerClassGen.new Outer<>(); - return outer.new Nested<>(rootField, outerField, innerField); - } - - public static void consumeNestedStatic(InnerClassGen.Outer.Nested nested) { - } - -} diff --git a/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassSub.java b/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassSub.java deleted file mode 100644 index 6441d71a4b20..000000000000 --- a/sbt-test/pipelining/Yjava-tasty-paths/a/InnerClassSub.java +++ /dev/null @@ -1,52 +0,0 @@ -package a; - -public class InnerClassSub extends InnerClass { - - public class InnerSub extends Inner { - public InnerSub(U innerField) { - super(innerField); - } - } - - public class OuterSub extends Outer { - public OuterSub() { - super(); - } - } - - public Inner createInnerSub(U innerField) { - return new InnerSub<>(innerField); - } - - public Outer.Nested createNestedSub(U outerField, V innerField) { - OuterSub outer = new OuterSub<>(); - return outer.new Nested<>(outerField, innerField); - } - - public InnerClass.Inner createInnerSub2(U innerField) { - return new InnerSub<>(innerField); - } - - public InnerClass.Outer.Nested createNestedSub2(U outerField, V innerField) { - OuterSub outer = new OuterSub<>(); - return outer.new Nested<>(outerField, innerField); - } - - public static InnerClass.Inner createInnerStatic(U innerField) { - InnerClassSub innerClass = new InnerClassSub(); - return innerClass.new Inner<>(innerField); - } - - public static InnerClass.Outer.Nested createNestedStatic(U outerField, V innerField) { - InnerClassSub innerClass = new InnerClassSub(); - InnerClassSub.Outer outer = innerClass.new Outer<>(); - return outer.new Nested<>(outerField, innerField); - } - - public static void consumeNestedStatic(InnerClass.Outer.Nested nested) { - } - - public static void consumeNestedStatic2(Outer.Nested nested) { - } - -} diff --git a/sbt-test/pipelining/Yjava-tasty-paths/a/RawTypes.java b/sbt-test/pipelining/Yjava-tasty-paths/a/RawTypes.java deleted file mode 100644 index 4f97c45e7f90..000000000000 --- a/sbt-test/pipelining/Yjava-tasty-paths/a/RawTypes.java +++ /dev/null @@ -1,16 +0,0 @@ -package a; - -public class RawTypes { - - public class C { - public class D { - } - } - - public static void mii_Raw_Raw(RawTypes.C.D d) { - } - - public static void mii_Raw_Raw2(C.D d) { - } - -} diff --git a/sbt-test/pipelining/Yjava-tasty-paths/a/package.scala b/sbt-test/pipelining/Yjava-tasty-paths/a/package.scala deleted file mode 100644 index 93f99e9892fe..000000000000 --- a/sbt-test/pipelining/Yjava-tasty-paths/a/package.scala +++ /dev/null @@ -1,2 +0,0 @@ -// THIS FILE EXISTS SO THAT `A.java` WILL BE COMPILED BY SCALAC -package a diff --git a/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala b/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala deleted file mode 100644 index bad55e361aa7..000000000000 --- a/sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala +++ /dev/null @@ -1,68 +0,0 @@ -package b - -import a.InnerClass -import a.InnerClassGen -import a.RawTypes -import a.InnerClassSub - -object B { - @main def test = { - locally { - val ici: InnerClass = new InnerClass() - // val ici_inner1: ici.Inner[Long] = ici.createInner[Long](47L) // error - val ici_inner2: InnerClass#Inner[Long] = ici.createInner[Long](47L) - val ici_inner3: InnerClass#Inner[Long] = InnerClass.createInnerStatic[Long](47L) - - val ici_outer: InnerClass#Outer[Long] = new ici.Outer[Long]() - val ici_nested1: InnerClass#Outer[Long]#Nested[Int] = new ici_outer.Nested[Int](47L, 23) - val ici_nested2: InnerClass#Outer[Long]#Nested[Int] = ici.createNested[Long, Int](47L, 23) - val ici_nested3: InnerClass#Outer[Long]#Nested[Int] = InnerClass.createNestedStatic[Long, Int](47L, 23) - - InnerClass.consumeNestedStatic(ici_nested3) - InnerClass.consumeNestedStatic2(ici_nested3) - } - - locally { - val ici: InnerClassGen[String] = new InnerClassGen() - // val ici_inner1: ici.Inner[Long] = ici.createInner[Long]("Hello", 47L) // error - val ici_inner2: InnerClassGen[String]#Inner[Long] = ici.createInner[Long]("Hello", 47L) - val ici_inner3: InnerClassGen[String]#Inner[Long] = InnerClassGen.createInnerStatic[String, Long]("Hello", 47L) - - val ici_outer: InnerClassGen[String]#Outer[Long] = new ici.Outer[Long]() - val ici_nested1: InnerClassGen[String]#Outer[Long]#Nested[Int] = new ici_outer.Nested[Int]("Hello", 47L, 23) - val ici_nested2: InnerClassGen[String]#Outer[Long]#Nested[Int] = ici.createNested[Long, Int]("Hello", 47L, 23) - val ici_nested3: InnerClassGen[String]#Outer[Long]#Nested[Int] = InnerClassGen.createNestedStatic[String, Long, Int]("Hello", 47L, 23) - - InnerClassGen.consumeNestedStatic(ici_nested3) - } - - locally { - val rt: RawTypes = new RawTypes() - val c: RawTypes#C[String] = new rt.C[String]() - - val cd_ii: RawTypes#C[String]#D[String] = new c.D[String]() - val cd_ii_Raw: RawTypes#C[?]#D[?] = cd_ii - - RawTypes.mii_Raw_Raw(cd_ii_Raw) - RawTypes.mii_Raw_Raw2(cd_ii_Raw) - } - - locally { - val ici: InnerClassSub = new InnerClassSub() - // val ici_inner1: ici.Inner[Long] = ici.createInner[Long](47L) // error - val ici_inner2: InnerClass#Inner[Long] = ici.createInnerSub[Long](47L) - val ici_inner2_2: InnerClass#Inner[Long] = ici.createInnerSub2[Long](47L) - val ici_inner3: InnerClass#Inner[Long] = InnerClassSub.createInnerStatic[Long](47L) - - val ici_outer: InnerClassSub#Outer[Long] = new ici.Outer[Long]() - val ici_nested1: InnerClassSub#Outer[Long]#Nested[Int] = new ici_outer.Nested[Int](47L, 23) - val ici_nested2: InnerClass#Outer[Long]#Nested[Int] = ici.createNestedSub[Long, Int](47L, 23) - val ici_nested2_2: InnerClass#Outer[Long]#Nested[Int] = ici.createNestedSub2[Long, Int](47L, 23) - val ici_nested3: InnerClass#Outer[Long]#Nested[Int] = InnerClassSub.createNestedStatic[Long, Int](47L, 23) - - InnerClass.consumeNestedStatic(ici_nested3) - InnerClass.consumeNestedStatic2(ici_nested3) - } - } - -} diff --git a/sbt-test/pipelining/Yjava-tasty-paths/build.sbt b/sbt-test/pipelining/Yjava-tasty-paths/build.sbt deleted file mode 100644 index d63d1f9a3f7e..000000000000 --- a/sbt-test/pipelining/Yjava-tasty-paths/build.sbt +++ /dev/null @@ -1,31 +0,0 @@ -lazy val a = project.in(file("a")) - .settings( - scalacOptions += "-Yjava-tasty", // enable pickling of java signatures - scalacOptions ++= Seq("-Yjava-tasty-output", ((ThisBuild / baseDirectory).value / "a-paths-java-tasty.jar").toString), - scalacOptions += "-Ycheck:all", - Compile / classDirectory := ((ThisBuild / baseDirectory).value / "a-paths-classes"), // send classfiles to a different directory - ) - -lazy val b = project.in(file("b")) - .settings( - Compile / unmanagedClasspath := Seq(Attributed.blank((ThisBuild / baseDirectory).value / "a-paths-java-tasty.jar")), - scalacOptions += "-Ycheck:all", - scalacOptions += "-explain-cyclic", - scalacOptions += "-Ydebug-cyclic", - ) - .settings( - fork := true, // we have to fork the JVM if we actually want to run the code with correct failure semantics - Runtime / unmanagedClasspath += Attributed.blank((ThisBuild / baseDirectory).value / "a-paths-classes"), // make sure the java classes are visible at runtime - ) - -// same as b, but adds the real classes to the classpath instead of the tasty jar -lazy val bAlt = project.in(file("b-alt")) - .settings( - Compile / sources := (b / Compile / sources).value, - Compile / unmanagedClasspath := Seq(Attributed.blank((ThisBuild / baseDirectory).value / "a-paths-classes")), - scalacOptions += "-Ycheck:all", - ) - .settings( - fork := true, // we have to fork the JVM if we actually want to run the code with correct failure semantics - Runtime / unmanagedClasspath += Attributed.blank((ThisBuild / baseDirectory).value / "a-paths-classes"), // make sure the java classes are visible at runtime - ) diff --git a/sbt-test/pipelining/Yjava-tasty-paths/project/DottyInjectedPlugin.scala b/sbt-test/pipelining/Yjava-tasty-paths/project/DottyInjectedPlugin.scala deleted file mode 100644 index 69f15d168bfc..000000000000 --- a/sbt-test/pipelining/Yjava-tasty-paths/project/DottyInjectedPlugin.scala +++ /dev/null @@ -1,12 +0,0 @@ -import sbt._ -import Keys._ - -object DottyInjectedPlugin extends AutoPlugin { - override def requires = plugins.JvmPlugin - override def trigger = allRequirements - - override val projectSettings = Seq( - scalaVersion := sys.props("plugin.scalaVersion"), - scalacOptions += "-source:3.0-migration" - ) -} diff --git a/sbt-test/pipelining/Yjava-tasty-paths/test b/sbt-test/pipelining/Yjava-tasty-paths/test deleted file mode 100644 index 101a1b7cd2f1..000000000000 --- a/sbt-test/pipelining/Yjava-tasty-paths/test +++ /dev/null @@ -1,5 +0,0 @@ -> a/compile -# test depending on variations of Java paths -> b/run -# double check against the real java classes -> bAlt/run