diff options
author | Martin Odersky <odersky@gmail.com> | 2016-02-01 00:08:26 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-02-09 09:43:07 +0100 |
commit | defba2af7c3b49231962a6f882173bcaff914fcc (patch) | |
tree | 16149a87ac1422d5eac51e4e563f56eda743562c | |
parent | 3637e08033c857e19862ae1fc9730d96cdba3fe2 (diff) | |
download | dotty-defba2af7c3b49231962a6f882173bcaff914fcc.tar.gz dotty-defba2af7c3b49231962a6f882173bcaff914fcc.tar.bz2 dotty-defba2af7c3b49231962a6f882173bcaff914fcc.zip |
Check that non-abstract classes have realizable bounds.
-rw-r--r-- | src/dotty/tools/dotc/core/TypeOps.scala | 25 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Checking.scala | 7 | ||||
-rw-r--r-- | test/dotc/tests.scala | 2 | ||||
-rw-r--r-- | tests/neg/i1050.scala | 21 |
4 files changed, 41 insertions, 14 deletions
diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala index 882ab9f10..227dbb90f 100644 --- a/src/dotty/tools/dotc/core/TypeOps.scala +++ b/src/dotty/tools/dotc/core/TypeOps.scala @@ -449,16 +449,21 @@ trait TypeOps { this: Context => // TODO: Make standalone object. case _ => false } if (!isConcrete(tp)) NotConcrete - else { - def hasBadBounds(mbr: SingleDenotation) = { - val bounds = mbr.info.bounds - !(bounds.lo <:< bounds.hi) - } - tp.nonClassTypeMembers.find(hasBadBounds) match { - case Some(mbr) => new HasProblemBounds(mbr) - case _ => Realizable - } - } + else boundsRealizability(tp) + } + + /** `Realizable` is `tp` has good bounds, a `HasProblemBounds` instance + * pointing to a bad bounds member otherwise. + */ + def boundsRealizability(tp: Type)(implicit ctx: Context) = { + def hasBadBounds(mbr: SingleDenotation) = { + val bounds = mbr.info.bounds + !(bounds.lo <:< bounds.hi) + } + tp.nonClassTypeMembers.find(hasBadBounds) match { + case Some(mbr) => new HasProblemBounds(mbr) + case _ => Realizable + } } private def enterArgBinding(formal: Symbol, info: Type, cls: ClassSymbol, decls: Scope) = { diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala index ca7c5c5ab..7e90d755b 100644 --- a/src/dotty/tools/dotc/typer/Checking.scala +++ b/src/dotty/tools/dotc/typer/Checking.scala @@ -330,6 +330,13 @@ trait Checking { } } + /** Check that all type members of `tp` have realizable bounds */ + def checkRealizableBounds(tp: Type, pos: Position)(implicit ctx: Context): Unit = { + val rstatus = ctx.boundsRealizability(tp) + if (rstatus ne TypeOps.Realizable) + ctx.error(i"$tp cannot be instantiated since it${rstatus.msg}", pos) + } + /** Check that `tp` is a class type with a stable prefix. Also, if `traitReq` is * true check that `tp` is a trait. * Stability checking is disabled in phases after RefChecks. diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index e1a10a6e2..47ac00c6f 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -162,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 = 8) + @Test def neg_i1050 = compileFile(negDir, "i1050", xerrors = 11) @Test def neg_i1050a = compileFile(negDir, "i1050a", xerrors = 2) @Test def neg_moduleSubtyping = compileFile(negDir, "moduleSubtyping", xerrors = 4) @Test def neg_escapingRefs = compileFile(negDir, "escapingRefs", xerrors = 2) diff --git a/tests/neg/i1050.scala b/tests/neg/i1050.scala index 25e647a57..5808011fa 100644 --- a/tests/neg/i1050.scala +++ b/tests/neg/i1050.scala @@ -79,6 +79,21 @@ object Tiark3 { val v = new V {} v.brand("boom!"): Nothing } +object Tiark4 { + trait U { + type Y + trait X { type L = Y } + def compute: X + final lazy val p: X = compute + def brand(x: Y): p.L = x + } + trait V extends U { + type Y >: Any <: Nothing + def compute: X = ??? + } + val v = new V {} // error: cannot be instantiated + v.brand("boom!") +} object Import { trait A { type L <: Nothing } trait B { type L >: Any} @@ -90,7 +105,7 @@ object Import { val x: L = ??? // error: nonfinal lazy } } - trait V extends U { - lazy val p: A & B = ??? } - +object V { // error: cannot be instantiated + type Y >: Any <: Nothing // error: only classes can have declared but undefined members +} |