aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-03-01 18:27:02 +0100
committerMartin Odersky <odersky@gmail.com>2014-03-01 18:27:02 +0100
commitb9e576ad1ba0ff02c550c821648f23905477e545 (patch)
tree5d8116af63cb38a52861941058a1eea62057e8d4
parent340ca0615bc40ca0232143b1d7e206c56e721c5c (diff)
downloaddotty-b9e576ad1ba0ff02c550c821648f23905477e545.tar.gz
dotty-b9e576ad1ba0ff02c550c821648f23905477e545.tar.bz2
dotty-b9e576ad1ba0ff02c550c821648f23905477e545.zip
Check that inferred parent classes are feasible.
-rw-r--r--src/dotty/tools/dotc/typer/Inferencing.scala20
-rw-r--r--test/dotc/tests.scala2
-rw-r--r--tests/neg/templateParents.scala7
-rw-r--r--tests/pos/templateParents.scala19
4 files changed, 39 insertions, 9 deletions
diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala
index 680096d38..ea3109afa 100644
--- a/src/dotty/tools/dotc/typer/Inferencing.scala
+++ b/src/dotty/tools/dotc/typer/Inferencing.scala
@@ -468,6 +468,7 @@ object Inferencing {
case p :: _ if p.classSymbol.isRealClass => parents
case _ =>
val pcls = (defn.ObjectClass /: parents)(improve)
+ typr.println(i"ensure first is class $parents%, % --> ${parents map (_ baseTypeWithArgs pcls)}%, %")
val ptype = ctx.typeComparer.glb(
defn.ObjectType :: (parents map (_ baseTypeWithArgs pcls)))
ptype :: parents
@@ -479,9 +480,22 @@ object Inferencing {
case p :: ps if p.tpe.classSymbol.isRealClass => parents
case _ =>
// add synthetic class type
- val parentTypes = ensureFirstIsClass(parents.tpes)
- assert(parentTypes.length > parents.length)
- (TypeTree(parentTypes.head) withPos pos) :: parents
+ val first :: _ = ensureFirstIsClass(parents.tpes)
+ TypeTree(checkFeasible(first, pos, i"\n in inferred parent $first")).withPos(pos) :: parents
+ }
+
+ /** Check that any top-level type arguments in this type are feasible, i.e. that
+ * their lower bound conforms to their upper cound. If a type argument is
+ * infeasible, issue and error and continue with upper bound.
+ */
+ def checkFeasible(tp: Type, pos: Position, where: => String = "")(implicit ctx: Context): Type = tp match {
+ case tp: RefinedType =>
+ tp.derivedRefinedType(tp.parent, tp.refinedName, checkFeasible(tp.refinedInfo, pos, where))
+ case tp @ TypeBounds(lo, hi) if !(lo <:< hi) =>
+ ctx.error(i"no type exists between low bound $lo and high bound $hi$where", pos)
+ tp.derivedTypeAlias(hi)
+ case _ =>
+ tp
}
/** Check that class does not define */
diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala
index b1fb42d9e..03bc89ea9 100644
--- a/test/dotc/tests.scala
+++ b/test/dotc/tests.scala
@@ -47,7 +47,7 @@ class tests extends CompilerTest {
@Test def neg_typers() = compileFile(negDir, "typers", xerrors = 10)
@Test def neg_privates() = compileFile(negDir, "privates", xerrors = 2)
@Test def neg_rootImports = compileFile(negDir, "rootImplicits", xerrors = 2)
- @Test def neg_templateParents() = compileFile(posDir, "templateParents", xerrors = 2)
+ @Test def neg_templateParents() = compileFile(negDir, "templateParents", xerrors = 3)
@Test def dotc = compileDir(dotcDir + "tools/dotc")
@Test def dotc_ast = compileDir(dotcDir + "tools/dotc/ast")
diff --git a/tests/neg/templateParents.scala b/tests/neg/templateParents.scala
index 637c6037a..6ecc8c384 100644
--- a/tests/neg/templateParents.scala
+++ b/tests/neg/templateParents.scala
@@ -7,3 +7,10 @@ object templateParentsNeg {
new C("b") with C2 // error: C2 is not a trait
}
+object templateParentsNeg1 {
+ class C[T]
+ trait D extends C[String]
+ trait E extends C[Int]
+
+ val x = new D with E // error no type fits between inferred bounds
+} \ No newline at end of file
diff --git a/tests/pos/templateParents.scala b/tests/pos/templateParents.scala
index 530f8c148..845913270 100644
--- a/tests/pos/templateParents.scala
+++ b/tests/pos/templateParents.scala
@@ -1,12 +1,21 @@
object templateParents {
-// traits do not call a constructor
- class C[+T](x: T)
+ // traits do not call a constructor
+ class C[+T](x: T)
trait D extends C[String]
trait E extends C[Int]
new C("abc") with D
+
+}
- //val x = new D with E
+object templateParents1 {
+ // tests inference of synthesized class type
+ class C[+T]
+ trait D extends C[String]
+ trait E extends C[Int]
+
+ val x = new D with E
+
+ val y: C[Int & String] = x
+}
- //val y: C = x
-} \ No newline at end of file