Skip to content

Commit 0fbacf7

Browse files
author
changvvb
committed
Migrate scala2 PR-7671
1 parent 515cb9f commit 0fbacf7

File tree

16 files changed

+187
-4
lines changed

16 files changed

+187
-4
lines changed

compiler/src/dotty/tools/dotc/core/ContextOps.scala

+40-3
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ package dotty.tools.dotc
22
package core
33

44
import Contexts._, Symbols._, Types._, Flags._, Scopes._, Decorators._, NameOps._
5-
import Denotations._
6-
import SymDenotations.LazyType, Names.Name, StdNames.nme
5+
import Denotations._, SymDenotations._
6+
import Names.Name, StdNames.nme
77
import ast.untpd
88

99
/** Extension methods for contexts where we want to keep the ctx.<methodName> syntax */
@@ -34,14 +34,51 @@ object ContextOps:
3434
if (elem.name == name) return elem.sym.denot // return self
3535
}
3636
val pre = ctx.owner.thisType
37-
pre.findMember(name, pre, required, excluded)
37+
if ctx.isJava then javaFindMember(name, pre, required, excluded)
38+
else pre.findMember(name, pre, required, excluded)
3839
}
3940
else // we are in the outermost context belonging to a class; self is invisible here. See inClassContext.
4041
ctx.owner.findMember(name, ctx.owner.thisType, required, excluded)
4142
else
4243
ctx.scope.denotsNamed(name).filterWithFlags(required, excluded).toDenot(NoPrefix)
4344
}
4445

46+
final def javaFindMember(name: Name, pre: Type, required: FlagSet = EmptyFlags, excluded: FlagSet = EmptyFlags): Denotation =
47+
assert(ctx.isJava)
48+
inContext(ctx) {
49+
50+
val preSym = pre.typeSymbol
51+
52+
// 1. Try to search in current type and parents
53+
val directSearch = pre.findMember(name, pre, required, excluded)
54+
55+
// 2. Try to search in companion class if current is an object
56+
def searchCompanionClass = if preSym.is(Flags.Module) then
57+
preSym.companionClass.thisType.findMember(name, pre, required, excluded)
58+
else NoDenotation
59+
60+
// 3. Try to search in companion objects of super classes.
61+
// In Java code, static inner classes, which we model as members of the companion object,
62+
// can be referenced from an ident in a subclass or by a selection prefixed by the subclass.
63+
def searchSuperCompanionObjects =
64+
val toSearch = if preSym.is(Flags.Module) then
65+
if preSym.companionClass.exists then
66+
preSym.companionClass.asClass.baseClasses
67+
else Nil
68+
else
69+
preSym.asClass.baseClasses
70+
71+
toSearch.iterator.map { bc =>
72+
val pre1 = bc.thisType.typeSymbol.companionClass.thisType
73+
pre1.findMember(name, pre1, required, excluded)
74+
}.find(_.exists).getOrElse(NoDenotation)
75+
76+
if preSym.isClass then
77+
directSearch orElse searchCompanionClass orElse searchSuperCompanionObjects
78+
else
79+
directSearch
80+
}
81+
4582
/** A fresh local context with given tree and owner.
4683
* Owner might not exist (can happen for self valdefs), in which case
4784
* no owner is set in result context

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

+6-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,12 @@ trait TypeAssigner {
145145
// this is exactly what Erasure will do.
146146
case _ =>
147147
val pre = maybeSkolemizePrefix(qualType, name)
148-
val mbr = qualType.findMember(name, pre)
148+
val mbr =
149+
if ctx.isJava && pre.typeSymbol.isClass then
150+
ctx.javaFindMember(name, pre)
151+
else
152+
qualType.findMember(name, pre)
153+
149154
if reallyExists(mbr) then qualType.select(name, mbr)
150155
else if qualType.isErroneous || name.toTermName == nme.ERROR then UnspecifiedErrorType
151156
else NoType

compiler/test/dotc/pos-test-pickling.blacklist

+1
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,4 @@ i2797a
6666
# GADT cast applied to singleton type difference
6767
i4176-gadt.scala
6868

69+
java-inherited-type1

compiler/test/dotc/run-test-pickling.blacklist

+2
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,5 @@ varargs-abstract
3535
zero-arity-case-class.scala
3636
i12194.scala
3737
i12753
38+
t6138
39+
t6138-2
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
object Client {
2+
def test= {
3+
Test.Outer.Nested.sig
4+
Test.Outer.Nested.sig1
5+
Test.Outer.Nested.sig2
6+
val o = new Test.Outer
7+
new o.Nested1().sig
8+
new o.Nested1().sig1
9+
new o.Nested1().sig2
10+
}
11+
12+
def test1 = {
13+
val t = new Test
14+
val o = new t.Outer1
15+
new o.Nested1().sig
16+
new o.Nested1().sig1
17+
new o.Nested1().sig2
18+
}
19+
}
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
public class Test {
2+
static class OuterBase implements OuterBaseInterface {
3+
static class StaticInner {}
4+
class Inner {}
5+
}
6+
interface OuterBaseInterface {
7+
interface InnerFromInterface {}
8+
}
9+
public static class Outer extends OuterBase {
10+
public static class Nested {
11+
public static P<StaticInner, Inner, InnerFromInterface> sig; // was: "type StaticInner", "not found: type Inner", "not found: type InnerFromInterface"
12+
public static P<Outer.StaticInner, Outer.Inner, Outer.InnerFromInterface> sig1; // was: "type StaticInner is not a member of Test.Outer"
13+
public static P<OuterBase.StaticInner, OuterBase.Inner, OuterBaseInterface.InnerFromInterface> sig2;
14+
15+
}
16+
public class Nested1 {
17+
public P<StaticInner, Inner, InnerFromInterface> sig; // was: "not found: type StaticInner"
18+
public P<Outer.StaticInner, Outer.Inner, Outer.InnerFromInterface> sig1; // was: "type StaticInner is not a member of Test.Outer"
19+
public P<OuterBase.StaticInner, OuterBase.Inner, OuterBaseInterface.InnerFromInterface> sig2;
20+
}
21+
}
22+
public class Outer1 extends OuterBase {
23+
public class Nested1 {
24+
public P<StaticInner, Inner, InnerFromInterface> sig; // was: "not found: type StaticInner"
25+
public P<Outer.StaticInner, Outer.Inner, Outer.InnerFromInterface> sig1; // was: "type StaticInner is not a member of Test.Outer"
26+
public P<OuterBase.StaticInner, OuterBase.Inner, OuterBaseInterface.InnerFromInterface> sig2;
27+
}
28+
}
29+
public static class P<A, B, C>{}
30+
}

tests/pos/java-inherited-type1/J.java

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class J extends S {
2+
// These references all work in Javac because `object O { class I }` erases to `O$I`
3+
4+
void select1(S1.Inner1 i) { new S1.Inner1(); }
5+
void ident(Inner i) {}
6+
7+
void ident1(Inner1 i) {}
8+
void select(S.Inner i) { new S.Inner(); }
9+
}
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class S extends S1
2+
object S {
3+
class Inner
4+
}
5+
6+
class S1
7+
object S1 {
8+
class Inner1
9+
}
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
object Test {
2+
val j = new J
3+
// force completion of these signatures
4+
j.ident(null);
5+
j.ident1(null);
6+
j.select(null);
7+
j.select1(null);
8+
9+
val message:TestMessage = null
10+
val builder:TestMessage.Builder = message.toBuilder
11+
builder.setName("name")
12+
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
abstract class AbstractMessage {
2+
public static abstract class Builder<BuilderType extends Builder<BuilderType>> {
3+
}
4+
}
5+
6+
class TestMessage extends AbstractMessage {
7+
8+
public Builder toBuilder() {
9+
return null;
10+
}
11+
12+
public static class Builder extends AbstractMessage.Builder<Builder> {
13+
public Builder setName(String name) {
14+
return this;
15+
}
16+
}
17+
}

tests/run/t6138-2.check

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Foo$Bar was instantiated!

tests/run/t6138-2/JavaClass.java

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
public class JavaClass {
2+
// This is defined in ScalaClass
3+
public static final Foo.Bar bar = new Foo.Bar();
4+
}

tests/run/t6138-2/ScalaClass.scala

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/* Similar to t10490 -- but defines `Foo` in the object.
2+
* Placing this test within t10490 makes it work without a fix, that's why it's independent.
3+
* Note that this was already working, we add it to make sure we don't regress
4+
*/
5+
6+
class Foo
7+
object Foo {
8+
class Bar {
9+
override def toString: String = "Foo$Bar was instantiated!"
10+
}
11+
}
12+
13+
object Test {
14+
def main(args: Array[String]): Unit = {
15+
// JavaClass is the user of the Scala defined classes
16+
println(JavaClass.bar)
17+
}
18+
}

tests/run/t6138/JavaClass.java

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
public class JavaClass {
2+
// This is defined in ScalaClass
3+
public static final Foo.Bar bar = (new Foo()).new Bar();
4+
}

tests/run/t6138/ScalaClass.scala

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
class Foo {
2+
class Bar {
3+
override def toString: String = "Foo$Bar was instantiated!"
4+
}
5+
}
6+
7+
object Test {
8+
def main(args: Array[String]): Unit = {
9+
// JavaClass is the user of the Scala defined classes
10+
println(JavaClass.bar)
11+
//println(JavaClass.baz)
12+
}
13+
}

tests/run/t6238.check

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Foo$Bar was instantiated!

0 commit comments

Comments
 (0)