diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 6 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Infer.scala | 54 |
2 files changed, 25 insertions, 35 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 8f025336bb..43b96314b0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -346,7 +346,11 @@ trait Implicits { case _ => tp } def stripped(tp: Type): Type = { - deriveTypeWithWildcards(freeTypeParametersNoSkolems.collect(tp))(tp) + // `t.typeSymbol` returns the symbol of the normalized type. If that normalized type + // is a `PolyType`, the symbol of the result type is collected. This is precisely + // what we require for SI-5318. + val syms = for (t <- tp; if t.typeSymbol.isTypeParameter) yield t.typeSymbol + deriveTypeWithWildcards(syms.distinct)(tp) } def sum(xs: List[Int]) = (0 /: xs)(_ + _) def complexity(tp: Type): Int = tp.normalize match { diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 1c1adee343..e91050987b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -1076,7 +1076,7 @@ trait Infer { */ def inferConstructorInstance(tree: Tree, undetparams: List[Symbol], pt0: Type) { val pt = widen(pt0) - val ptparams = freeTypeParamsOfTerms.collect(pt) + val ptparams = freeTypeParamsOfTerms(pt) val ctorTp = tree.tpe val resTp = ctorTp.finalResultType @@ -1310,8 +1310,8 @@ trait Infer { def inferTypedPattern(tree0: Tree, pattp: Type, pt0: Type): Type = { val pt = widen(pt0) - val ptparams = freeTypeParamsOfTerms.collect(pt) - val tpparams = freeTypeParamsOfTerms.collect(pattp) + val ptparams = freeTypeParamsOfTerms(pt) + val tpparams = freeTypeParamsOfTerms(pattp) def ptMatchesPattp = pt matchesPattern pattp.widen def pattpMatchesPt = pattp matchesPattern pt @@ -1364,7 +1364,7 @@ trait Infer { def inferModulePattern(pat: Tree, pt: Type) = if (!(pat.tpe <:< pt)) { - val ptparams = freeTypeParamsOfTerms.collect(pt) + val ptparams = freeTypeParamsOfTerms(pt) debuglog("free type params (2) = " + ptparams) val ptvars = ptparams map freshVar val pt1 = pt.instantiateTypeParams(ptparams, ptvars) @@ -1381,19 +1381,6 @@ trait Infer { } } - abstract class SymCollector extends TypeCollector(List[Symbol]()) { - protected def includeCondition(sym: Symbol): Boolean - - def traverse(tp: Type) { - tp.normalize match { - case TypeRef(_, sym, _) => - if (includeCondition(sym) && !result.contains(sym)) result = sym :: result - case _ => - } - mapOver(tp) - } - } - object approximateAbstracts extends TypeMap { def apply(tp: Type): Type = tp.normalize match { case TypeRef(pre, sym, _) if sym.isAbstractType => WildcardType @@ -1401,31 +1388,30 @@ trait Infer { } } - /** A traverser to collect type parameters referred to in a type + /** Collects type parameters referred to in a type. */ - object freeTypeParamsOfTerms extends SymCollector { + def freeTypeParamsOfTerms(tp: Type): List[Symbol] = { // An inferred type which corresponds to an unknown type // constructor creates a file/declaration order-dependent crasher // situation, the behavior of which depends on the state at the // time the typevar is created. Until we can deal with these // properly, we can avoid it by ignoring type parameters which // have type constructors amongst their bounds. See SI-4070. - protected def includeCondition(sym: Symbol) = ( - sym.isAbstractType - && sym.owner.isTerm - && !sym.info.bounds.exists(_.typeParams.nonEmpty) - ) - } - - /** A traverser to collect type parameters referred to in a type - */ - object freeTypeParametersNoSkolems extends SymCollector { - protected def includeCondition(sym: Symbol): Boolean = - sym.isTypeParameter && sym.owner.isTerm - } + def isFreeTypeParamOfTerm(sym: Symbol) = ( + sym.isAbstractType + && sym.owner.isTerm + && !sym.info.bounds.exists(_.typeParams.nonEmpty) + ) - object typeRefs extends SymCollector { - protected def includeCondition(sym: Symbol): Boolean = true + // Intentionally *not* using `Type#typeSymbol` here, which would normalize `tp` + // and collect symbols from the result type of any resulting `PolyType`s, which + // are not free type parameters of `tp`. + // + // Contrast with `isFreeTypeParamNoSkolem`. + val syms = tp collect { + case TypeRef(_, sym, _) if isFreeTypeParamOfTerm(sym) => sym + } + syms.distinct } /* -- Overload Resolution ---------------------------------------------- */ |