diff options
author | Martin Odersky <odersky@gmail.com> | 2014-03-01 18:27:02 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-03-01 18:27:02 +0100 |
commit | b9e576ad1ba0ff02c550c821648f23905477e545 (patch) | |
tree | 5d8116af63cb38a52861941058a1eea62057e8d4 | |
parent | 340ca0615bc40ca0232143b1d7e206c56e721c5c (diff) | |
download | dotty-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.scala | 20 | ||||
-rw-r--r-- | test/dotc/tests.scala | 2 | ||||
-rw-r--r-- | tests/neg/templateParents.scala | 7 | ||||
-rw-r--r-- | tests/pos/templateParents.scala | 19 |
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 |