aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/core/TypeOps.scala17
-rw-r--r--src/dotty/tools/dotc/typer/Checking.scala9
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala16
-rw-r--r--test/dotc/tests.scala11
-rw-r--r--tests/neg/cycles.scala10
-rw-r--r--tests/neg/i1050.scala62
-rw-r--r--tests/neg/ski.scala22
-rw-r--r--tests/neg/t2994.scala6
-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.flags1
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