Skip to content

Commit d7a9d09

Browse files
bishaboshaWojciechMazur
authored andcommitted
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 d37857c]
1 parent 9316033 commit d7a9d09

File tree

5 files changed

+149
-4
lines changed

5 files changed

+149
-4
lines changed

compiler/src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,17 +1539,19 @@ class Namer { typer: Typer =>
15391539
end parentType
15401540

15411541
/** Check parent type tree `parent` for the following well-formedness conditions:
1542-
* (1) It must be a class type with a stable prefix (@see checkClassTypeWithStablePrefix)
1542+
* (1) It must be a class type with a stable prefix (unless `isJava`) (@see checkClassTypeWithStablePrefix)
15431543
* (2) If may not derive from itself
15441544
* (3) The class is not final
15451545
* (4) If the class is sealed, it is defined in the same compilation unit as the current class
1546+
*
1547+
* @param isJava If true, the parent type is in Java mode, and we do not require a stable prefix
15461548
*/
1547-
def checkedParentType(parent: untpd.Tree): Type = {
1549+
def checkedParentType(parent: untpd.Tree, isJava: Boolean): Type = {
15481550
val ptype = parentType(parent)(using completerCtx.superCallContext).dealiasKeepAnnots
15491551
if (cls.isRefinementClass) ptype
15501552
else {
15511553
val pt = checkClassType(ptype, parent.srcPos,
1552-
traitReq = parent ne parents.head, stablePrefixReq = true)
1554+
traitReq = parent ne parents.head, stablePrefixReq = !isJava)
15531555
if (pt.derivesFrom(cls)) {
15541556
val addendum = parent match {
15551557
case Select(qual: Super, _) if Feature.migrateTo3 =>
@@ -1618,7 +1620,9 @@ class Namer { typer: Typer =>
16181620
val parentTypes = defn.adjustForTuple(cls, cls.typeParams,
16191621
defn.adjustForBoxedUnit(cls,
16201622
addUsingTraits(
1621-
ensureFirstIsClass(cls, parents.map(checkedParentType(_)))
1623+
locally:
1624+
val isJava = ctx.isJava
1625+
ensureFirstIsClass(cls, parents.map(checkedParentType(_, isJava)))
16221626
)
16231627
)
16241628
)
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package a;
2+
3+
public class InnerClassSub extends InnerClass {
4+
5+
public class InnerSub<U> extends Inner<U> {
6+
public InnerSub(U innerField) {
7+
super(innerField);
8+
}
9+
}
10+
11+
public class OuterSub<U> extends Outer<U> {
12+
public OuterSub() {
13+
super();
14+
}
15+
}
16+
17+
public <U> Inner<U> createInnerSub(U innerField) {
18+
return new InnerSub<>(innerField);
19+
}
20+
21+
public <U, V> Outer<U>.Nested<V> createNestedSub(U outerField, V innerField) {
22+
OuterSub<U> outer = new OuterSub<>();
23+
return outer.new Nested<>(outerField, innerField);
24+
}
25+
26+
public <U> InnerClass.Inner<U> createInnerSub2(U innerField) {
27+
return new InnerSub<>(innerField);
28+
}
29+
30+
public <U, V> InnerClass.Outer<U>.Nested<V> createNestedSub2(U outerField, V innerField) {
31+
OuterSub<U> outer = new OuterSub<>();
32+
return outer.new Nested<>(outerField, innerField);
33+
}
34+
35+
public static <U> InnerClass.Inner<U> createInnerStatic(U innerField) {
36+
InnerClassSub innerClass = new InnerClassSub();
37+
return innerClass.new Inner<>(innerField);
38+
}
39+
40+
public static <U, V> InnerClass.Outer<U>.Nested<V> createNestedStatic(U outerField, V innerField) {
41+
InnerClassSub innerClass = new InnerClassSub();
42+
InnerClassSub.Outer<U> outer = innerClass.new Outer<>();
43+
return outer.new Nested<>(outerField, innerField);
44+
}
45+
46+
public static <U, V> void consumeNestedStatic(InnerClass.Outer<U>.Nested<V> nested) {
47+
}
48+
49+
public static <U, V> void consumeNestedStatic2(Outer<U>.Nested<V> nested) {
50+
}
51+
52+
}

sbt-test/pipelining/Yjava-tasty-paths/b/Test.scala

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package b
33
import a.InnerClass
44
import a.InnerClassGen
55
import a.RawTypes
6+
import a.InnerClassSub
67

78
object B {
89
@main def test = {
@@ -45,6 +46,23 @@ object B {
4546
RawTypes.mii_Raw_Raw(cd_ii_Raw)
4647
RawTypes.mii_Raw_Raw2(cd_ii_Raw)
4748
}
49+
50+
locally {
51+
val ici: InnerClassSub = new InnerClassSub()
52+
// val ici_inner1: ici.Inner[Long] = ici.createInner[Long](47L) // error
53+
val ici_inner2: InnerClass#Inner[Long] = ici.createInnerSub[Long](47L)
54+
val ici_inner2_2: InnerClass#Inner[Long] = ici.createInnerSub2[Long](47L)
55+
val ici_inner3: InnerClass#Inner[Long] = InnerClassSub.createInnerStatic[Long](47L)
56+
57+
val ici_outer: InnerClassSub#Outer[Long] = new ici.Outer[Long]()
58+
val ici_nested1: InnerClassSub#Outer[Long]#Nested[Int] = new ici_outer.Nested[Int](47L, 23)
59+
val ici_nested2: InnerClass#Outer[Long]#Nested[Int] = ici.createNestedSub[Long, Int](47L, 23)
60+
val ici_nested2_2: InnerClass#Outer[Long]#Nested[Int] = ici.createNestedSub2[Long, Int](47L, 23)
61+
val ici_nested3: InnerClass#Outer[Long]#Nested[Int] = InnerClassSub.createNestedStatic[Long, Int](47L, 23)
62+
63+
InnerClass.consumeNestedStatic(ici_nested3)
64+
InnerClass.consumeNestedStatic2(ici_nested3)
65+
}
4866
}
4967

5068
}

tests/run/i19619/InnerClassSub.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// InnerClass.java
2+
3+
package lib;
4+
5+
public class InnerClassSub extends InnerClass {
6+
7+
public class InnerSub<U> extends Inner<U> {
8+
public InnerSub(U innerField) {
9+
super(innerField);
10+
}
11+
}
12+
13+
public class OuterSub<U> extends Outer<U> {
14+
public OuterSub() {
15+
super();
16+
}
17+
}
18+
19+
public <U> Inner<U> createInnerSub(U innerField) {
20+
return new InnerSub<>(innerField);
21+
}
22+
23+
public <U, V> Outer<U>.Nested<V> createNestedSub(U outerField, V innerField) {
24+
OuterSub<U> outer = new OuterSub<>();
25+
return outer.new Nested<>(outerField, innerField);
26+
}
27+
28+
public <U> InnerClass.Inner<U> createInnerSub2(U innerField) {
29+
return new InnerSub<>(innerField);
30+
}
31+
32+
public <U, V> InnerClass.Outer<U>.Nested<V> createNestedSub2(U outerField, V innerField) {
33+
OuterSub<U> outer = new OuterSub<>();
34+
return outer.new Nested<>(outerField, innerField);
35+
}
36+
37+
public static <U> InnerClass.Inner<U> createInnerStatic(U innerField) {
38+
InnerClassSub innerClass = new InnerClassSub();
39+
return innerClass.new Inner<>(innerField);
40+
}
41+
42+
public static <U, V> InnerClass.Outer<U>.Nested<V> createNestedStatic(U outerField, V innerField) {
43+
InnerClassSub innerClass = new InnerClassSub();
44+
InnerClassSub.Outer<U> outer = innerClass.new Outer<>();
45+
return outer.new Nested<>(outerField, innerField);
46+
}
47+
48+
public static <U, V> void consumeNestedStatic(InnerClass.Outer<U>.Nested<V> nested) {
49+
}
50+
51+
public static <U, V> void consumeNestedStatic2(Outer<U>.Nested<V> nested) {
52+
}
53+
54+
}

tests/run/i19619/Test.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import lib.InnerClass
22
import lib.InnerClassGen
33
import lib.RawTypes
4+
import lib.InnerClassSub
45

56
@main def Test =
67

@@ -40,3 +41,19 @@ import lib.RawTypes
4041

4142
RawTypes.mii_Raw_Raw(cd_ii_Raw)
4243
RawTypes.mii_Raw_Raw2(cd_ii_Raw)
44+
45+
locally:
46+
val ici: InnerClassSub = new InnerClassSub()
47+
// val ici_inner1: ici.Inner[Long] = ici.createInner[Long](47L) // error
48+
val ici_inner2: InnerClass#Inner[Long] = ici.createInnerSub[Long](47L)
49+
val ici_inner2_2: InnerClass#Inner[Long] = ici.createInnerSub2[Long](47L)
50+
val ici_inner3: InnerClass#Inner[Long] = InnerClassSub.createInnerStatic[Long](47L)
51+
52+
val ici_outer: InnerClassSub#Outer[Long] = new ici.Outer[Long]()
53+
val ici_nested1: InnerClassSub#Outer[Long]#Nested[Int] = new ici_outer.Nested[Int](47L, 23)
54+
val ici_nested2: InnerClass#Outer[Long]#Nested[Int] = ici.createNestedSub[Long, Int](47L, 23)
55+
val ici_nested2_2: InnerClass#Outer[Long]#Nested[Int] = ici.createNestedSub2[Long, Int](47L, 23)
56+
val ici_nested3: InnerClass#Outer[Long]#Nested[Int] = InnerClassSub.createNestedStatic[Long, Int](47L, 23)
57+
58+
InnerClass.consumeNestedStatic(ici_nested3)
59+
InnerClass.consumeNestedStatic2(ici_nested3)

0 commit comments

Comments
 (0)