diff options
author | Guillaume Martres <smarter@ubuntu.com> | 2016-01-18 19:05:48 +0100 |
---|---|---|
committer | Guillaume Martres <smarter@ubuntu.com> | 2016-01-18 19:05:48 +0100 |
commit | 1aa8fbb56e95d7aea04b338d3edf7d53077b804a (patch) | |
tree | a49dfa96f7e99c0b18bc5053b823b141ed2ded96 /src/dotty/tools/dotc/typer | |
parent | dd733181fd943f5074af57b151da95df7c999fc9 (diff) | |
parent | 224232df2affa882c2c41fc8a6730ad7fc049679 (diff) | |
download | dotty-1aa8fbb56e95d7aea04b338d3edf7d53077b804a.tar.gz dotty-1aa8fbb56e95d7aea04b338d3edf7d53077b804a.tar.bz2 dotty-1aa8fbb56e95d7aea04b338d3edf7d53077b804a.zip |
Merge pull request #1014 from dotty-staging/fix/deep-subtypes
Check all bounds and avoid infinite subtyping checks when intersecting denotations
Diffstat (limited to 'src/dotty/tools/dotc/typer')
-rw-r--r-- | src/dotty/tools/dotc/typer/Applications.scala | 1 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Checking.scala | 15 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 17 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 3 |
4 files changed, 32 insertions, 4 deletions
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala index b3cda20b8..649b8088f 100644 --- a/src/dotty/tools/dotc/typer/Applications.scala +++ b/src/dotty/tools/dotc/typer/Applications.scala @@ -607,7 +607,6 @@ trait Applications extends Compatibility { self: Typer => case pt: PolyType => if (typedArgs.length <= pt.paramBounds.length) typedArgs = typedArgs.zipWithConserve(pt.paramBounds)(adaptTypeArg) - Checking.checkBounds(typedArgs, pt) case _ => } assignType(cpy.TypeApply(tree)(typedFn, typedArgs), typedFn, typedArgs) diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala index 6ded7c109..0b4787d15 100644 --- a/src/dotty/tools/dotc/typer/Checking.scala +++ b/src/dotty/tools/dotc/typer/Checking.scala @@ -48,6 +48,21 @@ object Checking { def checkBounds(args: List[tpd.Tree], poly: PolyType)(implicit ctx: Context): Unit = checkBounds(args, poly.paramBounds, _.substParams(poly, _)) + /** Check all AppliedTypeTree nodes in this tree for legal bounds */ + val boundsChecker = new TreeTraverser { + def traverse(tree: Tree)(implicit ctx: Context) = { + tree match { + case AppliedTypeTree(tycon, args) => + val tparams = tycon.tpe.typeSymbol.typeParams + val bounds = tparams.map(tparam => + tparam.info.asSeenFrom(tycon.tpe.normalizedPrefix, tparam.owner.owner).bounds) + checkBounds(args, bounds, _.substDealias(tparams, _)) + case _ => + } + traverseChildren(tree) + } + } + /** Check that `tp` refers to a nonAbstract class * and that the instance conforms to the self type of the created class. */ diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index 406e7378f..ecbec7d07 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -869,7 +869,9 @@ class Namer { typer: Typer => if (tparamSyms.nonEmpty && !isDerived) tp.LambdaAbstract(tparamSyms) //else if (toParameterize) tp.parameterizeWith(tparamSyms) else tp - sym.info = abstracted(TypeBounds.empty) + + val dummyInfo = abstracted(TypeBounds.empty) + sym.info = dummyInfo // Temporarily set info of defined type T to ` >: Nothing <: Any. // This is done to avoid cyclic reference errors for F-bounds. // This is subtle: `sym` has now an empty TypeBounds, but is not automatically @@ -890,6 +892,19 @@ class Namer { typer: Typer => sym.info = NoCompleter sym.info = checkNonCyclic(sym, unsafeInfo, reportErrors = true) } + + // Here we pay the price for the cavalier setting info to TypeBounds.empty above. + // We need to compensate by invalidating caches in references that might + // still contain the TypeBounds.empty. If we do not do this, stdlib factories + // fail with a bounds error in PostTyper. + def ensureUpToDate(tp: Type, outdated: Type) = tp match { + case tref: TypeRef if tref.info == outdated && sym.info != outdated => + tref.uncheckedSetSym(null) + case _ => + } + ensureUpToDate(sym.typeRef, dummyInfo) + ensureUpToDate(sym.typeRef.appliedTo(tparamSyms.map(_.typeRef)), TypeBounds.empty) + etaExpandArgs.apply(sym.info) } diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 511a12ea7..008eab0fd 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -961,8 +961,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit val TypeDef(name, rhs) = tdef checkLowerNotHK(sym, tdef.tparams.map(symbolOfTree), tdef.pos) completeAnnotations(tdef, sym) - val _ = typedType(rhs) // unused, typecheck only to remove from typedTree - assignType(cpy.TypeDef(tdef)(name, TypeTree(sym.info), Nil), sym) + assignType(cpy.TypeDef(tdef)(name, typedType(rhs), Nil), sym) } def typedClassDef(cdef: untpd.TypeDef, cls: ClassSymbol)(implicit ctx: Context) = track("typedClassDef") { |