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 {
81
81
if (depVars.nonEmpty) instantiateSelected(tp, depVars.toList)
82
82
}
83
83
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
+
84
106
/** The accumulator which forces type variables using the policy encoded in `force`
85
107
* and returns whether the type is fully defined. The direction in which
86
108
* 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
12
12
import ast .Trees ._
13
13
import NameOps ._
14
14
import ProtoTypes ._
15
+ import Inferencing .couldInstantiateTypeVar
15
16
import collection .mutable
16
17
import reporting ._
17
18
import Checking .{checkNoPrivateLeaks , checkNoWildcard }
@@ -159,6 +160,9 @@ trait TypeAssigner {
159
160
TryDynamicCallType
160
161
else if (qualType.isErroneous || name.toTermName == nme.ERROR )
161
162
UnspecifiedErrorType
163
+ else if couldInstantiateTypeVar(qualType) then
164
+ // try again with more defined qualifier type
165
+ selectionType(tree, qual1)
162
166
else if (name == nme.CONSTRUCTOR )
163
167
errorType(ex " $qualType does not have a constructor " , tree.srcPos)
164
168
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