File tree 7 files changed +88
-5
lines changed
compiler/src/dotty/tools/dotc
7 files changed +88
-5
lines changed Original file line number Diff line number Diff line change @@ -205,6 +205,11 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
205
205
Checking .checkInstantiable(tree.tpe, nu.pos)
206
206
withNoCheckNews(nu :: Nil )(super .transform(tree))
207
207
case _ =>
208
+ tree.fun.tpe.widen match {
209
+ case mt : MethodType if mt.isDependent || mt.isParamDependent =>
210
+ Checking .checkRealizableArgs(mt, tree.args)
211
+ case _ =>
212
+ }
208
213
super .transform(tree)
209
214
}
210
215
case tree : TypeApply =>
Original file line number Diff line number Diff line change @@ -151,6 +151,18 @@ object Checking {
151
151
ctx.errorOrMigrationWarning(em " $tp is not a legal path \n since it ${rstatus.msg}" , pos)
152
152
}
153
153
154
+ /** Check that all arguments to dependent parameters are realizable */
155
+ def checkRealizableArgs (mt : MethodType , args : List [Tree ])(implicit ctx : Context ): Unit = {
156
+ val paramTypes = mt.paramInfos.toArray
157
+ val resultType = mt.resultType
158
+ def isDependent (paramRef : ParamRef , i : Int ) =
159
+ (i + 1 until paramTypes.length).exists(j => paramRef.occursIn(paramTypes(j))) ||
160
+ paramRef.occursIn(resultType)
161
+ for ((paramRef, i) <- mt.paramRefs.zipWithIndex)
162
+ if (isDependent(paramRef, i))
163
+ checkRealizable(args(i).tpe, args(i).pos)
164
+ }
165
+
154
166
/** A type map which checks that the only cycles in a type are F-bounds
155
167
* and that protects all F-bounded references by LazyRefs.
156
168
*/
Original file line number Diff line number Diff line change
1
+ object App {
2
+ trait A { type L >: Any }
3
+ def upcast (a : A , x : Any ): a.L = x
4
+ lazy val p : A { type L <: Nothing } = p
5
+ val q = new A { type L = Any }
6
+ def coerce (x : Any ): Int = upcast(p, x) // error: not a legal path
7
+ def coerce1 (x : Any ): Any = upcast(q, x) // ok
8
+ def coerce2 (x : Any ): Int = upcast(p, x): p.L // error: not a legal path // error
9
+
10
+ def compare (x : A , y : x.L ) = assert(x == y)
11
+
12
+ def compare2 (x : A )(y : x.type ) = assert(x == y)
13
+
14
+
15
+ def main (args : Array [String ]): Unit = {
16
+ // println(coerce("Uh oh!"))
17
+ compare(q, q) // OK
18
+ compare(p, p) // error: not a legal path
19
+ compare2(p)(p) // error: not a legal path
20
+ }
21
+ }
Original file line number Diff line number Diff line change @@ -12,14 +12,21 @@ class Test {
12
12
13
13
class Client extends o.Inner // old-error // old-error
14
14
15
- def xToString (x : o.X ): String = x // old- error
15
+ def xToString (x : o.X ): String = x // error
16
16
17
17
def intToString (i : Int ): String = xToString(i)
18
18
}
19
- object Test2 {
20
19
21
- import Test .o ._ // error
20
+ object Test2 {
21
+ trait A {
22
+ type X = String
23
+ }
24
+ trait B {
25
+ type X = Int
26
+ }
27
+ lazy val o : A & B = ???
22
28
23
- def xToString (x : X ): String = x
29
+ def xToString (x : o. X ): String = x // error
24
30
31
+ def intToString (i : Int ): String = xToString(i)
25
32
}
Original file line number Diff line number Diff line change
1
+ class C { type T }
2
+
3
+ class Test {
4
+
5
+ type D <: C
6
+
7
+ lazy val a : C = ???
8
+ final lazy val b : C = ???
9
+ val c : D = ???
10
+ final lazy val d : D = ???
11
+
12
+ val x1 : a.T = ??? // error: not a legal path, since a is lazy & non-final
13
+ val x2 : b.T = ??? // OK, b is lazy but concrete
14
+ val x3 : c.T = ??? // OK, c is abstract but strict
15
+ val x4 : d.T = ??? // error: not a legal path since d is abstract and lazy
16
+
17
+ val y1 : Singleton = a
18
+ val y2 : Singleton = a
19
+ val y3 : Singleton = a
20
+ val y4 : Singleton = a
21
+
22
+ }
Original file line number Diff line number Diff line change
1
+ package test
2
+
3
+ class Thing {
4
+ def info : Info [this .type ] = InfoRepository .getInfo(this )
5
+ def info2 : Info [this .type ] = {
6
+ def self : this .type = this
7
+ InfoRepository .getInfo(self) // error: not a legal path
8
+ }
9
+ }
10
+
11
+ trait Info [T ]
12
+ case class InfoImpl [T ](thing : T ) extends Info [T ]
13
+
14
+ object InfoRepository {
15
+ def getInfo (t : Thing ): Info [t.type ] = InfoImpl (t)
16
+ }
Original file line number Diff line number Diff line change @@ -3,7 +3,7 @@ package test
3
3
class Thing {
4
4
def info : Info [this .type ] = InfoRepository .getInfo(this )
5
5
def info2 : Info [this .type ] = {
6
- def self : this .type = this
6
+ val self : this .type = this
7
7
InfoRepository .getInfo(self)
8
8
}
9
9
}
You can’t perform that action at this time.
0 commit comments