File tree Expand file tree Collapse file tree 5 files changed +67
-0
lines changed
compiler/src/dotty/tools/dotc/typer Expand file tree Collapse file tree 5 files changed +67
-0
lines changed Original file line number Diff line number Diff line change @@ -81,6 +81,28 @@ object Inferencing {
8181 if (depVars.nonEmpty) instantiateSelected(tp, depVars.toList)
8282 }
8383
84+ /** If `tp` is top-level type variable with a lower bound in the current constraint,
85+ * instantiate it from below. We also look for TypeVars whereever their instantiation
86+ * could uncover new type members.
87+ */
88+ def couldInstantiateTypeVar (tp : Type )(using Context ): Boolean = tp.dealias match
89+ case tvar : TypeVar
90+ if ! tvar.isInstantiated
91+ && ctx.typerState.constraint.contains(tvar)
92+ && tvar.hasLowerBound =>
93+ tvar.instantiate(fromBelow = true )
94+ true
95+ case AppliedType (tycon, _) =>
96+ couldInstantiateTypeVar(tycon)
97+ case RefinedType (parent, _, _) =>
98+ couldInstantiateTypeVar(parent)
99+ case tp : AndOrType =>
100+ couldInstantiateTypeVar(tp.tp1) || couldInstantiateTypeVar(tp.tp2)
101+ case AnnotatedType (tp, _) =>
102+ couldInstantiateTypeVar(tp)
103+ case _ =>
104+ false
105+
84106 /** The accumulator which forces type variables using the policy encoded in `force`
85107 * and returns whether the type is fully defined. The direction in which
86108 * a type variable is instantiated is determined as follows:
Original file line number Diff line number Diff line change @@ -12,6 +12,7 @@ import config.Printers.typr
1212import ast .Trees ._
1313import NameOps ._
1414import ProtoTypes ._
15+ import Inferencing .couldInstantiateTypeVar
1516import collection .mutable
1617import reporting ._
1718import Checking .{checkNoPrivateLeaks , checkNoWildcard }
@@ -159,6 +160,9 @@ trait TypeAssigner {
159160 TryDynamicCallType
160161 else if (qualType.isErroneous || name.toTermName == nme.ERROR )
161162 UnspecifiedErrorType
163+ else if couldInstantiateTypeVar(qualType) then
164+ // try again with more defined qualifier type
165+ selectionType(tree, qual1)
162166 else if (name == nme.CONSTRUCTOR )
163167 errorType(ex " $qualType does not have a constructor " , tree.srcPos)
164168 else {
File renamed without changes.
Original file line number Diff line number Diff line change 1+ class D
2+ class C [+ T ](x : T )
3+
4+ class Foo () {
5+ val status : Int = 0
6+ }
7+
8+ object Main {
9+ implicit class RichC [T ](c : C [T ]) {
10+ def await (implicit d : D = ??? ): T = ???
11+ }
12+
13+ def test1 : Int = {
14+ val foo = new C (new Foo ()).await
15+ foo.status
16+ }
17+
18+ val test2 = new C (new Foo ()).await.status
19+ }
Original file line number Diff line number Diff line change 1+ // object Test {
2+ // val x: Int => Int = identity
3+ // }
4+
5+ trait Foo [F [_]] {
6+ def foo [G [x] >: F [x]]: G [Unit ]
7+ }
8+
9+ trait M [A ] {
10+ def bla : Int = 1
11+ def baz (f : Int => Int ): Int = f(1 )
12+ }
13+
14+ object Test {
15+ def bar (x : Foo [M ]): Unit = {
16+ // error: value bla is not a member of G[Unit], where: G is a type variable with constraint >: M and <: [x] =>> Any
17+ x.foo.bla
18+
19+ // error: value bla is not a member of G[Unit], where: G is a type variable with constraint >: M and <: [x] =>> Any
20+ x.foo.baz(x => x)
21+ }
22+ }
You can’t perform that action at this time.
0 commit comments