diff options
author | Paul Phillips <paulp@improving.org> | 2012-01-04 16:03:56 -0800 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-01-04 22:51:07 -0800 |
commit | 14ca7ef432d57a6188f184b700ca37e42b9ba17d (patch) | |
tree | fb88caf51411fe8860590f5436c8f4b2e0d76cdd /src | |
parent | 6975b4888da9b56e2c06d45da8f483f2e33a102b (diff) | |
download | scala-14ca7ef432d57a6188f184b700ca37e42b9ba17d.tar.gz scala-14ca7ef432d57a6188f184b700ca37e42b9ba17d.tar.bz2 scala-14ca7ef432d57a6188f184b700ca37e42b9ba17d.zip |
Fix bugs with lubs.
Was not substituting before using fallback lub. I don't think
it was hurting anything because the substitution is wrong anyway,
since it gives up on f-bounds. (This is directly responsible
for the malformed lubs.) But if it must fail, it shouldn't be
letting A and Repr escape into the error message:
scala> List(List(), Stream())
<console>:8: error: type mismatch;
found : List[Nothing]
required: scala.collection.immutable.LinearSeq[Nothing] with .....
scala.collection.LinearSeqOptimized[A,Repr]]]]]
List(List(), Stream())
^
Rather, like this:
found : List[Nothing]
required: scala.collection.immutable.LinearSeq[Nothing] with .....
scala.collection.LinearSeqOptimized[Nothing,scala.collection.immutable.Stream[Nothing]]]]]]
Also, AbstractSeq and other not-public classes were appeaing in the
errors, alerting me to the fact that it would happily infer a lub
containing a type which cannot be referenced.
scala> List(List(), Vector())
res1: List[scala.collection.immutable.Seq[Nothing] with scala.collection.AbstractSeq[Nothing] ...
So I excluded non-public types in lubList:
scala> List(List(), Vector())
res0: List[scala.collection.immutable.Seq[Nothing]] = List(List(), Vector())
Finally, I added logging for recursive bounds.
% scala -Ydebug
scala> List(List(), Stream())
Encountered 2 recursive bounds while lubbing 2 types.
type A in trait LinearSeqOptimized appears in the bounds of type Repr
type Repr >: scala.this.Nothing <: collection.this.LinearSeqOptimized[A,Repr]
type Repr in trait LinearSeqOptimized appears in its own bounds
type Repr >: scala.this.Nothing <: collection.this.LinearSeqOptimized[A,Repr]
Review by @moors.
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/reflect/internal/Types.scala | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index a644baf9f9..c1d3f85bc9 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -5455,6 +5455,23 @@ A type's typeSymbol should never be inspected directly. val formatted = tableDef.table(transposed) println("** Depth is " + depth + "\n" + formatted) } + + /** From a list of types, find any which take type parameters + * where the type parameter bounds contain references to other + * any types in the list (including itself.) + * + * @return List of symbol pairs holding the recursive type + * parameter and the parameter which references it. + */ + def findRecursiveBounds(ts: List[Type]): List[(Symbol, Symbol)] = { + if (ts.isEmpty) Nil + else { + val sym = ts.head.typeSymbol + require(ts.tail forall (_.typeSymbol == sym), ts) + for (p <- sym.typeParams ; in <- sym.typeParams ; if in.info.bounds contains p) yield + p -> in + } + } /** Given a matrix `tsBts` whose columns are basetype sequences (and the symbols `tsParams` that should be interpreted as type parameters in this matrix), * compute its least sorted upwards closed upper bound relative to the following ordering <= between lists of types: @@ -5501,6 +5518,19 @@ A type's typeSymbol should never be inspected directly. // merging, strip targs that refer to bound tparams (when we're computing the lub of type // constructors.) Also filter out all types that are a subtype of some other type. if (isUniformFrontier) { + if (settings.debug.value || printLubs) { + val fbounds = findRecursiveBounds(ts0) + if (fbounds.nonEmpty) { + println("Encountered " + fbounds.size + " recursive bounds while lubbing " + ts0.size + " types.") + for ((p0, p1) <- fbounds) { + val desc = if (p0 == p1) "its own bounds" else "the bounds of " + p1 + + println(" " + p0.fullLocationString + " appears in " + desc) + println(" " + p1 + " " + p1.info.bounds) + } + println("") + } + } val tails = tsBts map (_.tail) mergePrefixAndArgs(elimSub(ts0 map elimHigherOrderTypeParam, depth), 1, depth) match { case Some(tp) => tp :: loop(tails) @@ -5526,7 +5556,7 @@ A type's typeSymbol should never be inspected directly. } } - val initialBTSes = ts map (_.baseTypeSeq.toList) + val initialBTSes = ts map (_.baseTypeSeq.toList filter (_.typeSymbol.isPublic)) if (printLubs) printLubMatrix(ts zip initialBTSes toMap, depth) @@ -5977,7 +6007,7 @@ A type's typeSymbol should never be inspected directly. // conforming to bounds. val bounds0 = sym.typeParams map (_.info.bounds.hi) filterNot (_.typeSymbol == AnyClass) if (bounds0.isEmpty) AnyClass.tpe - else intersectionType(bounds0) + else intersectionType(bounds0 map (b => b.asSeenFrom(tps.head, sym))) } else if (tparam.variance == -variance) NothingClass.tpe else NoType |