From b7e7cf14bb3b06cdf9c7f7a8ccfe2d3220af95c4 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Sat, 14 May 2011 16:55:44 +0000 Subject: Change Types#narrow to create an existential ra... Change Types#narrow to create an existential rather than a refinement type, as the comment indicated was a desirable outcome. (Definitely) review by odersky. --- .../scala/tools/nsc/matching/MatrixAdditions.scala | 18 +++++++++++++++--- src/compiler/scala/tools/nsc/symtab/Types.scala | 15 ++------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala b/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala index d75670fd38..2d31281e34 100644 --- a/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala +++ b/src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala @@ -142,11 +142,23 @@ trait MatrixAdditions extends ast.TreeDSL { import Flags.{ MUTABLE, ABSTRACT, SEALED } private case class Combo(index: Int, sym: Symbol) { - val isBaseClass = sym.tpe.baseClasses.toSet - // is this combination covered by the given pattern? def isCovered(p: Pattern) = { - def coversSym = isBaseClass(decodedEqualsType(p.tpe).typeSymbol) + def coversSym = { + val lhs = decodedEqualsType(p.tpe) + val rhs = sym.tpe + // This logic, arrived upon after much struggle, attempts to find the + // the route through the type maze which let us issue precise exhaustiveness + // warnings against narrowed types (see test case sealed-java-enums.scala) + // while retaining the necessary pattern matching behavior that case _: List[_] => + // matches both "object Nil" and "class ::[T]". + // + // Doubtless there is a more direct/correct expression of it. + if (rhs.typeSymbol.isSingletonExistential) + lhs <:< rhs + else + rhs.baseClasses contains lhs.typeSymbol + } cond(p.tree) { case _: UnApply | _: ArrayValue => true diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index 87fc2b4963..80a48e55fc 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -79,8 +79,6 @@ trait Types extends reflect.generic.Types { self: SymbolTable => private var explainSwitch = false private final val emptySymbolSet = immutable.Set.empty[Symbol] - private final val alternativeNarrow = false - private final val LogPendingSubTypesThreshold = 50 private final val LogPendingBaseTypesThreshold = 50 private final val LogVolatileThreshold = 50 @@ -317,21 +315,12 @@ trait Types extends reflect.generic.Types { self: SymbolTable => /** Map to a singleton type which is a subtype of this type. * The fallback implemented here gives - * T.narrow = (T {}).this.type + * T.narrow = T' forSome { type T' <: T with Singleton } * Overridden where we know more about where types come from. - * - * todo: change to singleton type of an existentially defined variable - * of the right type instead of making this a `this` of a refined type. */ def narrow: Type = if (phase.erasedTypes) this - else if (alternativeNarrow) { // investigate why this does not work! - val tparam = commonOwner(this) freshExistential ".type" setInfo singletonBounds(this) - tparam.tpe - } else { - val cowner = commonOwner(this) - refinedType(List(this), cowner, EmptyScope, cowner.pos).narrow - } + else commonOwner(this) freshExistential ".type" setInfo singletonBounds(this) tpe /** For a TypeBounds type, itself; * for a reference denoting an abstract type, its bounds, -- cgit v1.2.3