summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/matching/MatrixAdditions.scala18
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala15
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,