Permalink
Browse files

SI-7285 Fix match analysis with nested objects.

The fix for SI-6146 introduced `nestedMemberType` to
enumerate sealed subtypes based on the (prefixed) type
of the scrutinee and the symbols of its sealed subclasses.
That method needed to widen `ThisType(modSym)`s to
`ModuleTypeRef(modSym)` before calling `asSeenFrom`.

However, this could lead to confused in the match analysis,
which sees `ModuleTypeRef` as distinct from singleton types
on the same modules (after all, they aren't =:=). Spurious
warnings ensued.

This commit makes two changes:

 - conditionally re-narrow the result of `asSeenFrom` in `nestedMemberType`.
 - present `a.b.SomeModule.type` as `SomeModule` in warnings emitted
   by the pattern matcher.
  • Loading branch information...
1 parent 499962d commit dd89b006218d76a74d0185392d5e427c0867a33c @retronym retronym committed Mar 23, 2013
@@ -574,6 +574,7 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis {
assert(tp.isInstanceOf[SingletonType])
val toString = tp match {
case ConstantType(c) => c.escapedStringValue
+ case _ if tp.typeSymbol.isModuleClass => tp.typeSymbol.name.toString
case _ => tp.toString
}
Const.unique(tp, new ValueConst(tp, tp.widen, toString))
@@ -623,4 +624,4 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis {
override def toString = "null"
}
}
-}
+}
@@ -5036,10 +5036,11 @@ trait Types extends api.Types { self: SymbolTable =>
if (tp.isTrivial) tp
else if (tp.prefix.typeSymbol isNonBottomSubClass owner) {
val widened = tp match {
- case _: ConstantType => tp // Java enum constants: don't widen to the enum type!
- case _ => tp.widen // C.X.type widens to C.this.X.type, otherwise `tp asSeenFrom (pre, C)` has no effect.
+ case _: ConstantType => tp // Java enum constants: don't widen to the enum type!
+ case _ => tp.widen // C.X.type widens to C.this.X.type, otherwise `tp asSeenFrom (pre, C)` has no effect.
}
- widened asSeenFrom (pre, tp.typeSymbol.owner)
+ val memType = widened asSeenFrom (pre, tp.typeSymbol.owner)
+ if (tp eq widened) memType else memType.narrow
}
else loop(tp.prefix) memberType tp.typeSymbol
View
@@ -0,0 +1,13 @@
+t7285.scala:15: error: match may not be exhaustive.
+It would fail on the following input: (Up, Down)
+ (d1, d2) match {
+ ^
+t7285.scala:33: error: match may not be exhaustive.
+It would fail on the following input: Down
+ (d1) match {
+ ^
+t7285.scala:51: error: match may not be exhaustive.
+It would fail on the following input: (Up, Down)
+ (d1, d2) match {
+ ^
+three errors found
@@ -0,0 +1 @@
+-Xfatal-warnings
View
@@ -0,0 +1,55 @@
+sealed abstract class Base
+
+
+object Test1 {
+ sealed abstract class Base
+
+ object Base {
+ case object Down extends Base {
+ }
+
+ case object Up extends Base {
+ }
+
+ (d1: Base, d2: Base) =>
+ (d1, d2) match {
+ case (Up, Up) | (Down, Down) => false
+ case (Down, Up) => true
+ }
+ }
+}
+
+object Test2 {
+ sealed abstract class Base
+
+ object Base {
+ case object Down extends Base {
+ }
+
+ case object Up extends Base {
+ }
+
+ (d1: Base, d2: Base) =>
+ (d1) match {
+ case Test2.Base.Up => false
+ }
+ }
+}
+
+
+object Test4 {
+ sealed abstract class Base
+
+ object Base {
+ case object Down extends Base
+
+ case object Up extends Base
+ }
+
+ import Test4.Base._
+ (d1: Base, d2: Base) =>
+ (d1, d2) match {
+ case (Up, Up) | (Down, Down) => false
+ case (Down, Test4.Base.Up) => true
+ }
+}
@@ -0,0 +1 @@
+-Xfatal-warnings
@@ -0,0 +1,83 @@
+sealed abstract class Base
+
+object Test {
+ case object Up extends Base
+
+ def foo(d1: Base) =
+ d1 match {
+ case Up =>
+ }
+
+ // Sealed subtype: ModuleTypeRef <empty>.this.Test.Up.type
+ // Pattern: UniqueThisType Test.this.type
+}
+
+
+object Test1 {
+ sealed abstract class Base
+
+ object Base {
+ case object Down extends Base {
+ }
+
+ case object Up extends Base {
+ }
+
+ (d1: Base, d2: Base) =>
+ (d1, d2) match {
+ case (Up, Up) | (Down, Down) => false
+ case (Down, Up) => true
+ case (Up, Down) => false
+ }
+ }
+}
+
+object Test2 {
+ sealed abstract class Base
+
+ object Base {
+ case object Down extends Base {
+ }
+
+ case object Up extends Base {
+ }
+
+ (d1: Base, d2: Base) =>
+ (d1) match {
+ case Up | Down => false
+ }
+ }
+}
+
+object Test3 {
+ sealed abstract class Base
+
+ object Base {
+ case object Down extends Base
+
+ (d1: Base, d2: Base) =>
+ (d1, d2) match {
+ case (Down, Down) => false
+ }
+ }
+}
+
+object Test4 {
+ sealed abstract class Base
+
+ object Base {
+ case object Down extends Base {
+ }
+
+ case object Up extends Base {
+ }
+
+ }
+ import Test4.Base._
+ (d1: Base, d2: Base) =>
+ (d1, d2) match {
+ case (Up, Up) | (Down, Down) => false
+ case (Down, Test4.Base.Up) => true
+ case (Up, Down) => false
+ }
+}
@@ -43,10 +43,7 @@ mt1: u.Type = O.X.S1.type
scala> global.typeDeconstruct.show(mt1)
res0: String =
TypeRef(
- pre = TypeRef(
- pre = ThisType(object O)
- TypeSymbol(class X extends AnyRef)
- )
+ pre = SingleType(pre = ThisType(object O), object X)
TypeSymbol(class S1 extends C.this.F[T])
)

0 comments on commit dd89b00

Please sign in to comment.