diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala | 46 | ||||
-rw-r--r-- | src/intellij/compiler.iml.SAMPLE | 2 | ||||
-rw-r--r-- | src/intellij/reflect.iml.SAMPLE | 25 | ||||
-rw-r--r-- | src/intellij/scala-lang.ipr.SAMPLE | 1 | ||||
-rw-r--r-- | test/files/neg/virtpatmat_unreach_select.check | 4 | ||||
-rw-r--r-- | test/files/neg/virtpatmat_unreach_select.flags | 1 | ||||
-rw-r--r-- | test/files/neg/virtpatmat_unreach_select.scala | 12 | ||||
-rw-r--r-- | test/files/pos/t5738.scala | 8 | ||||
-rw-r--r-- | test/files/pos/t5742.scala | 8 | ||||
-rw-r--r-- | test/files/run/t5816.check | 1 | ||||
-rw-r--r-- | test/files/run/t5816.scala | 17 | ||||
-rw-r--r-- | test/files/run/t5840.scala | 7 | ||||
-rw-r--r-- | test/files/run/t5881.check | 2 | ||||
-rw-r--r-- | test/files/run/t5881.scala | 6 |
14 files changed, 127 insertions, 13 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala index 68522c727f..4e8f416b16 100644 --- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala +++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala @@ -1429,6 +1429,12 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // (Select(codegen._asInstanceOf(testedBinder, expectedTp), outer)) OBJ_EQ expectedOuter // } + // TODO: improve, e.g., for constants + def sameValue(a: Tree, b: Tree): Boolean = (a eq b) || ((a, b) match { + case (_ : Ident, _ : Ident) => a.symbol eq b.symbol + case _ => false + }) + // returns (tree, tests), where `tree` will be used to refer to `root` in `tests` abstract class TreeMakersToConds(val root: Symbol) { @@ -1476,13 +1482,6 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // patmatDebug("accumSubst: "+ accumSubst) } - - // TODO: improve, e.g., for constants - def sameValue(a: Tree, b: Tree): Boolean = (a eq b) || ((a, b) match { - case (_ : Ident, _ : Ident) => a.symbol eq b.symbol - case _ => false - }) - // hashconsing trees (modulo value-equality) def unique(t: Tree, tpOverride: Type = NoType): Tree = trees find (a => a.correspondsStructure(t)(sameValue)) match { @@ -2075,7 +2074,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL // a literal constant becomes ConstantType(Constant(v)) when the type allows it (roughly, anyval + string + null) // equality between variables: SingleType(x) (note that pattern variables cannot relate to each other -- it's always patternVar == nonPatternVar) object Const { - def resetUniques() = {_nextTypeId = 0; _nextValueId = 0; uniques.clear()} // patmatDebug("RESET") + def resetUniques() = {_nextTypeId = 0; _nextValueId = 0; uniques.clear() ; trees.clear() } // patmatDebug("RESET") private var _nextTypeId = 0 def nextTypeId = {_nextTypeId += 1; _nextTypeId} @@ -2093,6 +2092,27 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL uniques(tp) = fresh fresh }) + + private val trees = collection.mutable.HashSet.empty[Tree] + + // hashconsing trees (modulo value-equality) + private[SymbolicMatchAnalysis] def uniqueTpForTree(t: Tree): Type = + // a new type for every unstable symbol -- only stable value are uniqued + // technically, an unreachable value may change between cases + // thus, the failure of a case that matches on a mutable value does not exclude the next case succeeding + // (and thuuuuus, the latter case must be considered reachable) + if (!t.symbol.isStable) t.tpe.narrow + else trees find (a => a.correspondsStructure(t)(sameValue)) match { + case Some(orig) => + // patmatDebug("unique: "+ (orig, orig.tpe)) + orig.tpe + case _ => + // duplicate, don't mutate old tree (TODO: use a map tree -> type instead?) + val treeWithNarrowedType = t.duplicate setType t.tpe.narrow + // patmatDebug("uniqued: "+ (t, t.tpe, treeWithNarrowedType.tpe)) + trees += treeWithNarrowedType + treeWithNarrowedType.tpe + } } sealed abstract class Const extends AbsConst { @@ -2181,11 +2201,13 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL case Literal(c) => if (c.tpe.typeSymbol == UnitClass) c.tpe else ConstantType(c) - case p if p.symbol.isStable => + case Ident(_) if p.symbol.isStable => + // for Idents, can encode uniqueness of symbol as uniqueness of the corresponding singleton type + // for Selects, which are handled by the next case, the prefix of the select varies independently of the symbol (see pos/virtpatmat_unreach_select.scala) singleType(tp.prefix, p.symbol) - case x => - // TODO: better type - x.tpe.narrow + case _ => + // patmatDebug("unique type for "+(p, Const.uniqueTpForTree(p))) + Const.uniqueTpForTree(p) } val toString = diff --git a/src/intellij/compiler.iml.SAMPLE b/src/intellij/compiler.iml.SAMPLE index 75c7653018..e3278d0311 100644 --- a/src/intellij/compiler.iml.SAMPLE +++ b/src/intellij/compiler.iml.SAMPLE @@ -19,7 +19,7 @@ <orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="module" module-name="library" /> <orderEntry type="library" name="lib" level="project" /> + <orderEntry type="module" module-name="reflect" /> <orderEntry type="library" name="ant" level="application" /> </component> </module> - diff --git a/src/intellij/reflect.iml.SAMPLE b/src/intellij/reflect.iml.SAMPLE new file mode 100644 index 0000000000..7f14a00699 --- /dev/null +++ b/src/intellij/reflect.iml.SAMPLE @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="JAVA_MODULE" version="4"> + <component name="FacetManager"> + <facet type="scala" name="Scala"> + <configuration> + <option name="compilerLibraryLevel" value="Project" /> + <option name="compilerLibraryName" value="compiler-locker" /> + <option name="compilerOptions" value="-sourcepath /Users/luc/scala/git/src/reflect" /> + <option name="maximumHeapSize" value="1536" /> + <option name="vmOptions" value="-Xms1536m -Xss1m -XX:MaxPermSize=128M -d32 -server -XX:+UseParallelGC" /> + </configuration> + </facet> + </component> + <component name="NewModuleRootManager" inherit-compiler-output="true"> + <exclude-output /> + <content url="file://$MODULE_DIR$/../reflect"> + <sourceFolder url="file://$MODULE_DIR$/../reflect" isTestSource="false" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + <orderEntry type="library" name="lib" level="project" /> + <orderEntry type="module" module-name="library" /> + </component> +</module> + diff --git a/src/intellij/scala-lang.ipr.SAMPLE b/src/intellij/scala-lang.ipr.SAMPLE index 43d6362708..c5f7b904c8 100644 --- a/src/intellij/scala-lang.ipr.SAMPLE +++ b/src/intellij/scala-lang.ipr.SAMPLE @@ -200,6 +200,7 @@ <module fileurl="file://$PROJECT_DIR$/library.iml" filepath="$PROJECT_DIR$/library.iml" /> <module fileurl="file://$PROJECT_DIR$/manual.iml" filepath="$PROJECT_DIR$/manual.iml" /> <module fileurl="file://$PROJECT_DIR$/partest.iml" filepath="$PROJECT_DIR$/partest.iml" /> + <module fileurl="file://$PROJECT_DIR$/reflect.iml" filepath="$PROJECT_DIR$/reflect.iml" /> <module fileurl="file://$PROJECT_DIR$/scala.iml" filepath="$PROJECT_DIR$/scala.iml" /> <module fileurl="file://$PROJECT_DIR$/scalap.iml" filepath="$PROJECT_DIR$/scalap.iml" /> <module fileurl="file://$PROJECT_DIR$/swing.iml" filepath="$PROJECT_DIR$/swing.iml" /> diff --git a/test/files/neg/virtpatmat_unreach_select.check b/test/files/neg/virtpatmat_unreach_select.check new file mode 100644 index 0000000000..3771971020 --- /dev/null +++ b/test/files/neg/virtpatmat_unreach_select.check @@ -0,0 +1,4 @@ +virtpatmat_unreach_select.scala:10: error: unreachable code + case WARNING.id => // unreachable + ^ +one error found diff --git a/test/files/neg/virtpatmat_unreach_select.flags b/test/files/neg/virtpatmat_unreach_select.flags new file mode 100644 index 0000000000..85d8eb2ba2 --- /dev/null +++ b/test/files/neg/virtpatmat_unreach_select.flags @@ -0,0 +1 @@ +-Xfatal-warnings diff --git a/test/files/neg/virtpatmat_unreach_select.scala b/test/files/neg/virtpatmat_unreach_select.scala new file mode 100644 index 0000000000..c46ff15453 --- /dev/null +++ b/test/files/neg/virtpatmat_unreach_select.scala @@ -0,0 +1,12 @@ +class Test { + object severity extends Enumeration + class Severity(val id: Int) extends severity.Value + val INFO = new Severity(0) + val WARNING = new Severity(1) + + (0: Int) match { + case WARNING.id => + case INFO.id => // reachable + case WARNING.id => // unreachable + } +} diff --git a/test/files/pos/t5738.scala b/test/files/pos/t5738.scala new file mode 100644 index 0000000000..b8755ed66e --- /dev/null +++ b/test/files/pos/t5738.scala @@ -0,0 +1,8 @@ +import scala.reflect.runtime.universe._ + +object Test extends App { + def f[T](a: T, b: T) = { + reify(a.toString + b) + reify(a + b.toString) + } +}
\ No newline at end of file diff --git a/test/files/pos/t5742.scala b/test/files/pos/t5742.scala new file mode 100644 index 0000000000..3d3125b5d3 --- /dev/null +++ b/test/files/pos/t5742.scala @@ -0,0 +1,8 @@ +import scala.reflect.runtime.universe._ + +object Test extends App { + def foo[T](a: T) = reify { + val x1 = a + val x2 = reify(a) + } +}
\ No newline at end of file diff --git a/test/files/run/t5816.check b/test/files/run/t5816.check new file mode 100644 index 0000000000..920b64a50d --- /dev/null +++ b/test/files/run/t5816.check @@ -0,0 +1 @@ +5.+(Test.this.y)
diff --git a/test/files/run/t5816.scala b/test/files/run/t5816.scala new file mode 100644 index 0000000000..f0279e5703 --- /dev/null +++ b/test/files/run/t5816.scala @@ -0,0 +1,17 @@ +import scala.reflect.runtime.universe._ +import scala.reflect.runtime.{currentMirror => cm} +import scala.tools.reflect.ToolBox + +object Test extends App { + val toolbox = cm.mkToolBox() + + def printSource[T](expr: Expr[T]) { + val ttree = toolbox typeCheck expr.tree + println(ttree.toString) + } + + var y = 3 + printSource(reify { + 5 + y + }) +}
\ No newline at end of file diff --git a/test/files/run/t5840.scala b/test/files/run/t5840.scala new file mode 100644 index 0000000000..da036d5122 --- /dev/null +++ b/test/files/run/t5840.scala @@ -0,0 +1,7 @@ +import scala.reflect.runtime.universe._ + +object Test extends App { + reify { + class C[T <: String with Singleton] + } +}
\ No newline at end of file diff --git a/test/files/run/t5881.check b/test/files/run/t5881.check new file mode 100644 index 0000000000..477fb935a8 --- /dev/null +++ b/test/files/run/t5881.check @@ -0,0 +1,2 @@ +ClassTag[class scala.collection.immutable.List]
+ClassTag[class scala.collection.immutable.List]
diff --git a/test/files/run/t5881.scala b/test/files/run/t5881.scala new file mode 100644 index 0000000000..01bee29181 --- /dev/null +++ b/test/files/run/t5881.scala @@ -0,0 +1,6 @@ +import scala.reflect.ClassTag + +object Test extends App { + println(implicitly[ClassTag[List[T forSome {type T <: List[T]}]]]) + println(implicitly[ClassTag[List[Any]]]) +}
\ No newline at end of file |