diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2013-01-31 00:33:19 +0100 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2013-02-07 21:58:47 +0100 |
commit | 55c9b9c280ac9bc36bbac09397c7646f8dcf4583 (patch) | |
tree | cdfc1cd396eaba78f0150968634722bcb8df8bd7 /src/compiler | |
parent | 81d8f9d3da656cfb05f125ba7cf70ca51a477240 (diff) | |
download | scala-55c9b9c280ac9bc36bbac09397c7646f8dcf4583.tar.gz scala-55c9b9c280ac9bc36bbac09397c7646f8dcf4583.tar.bz2 scala-55c9b9c280ac9bc36bbac09397c7646f8dcf4583.zip |
SI-6146 More accurate prefixes for sealed subtypes.
When analysing exhaustivity/reachability of type tests
and equality tests, the pattern matcher must construct
a set of sealed subtypes based on the prefix of the
static type of and the set of sealed descendent symbols
of that type.
Previously, it was using `memberType` for this purpose.
In simple cases, this is sufficient:
scala> class C { class I1; object O { class I2 } }; object D extends C
defined class C
defined module D
scala> typeOf[D.type] memberType typeOf[C#I1].typeSymbol
res0: u.Type = D.I1
But, as reported in this bug, it fails when there is an
additional level of nesting:
scala> typeOf[D.type] memberType typeOf[c.O.I2 forSome { val c: C }].typeSymbol
res5: u.Type = C.O.I2
This commit introduces `nestedMemberType`, which uses `memberType`
recursively up the prefix chain prefix chain.
scala> nestedMemberType(typeOf[c.O.I2 forSome { val c: C }].typeSymbol, typeOf[D.type], typeOf[C].typeSymbol)
res6: u.Type = D.O.Id
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/scala/tools/nsc/interpreter/IMain.scala | 4 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala | 4 |
2 files changed, 6 insertions, 2 deletions
diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala index a55f0af116..bed8570bd0 100644 --- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala +++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala @@ -262,7 +262,9 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends protected def newCompiler(settings: Settings, reporter: Reporter): ReplGlobal = { settings.outputDirs setSingleOutput virtualDirectory settings.exposeEmptyPackage.value = true - new Global(settings, reporter) with ReplGlobal + new Global(settings, reporter) with ReplGlobal { + override def toString: String = "<global>" + } } /** Parent classloader. Overridable. */ diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala index 452957745a..4a765ea22e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala @@ -2818,7 +2818,9 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // compare to the fully known type `tp` (modulo abstract types), // so that we can rule out stuff like: sealed trait X[T]; class XInt extends X[Int] --> XInt not valid when enumerating X[String] // however, must approximate abstract types in - val subTp = appliedType(pre.memberType(sym), sym.typeParams.map(_ => WildcardType)) + + val memberType = nestedMemberType(sym, pre, tpApprox.typeSymbol.owner) + val subTp = appliedType(memberType, sym.typeParams.map(_ => WildcardType)) val subTpApprox = typer.infer.approximateAbstracts(subTp) // TODO: needed? // patmatDebug("subtp"+(subTpApprox <:< tpApprox, subTpApprox, tpApprox)) if (subTpApprox <:< tpApprox) Some(checkableType(subTp)) |