diff options
-rw-r--r-- | src/dotty/tools/dotc/core/TypeOps.scala | 17 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Checking.scala | 9 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 16 | ||||
-rw-r--r-- | test/dotc/tests.scala | 11 | ||||
-rw-r--r-- | tests/neg/cycles.scala | 10 | ||||
-rw-r--r-- | tests/neg/i1050.scala | 62 | ||||
-rw-r--r-- | tests/neg/ski.scala | 22 | ||||
-rw-r--r-- | tests/neg/t2994.scala | 6 | ||||
-rw-r--r-- | tests/pos-scala2/i871.scala (renamed from tests/pos-special/i871.scala) | 0 | ||||
-rw-r--r-- | tests/pos-scala2/t1292.scala (renamed from tests/pos/t1292.scala) | 0 | ||||
-rw-r--r-- | tests/pos-scala2/t2994.scala (renamed from tests/pos/t2994.scala) | 0 | ||||
-rw-r--r-- | tests/pos-scala2/t3568.scala (renamed from tests/pos/t3568.scala) | 0 | ||||
-rw-r--r-- | tests/pos-scala2/t3731.scala (renamed from tests/pos/t3731.scala) | 0 | ||||
-rw-r--r-- | tests/pos-scala2/t3833.scala (renamed from tests/pos/t3833.scala) | 0 | ||||
-rw-r--r-- | tests/pos-scala2/t5070.scala (renamed from tests/pos/t5070.scala) | 0 | ||||
-rw-r--r-- | tests/pos-scala2/t5541.scala (renamed from tests/pos/t5541.scala) | 0 | ||||
-rw-r--r-- | tests/pos-scala2/variances-constr.scala (renamed from tests/pos-special/variances-constr.scala) | 0 | ||||
-rw-r--r-- | tests/pos-special/i871.flags | 1 |
18 files changed, 112 insertions, 42 deletions
diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala index 26ce4ebf8..9fcc6abbc 100644 --- a/src/dotty/tools/dotc/core/TypeOps.scala +++ b/src/dotty/tools/dotc/core/TypeOps.scala @@ -435,7 +435,10 @@ trait TypeOps { this: Context => // TODO: Make standalone object. /** The realizability status of given type `tp`*/ def realizability(tp: Type): Realizability = tp.dealias match { case tp: TermRef => - if (tp.symbol.isRealizable) Realizable else NotStable + if (tp.symbol.isRealizable) Realizable + else if (!tp.symbol.isStable) NotStable + else if (!tp.symbol.isEffectivelyFinal) new NotFinal(tp.symbol) + else new ProblemInUnderlying(tp.info, realizability(tp.info)) case _: SingletonType | NoPrefix => Realizable case tp => @@ -684,10 +687,16 @@ object TypeOps { object Realizable extends Realizability("") - object NotConcrete extends Realizability("is not a concrete type") + object NotConcrete extends Realizability("it is not a concrete type") - object NotStable extends Realizability("is not a stable reference") + object NotStable extends Realizability("it is not a stable reference") + + class NotFinal(sym: Symbol)(implicit ctx: Context) + extends Realizability(i"it refers to nonfinal $sym") class HasProblemBounds(mbr: SingleDenotation)(implicit ctx: Context) - extends Realizability(i"has a member $mbr with possibly empty bounds ${mbr.info.bounds.lo} .. ${mbr.info.bounds.hi}") + extends Realizability(i"it has a member $mbr with possibly conflicting bounds ${mbr.info.bounds.lo} <: ... <: ${mbr.info.bounds.hi}") + + class ProblemInUnderlying(tp: Type, problem: Realizability)(implicit ctx: Context) + extends Realizability(i"its underlying type ${tp} ${problem.msg}") } diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala index d333efa33..ee1c2a061 100644 --- a/src/dotty/tools/dotc/typer/Checking.scala +++ b/src/dotty/tools/dotc/typer/Checking.scala @@ -318,15 +318,14 @@ trait Checking { } /** Check that type `tp` is stable. */ - def checkStableAndRealizable(tp: Type, pos: Position)(implicit ctx: Context): Unit = + def checkStable(tp: Type, pos: Position)(implicit ctx: Context): Unit = if (!tp.isStable) ctx.error(d"$tp is not stable", pos) - else checkRealizable(tp, pos) /** Check that type `tp` is realizable. */ def checkRealizable(tp: Type, pos: Position)(implicit ctx: Context): Unit = { val rstatus = ctx.realizability(tp) if (rstatus ne TypeOps.Realizable) { - def msg = d"$tp is not a legal path since it ${rstatus.msg}" + def msg = d"$tp is not a legal path since ${rstatus.msg}" if (ctx.scala2Mode) ctx.migrationWarning(msg, pos) else ctx.error(msg, pos) } } @@ -339,7 +338,7 @@ trait Checking { def checkClassTypeWithStablePrefix(tp: Type, pos: Position, traitReq: Boolean)(implicit ctx: Context): Type = tp.underlyingClassRef(refinementOK = false) match { case tref: TypeRef => - if (ctx.phase <= ctx.refchecksPhase) checkStableAndRealizable(tref.prefix, pos) + if (ctx.phase <= ctx.refchecksPhase) checkStable(tref.prefix, pos) if (traitReq && !(tref.symbol is Trait)) ctx.error(d"$tref is not a trait", pos) tp case _ => @@ -442,7 +441,7 @@ trait NoChecking extends Checking { import tpd._ override def checkNonCyclic(sym: Symbol, info: TypeBounds, reportErrors: Boolean)(implicit ctx: Context): Type = info override def checkValue(tree: Tree, proto: Type)(implicit ctx: Context): tree.type = tree - override def checkStableAndRealizable(tp: Type, pos: Position)(implicit ctx: Context): Unit = () + override def checkStable(tp: Type, pos: Position)(implicit ctx: Context): Unit = () override def checkRealizable(tp: Type, pos: Position)(implicit ctx: Context): Unit = () override def checkClassTypeWithStablePrefix(tp: Type, pos: Position, traitReq: Boolean)(implicit ctx: Context): Type = tp override def checkImplicitParamsNotSingletons(vparamss: List[List[ValDef]])(implicit ctx: Context): Unit = () diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 79035108e..ce0a5c0f2 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -308,7 +308,10 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = track("typedSelect") { def asSelect(implicit ctx: Context): Tree = { val qual1 = typedExpr(tree.qualifier, selectionProto(tree.name, pt, this)) - if (tree.name.isTypeName) checkStableAndRealizable(qual1.tpe, qual1.pos) + if (tree.name.isTypeName) { + checkStable(qual1.tpe, qual1.pos) + checkRealizable(qual1.tpe, qual1.pos) + } typedSelect(tree, pt, qual1) } @@ -342,7 +345,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def typedSelectFromTypeTree(tree: untpd.SelectFromTypeTree, pt: Type)(implicit ctx: Context): Tree = track("typedSelectFromTypeTree") { val qual1 = typedType(tree.qualifier, selectionProto(tree.name, pt, this)) - //checkRealizable(qual1.tpe, qual1.pos) + checkRealizable(qual1.tpe, qual1.pos) assignType(cpy.SelectFromTypeTree(tree)(qual1, tree.name), qual1) } @@ -823,7 +826,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def typedSingletonTypeTree(tree: untpd.SingletonTypeTree)(implicit ctx: Context): SingletonTypeTree = track("typedSingletonTypeTree") { val ref1 = typedExpr(tree.ref) - checkStableAndRealizable(ref1.tpe, tree.pos) + checkStable(ref1.tpe, tree.pos) + checkRealizable(ref1.tpe, tree.pos) assignType(cpy.SingletonTypeTree(tree)(ref1), ref1) } @@ -920,8 +924,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def completeAnnotations(mdef: untpd.MemberDef, sym: Symbol)(implicit ctx: Context): Unit = { // necessary to force annotation trees to be computed. sym.annotations.foreach(_.tree) - // necessary in order to mark the typed ahead annotations as definitiely typed: - untpd.modsDeco(mdef).mods.annotations.mapconserve(typedAnnotation) + // necessary in order to mark the typed ahead annotations as definitely typed: + untpd.modsDeco(mdef).mods.annotations.foreach(typedAnnotation) } def typedAnnotation(annot: untpd.Tree)(implicit ctx: Context): Tree = track("typedAnnotation") { @@ -1057,7 +1061,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def typedImport(imp: untpd.Import, sym: Symbol)(implicit ctx: Context): Import = track("typedImport") { val expr1 = typedExpr(imp.expr, AnySelectionProto) - checkStableAndRealizable(expr1.tpe, imp.expr.pos) + checkStable(expr1.tpe, imp.expr.pos) assignType(cpy.Import(imp)(expr1, imp.selectors), sym) } diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index 85b1db139..3414f1977 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -42,6 +42,7 @@ class tests extends CompilerTest { val testsDir = "./tests/" val posDir = testsDir + "pos/" val posSpecialDir = testsDir + "pos-special/" + val posScala2Dir = testsDir + "pos-scala2/" val negDir = testsDir + "neg/" val runDir = testsDir + "run/" val newDir = testsDir + "new/" @@ -101,8 +102,8 @@ class tests extends CompilerTest { @Test def pos_all = compileFiles(posDir) // twice omitted to make tests run faster - @Test def pos_i871 = compileFile(posSpecialDir, "i871", scala2mode) - @Test def pos_variancesConstr = compileFile(posSpecialDir, "variances-constr", scala2mode) + @Test def pos_scala2_all = compileFiles(posScala2Dir, scala2mode) + @Test def pos_859 = compileFile(posSpecialDir, "i859", scala2mode)(allowDeepSubtypes) @Test def new_all = compileFiles(newDir, twice) @@ -137,7 +138,7 @@ class tests extends CompilerTest { @Test def neg_t1843_variances = compileFile(negDir, "t1843-variances", xerrors = 1) @Test def neg_t2660_ambi = compileFile(negDir, "t2660", xerrors = 2) - @Test def neg_t2994 = compileFile(negDir, "t2994", xerrors = 2) + @Test def neg_t2994 = compileFile(negDir, "t2994", xerrors = 5) @Test def neg_subtyping = compileFile(negDir, "subtyping", xerrors = 5) @Test def neg_variances = compileFile(negDir, "variances", xerrors = 2) @Test def neg_variancesConstr = compileFile(negDir, "variances-constr", xerrors = 2) @@ -161,7 +162,7 @@ class tests extends CompilerTest { @Test def neg_i803 = compileFile(negDir, "i803", xerrors = 2) @Test def neg_i866 = compileFile(negDir, "i866", xerrors = 2) @Test def neg_i974 = compileFile(negDir, "i974", xerrors = 2) - @Test def neg_i1050 = compileFile(negDir, "i1050", xerrors = 2) + @Test def neg_i1050 = compileFile(negDir, "i1050", xerrors = 3) @Test def neg_moduleSubtyping = compileFile(negDir, "moduleSubtyping", xerrors = 4) @Test def neg_escapingRefs = compileFile(negDir, "escapingRefs", xerrors = 2) @Test def neg_instantiateAbstract = compileFile(negDir, "instantiateAbstract", xerrors = 8) @@ -170,7 +171,7 @@ class tests extends CompilerTest { @Test def neg_selfreq = compileFile(negDir, "selfreq", xerrors = 2) @Test def neg_singletons = compileFile(negDir, "singletons", xerrors = 8) @Test def neg_shadowedImplicits = compileFile(negDir, "arrayclone-new", xerrors = 2) - @Test def neg_ski = compileFile(negDir, "ski", xerrors = 2) + @Test def neg_ski = compileFile(negDir, "ski", xerrors = 10) @Test def neg_traitParamsTyper = compileFile(negDir, "traitParamsTyper", xerrors = 5) @Test def neg_traitParamsMixin = compileFile(negDir, "traitParamsMixin", xerrors = 2) @Test def neg_firstError = compileFile(negDir, "firstError", xerrors = 3) diff --git a/tests/neg/cycles.scala b/tests/neg/cycles.scala index 77f902bf0..550bc98ea 100644 --- a/tests/neg/cycles.scala +++ b/tests/neg/cycles.scala @@ -9,11 +9,11 @@ class A { class B { type T <: x.type // error: cycle - val x: T = ??? + final val x: T = ??? } class C { - val x: D#T = ??? + final val x: D#T = ??? // error: conflicting bounds class D { type T <: x.type // error: cycle val z: x.type = ??? @@ -25,7 +25,7 @@ class E { type T <: x.type // error: not stable val z: x.type = ??? // error: not stable } - lazy val x: F#T = ??? + lazy val x: F#T = ??? // error: conflicting bounds } class T1 { @@ -37,6 +37,6 @@ class T2 { type U = X | Int } object T12 { - ??? : (T1 {})#U - ??? : (T2 {})#U + ??? : (T1 {})#U // error: conflicting bounds + ??? : (T2 {})#U // error: conflicting bounds } diff --git a/tests/neg/i1050.scala b/tests/neg/i1050.scala index 48e2b5f2e..bc906f4f4 100644 --- a/tests/neg/i1050.scala +++ b/tests/neg/i1050.scala @@ -2,7 +2,7 @@ trait A { type L <: Nothing } trait B { type L >: Any} object Test { lazy val x: A & B = ??? - val y: x.L = 1 + val y: x.L = 1 // error: underlying conflicting bounds val z: String = y } object Test50 { @@ -14,7 +14,7 @@ object Test50 { } lazy val o: A & B = ??? - def xToString(x: o.X): String = x + def xToString(x: o.X): String = x // error: underlying conflicting bounds def intToString(i: Int): String = xToString(i) @@ -22,3 +22,61 @@ object Test50 { val s: String = intToString(1) } } +object Test2 { + + trait C { type A } + + type T = C { type A = Any } + type U = C { type A = Nothing } + type X = T & U + + def main(args: Array[String]) = { + val y: X#A = 1 // error: conflicting bounds + val z: String = y + } +} +object Tiark1 { + trait A { type L <: Nothing } + trait B { type L >: Any} + trait U { + val p: B + def brand(x: Any): p.L = x // error: not final + } + trait V extends U { + lazy val p: A & B = ??? + } + val v = new V {} + v.brand("boom!") +} +object Tiark2 { + trait A { type L <: Nothing } + trait B { type L >: Any} + trait U { + type X <: B + val p: X + def brand(x: Any): p.L = x // error: not final + } + trait V extends U { + type X = B & A + lazy val p: X = ??? + } + val v = new V {} + v.brand("boom!"): Nothing +} +/* +object Import { + trait A { type L <: Nothing } + trait B { type L >: Any} + trait U { + val p: B + def brand(x: Any): p.L = x // error: not final + locally { import p._ + } + } + trait V extends U { + lazy val p: A & B = ??? + } + val v = new V {} + v.brand("boom!") +} +*/ diff --git a/tests/neg/ski.scala b/tests/neg/ski.scala index 6510e66ae..8fb35c7f2 100644 --- a/tests/neg/ski.scala +++ b/tests/neg/ski.scala @@ -17,8 +17,8 @@ trait S2[x <: Term, y <: Term] extends Term { type eval = S2[x, y] } trait S3[x <: Term, y <: Term, z <: Term] extends Term { - type ap[v <: Term] = eval#ap[v] - type eval = x#ap[z]#ap[y#ap[z]]#eval + type ap[v <: Term] = eval#ap[v] // error + type eval = x#ap[z]#ap[y#ap[z]]#eval // error // error } // The K combinator @@ -31,8 +31,8 @@ trait K1[x <: Term] extends Term { type eval = K1[x] } trait K2[x <: Term, y <: Term] extends Term { - type ap[z <: Term] = eval#ap[z] - type eval = x#eval + type ap[z <: Term] = eval#ap[z] // error + type eval = x#eval // error } // The I combinator @@ -41,8 +41,8 @@ trait I extends Term { type eval = I } trait I1[x <: Term] extends Term { - type ap[y <: Term] = eval#ap[y] - type eval = x#eval + type ap[y <: Term] = eval#ap[y] // error + type eval = x#eval // error } // Constants @@ -64,9 +64,9 @@ case class Equals[A >: B <:B , B]() object Test { type T1 = Equals[Int, Int] // compiles fine - type T2 = Equals[String, Int] // error + type T2 = Equals[String, Int] // was error, now masked type T3 = Equals[I#ap[c]#eval, c] - type T3a = Equals[I#ap[c]#eval, d]// error + type T3a = Equals[I#ap[c]#eval, d] // was error, now masked // Ic -> c type T4 = Equals[I#ap[c]#eval, c] @@ -106,11 +106,11 @@ object Test { type eval = A0 } trait A1 extends Term { - type ap[x <: Term] = x#ap[A0]#eval + type ap[x <: Term] = x#ap[A0]#eval // error type eval = A1 } trait A2 extends Term { - type ap[x <: Term] = x#ap[A1]#eval + type ap[x <: Term] = x#ap[A1]#eval // error type eval = A2 } @@ -126,7 +126,7 @@ object Test { type T15 = Equals[NN3#eval, c] trait An extends Term { - type ap[x <: Term] = x#ap[An]#eval + type ap[x <: Term] = x#ap[An]#eval // error type eval = An } diff --git a/tests/neg/t2994.scala b/tests/neg/t2994.scala index 9e9c4ec08..9827b1989 100644 --- a/tests/neg/t2994.scala +++ b/tests/neg/t2994.scala @@ -7,7 +7,7 @@ object Naturals { type a[s[_ <: NAT] <: NAT, z <: NAT] = z } final class SUCC[n <: NAT] extends NAT { - type a[s[_ <: NAT] <: NAT, z <: NAT] = s[n#a[s, z]] + type a[s[_ <: NAT] <: NAT, z <: NAT] = s[n#a[s, z]] // error: not a legal path } type _0 = ZERO type _1 = SUCC[_0] @@ -21,8 +21,8 @@ object Naturals { // crashes scala-2.8.0 beta1 trait MUL[n <: NAT, m <: NAT] extends NAT { trait curry[n[_[_], _], s[_]] { type f[z <: NAT] = n[s, z] } // can't do double param lists: - // error: `]' expected but `[` found. - type a[s[_ <: NAT] <: NAT, z <: NAT] = n#a[curry[m#a, s]#f, z] + // error: `]' expected but `[` found. // error: wrong number of type arguments + type a[s[_ <: NAT] <: NAT, z <: NAT] = n#a[curry[m#a, s]#f, z] // error: not a legal path // error: not a legal path } } diff --git a/tests/pos-special/i871.scala b/tests/pos-scala2/i871.scala index 2e5f100d8..2e5f100d8 100644 --- a/tests/pos-special/i871.scala +++ b/tests/pos-scala2/i871.scala diff --git a/tests/pos/t1292.scala b/tests/pos-scala2/t1292.scala index 8e69734e9..8e69734e9 100644 --- a/tests/pos/t1292.scala +++ b/tests/pos-scala2/t1292.scala diff --git a/tests/pos/t2994.scala b/tests/pos-scala2/t2994.scala index c7421c42a..c7421c42a 100644 --- a/tests/pos/t2994.scala +++ b/tests/pos-scala2/t2994.scala diff --git a/tests/pos/t3568.scala b/tests/pos-scala2/t3568.scala index 50f0cdb2e..50f0cdb2e 100644 --- a/tests/pos/t3568.scala +++ b/tests/pos-scala2/t3568.scala diff --git a/tests/pos/t3731.scala b/tests/pos-scala2/t3731.scala index 7a3cbec0f..7a3cbec0f 100644 --- a/tests/pos/t3731.scala +++ b/tests/pos-scala2/t3731.scala diff --git a/tests/pos/t3833.scala b/tests/pos-scala2/t3833.scala index 2df658df1..2df658df1 100644 --- a/tests/pos/t3833.scala +++ b/tests/pos-scala2/t3833.scala diff --git a/tests/pos/t5070.scala b/tests/pos-scala2/t5070.scala index c236b4f9e..c236b4f9e 100644 --- a/tests/pos/t5070.scala +++ b/tests/pos-scala2/t5070.scala diff --git a/tests/pos/t5541.scala b/tests/pos-scala2/t5541.scala index 54e2b6518..54e2b6518 100644 --- a/tests/pos/t5541.scala +++ b/tests/pos-scala2/t5541.scala diff --git a/tests/pos-special/variances-constr.scala b/tests/pos-scala2/variances-constr.scala index ee4219b10..ee4219b10 100644 --- a/tests/pos-special/variances-constr.scala +++ b/tests/pos-scala2/variances-constr.scala diff --git a/tests/pos-special/i871.flags b/tests/pos-special/i871.flags deleted file mode 100644 index a5c112f5a..000000000 --- a/tests/pos-special/i871.flags +++ /dev/null @@ -1 +0,0 @@ --language:Scala2
\ No newline at end of file |