diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-03-27 22:46:23 -0700 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-03-27 22:46:23 -0700 |
commit | 66fb8118f9c48c6be703e4e89aaaf8e76e430d5a (patch) | |
tree | 3ff5955b14d84ece8b3b6d506f12b61a9a72ed78 | |
parent | f2a74c5ebda2a6d3438203572059a4cee509002d (diff) | |
parent | dd89b006218d76a74d0185392d5e427c0867a33c (diff) | |
download | scala-66fb8118f9c48c6be703e4e89aaaf8e76e430d5a.tar.gz scala-66fb8118f9c48c6be703e4e89aaaf8e76e430d5a.tar.bz2 scala-66fb8118f9c48c6be703e4e89aaaf8e76e430d5a.zip |
Merge pull request #2292 from retronym/ticket/7285
SI-7285 Fix match analysis with nested objects
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/patmat/Logic.scala | 3 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Types.scala | 7 | ||||
-rw-r--r-- | test/files/neg/t7285.check | 13 | ||||
-rw-r--r-- | test/files/neg/t7285.flags | 1 | ||||
-rw-r--r-- | test/files/neg/t7285.scala | 55 | ||||
-rw-r--r-- | test/files/pos/t7285a.flags | 1 | ||||
-rw-r--r-- | test/files/pos/t7285a.scala | 83 | ||||
-rw-r--r-- | test/files/run/t6146b.check | 11 | ||||
-rw-r--r-- | test/files/run/t6146b.scala | 3 |
9 files changed, 170 insertions, 7 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala index 22eabb6d6f..0fab48028e 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala @@ -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" } } -}
\ No newline at end of file +} diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index a27b37dae5..a2c9f1fadf 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -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 diff --git a/test/files/neg/t7285.check b/test/files/neg/t7285.check new file mode 100644 index 0000000000..108f4292a8 --- /dev/null +++ b/test/files/neg/t7285.check @@ -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 diff --git a/test/files/neg/t7285.flags b/test/files/neg/t7285.flags new file mode 100644 index 0000000000..e8fb65d50c --- /dev/null +++ b/test/files/neg/t7285.flags @@ -0,0 +1 @@ +-Xfatal-warnings
\ No newline at end of file diff --git a/test/files/neg/t7285.scala b/test/files/neg/t7285.scala new file mode 100644 index 0000000000..14121d92b1 --- /dev/null +++ b/test/files/neg/t7285.scala @@ -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 + } +} diff --git a/test/files/pos/t7285a.flags b/test/files/pos/t7285a.flags new file mode 100644 index 0000000000..e8fb65d50c --- /dev/null +++ b/test/files/pos/t7285a.flags @@ -0,0 +1 @@ +-Xfatal-warnings
\ No newline at end of file diff --git a/test/files/pos/t7285a.scala b/test/files/pos/t7285a.scala new file mode 100644 index 0000000000..34e79c741b --- /dev/null +++ b/test/files/pos/t7285a.scala @@ -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 + } +} diff --git a/test/files/run/t6146b.check b/test/files/run/t6146b.check index b664d1152a..49ff70697e 100644 --- a/test/files/run/t6146b.check +++ b/test/files/run/t6146b.check @@ -37,8 +37,15 @@ memType: (sub: u.Type, scrut: u.Type)u.Type scala> -scala> memType(S1, fTpe) -res0: u.Type = O.X.S1.type +scala> val mt1 = memType(S1, fTpe) +mt1: u.Type = O.X.S1.type + +scala> global.typeDeconstruct.show(mt1) +res0: String = +TypeRef( + pre = SingleType(pre = ThisType(object O), object X) + TypeSymbol(class S1 extends C.this.F[T]) +) scala> memType(S2, fTpe) res1: u.Type = O.S2 diff --git a/test/files/run/t6146b.scala b/test/files/run/t6146b.scala index adcd40d2ee..e63709aa9d 100644 --- a/test/files/run/t6146b.scala +++ b/test/files/run/t6146b.scala @@ -31,7 +31,8 @@ val fTpe = typeOf[O.type].decl(newTermName("foo")).paramss.head.head.tpe def memType(sub: Type, scrut: Type): Type = nestedMemberType(sub.typeSymbol, scrut.prefix, scrut.typeSymbol.owner) -memType(S1, fTpe) +val mt1 = memType(S1, fTpe) +global.typeDeconstruct.show(mt1) memType(S2, fTpe) memType(S3, fTpe) memType(S4, fTpe) |