Permalink
Browse files

Merge pull request #1606 from retronym/ticket/6646

SI-6646 Fix regression in for desugaring.
  • Loading branch information...
2 parents 8b59843 + 45cf745 commit ea87ecbe818f7445156d6c2548e429a8ca54595d @adriaanm adriaanm committed Nov 13, 2012
@@ -285,7 +285,7 @@ abstract class TreeBuilder {
def makeGenerator(pos: Position, pat: Tree, valeq: Boolean, rhs: Tree): Enumerator = {
val pat1 = patvarTransformer.transform(pat)
val rhs1 =
- if (valeq || treeInfo.isVariablePattern(pat)) rhs
+ if (valeq || treeInfo.isVarPatternDeep(pat)) rhs
else makeFilter(rhs, pat1.duplicate, nme.CHECK_IF_REFUTABLE_STRING)
if (valeq) ValEq(pos, pat1, rhs1)
@@ -245,6 +245,68 @@ abstract class TreeInfo {
isSelfConstrCall(tree1) || isSuperConstrCall(tree1)
}
+ /**
+ * Does this tree represent an irrefutable pattern match
+ * in the position `for { <tree> <- expr }` based only
+ * on information at the `parser` phase? To qualify, there
+ * may be no subtree that will be interpreted as a
+ * Stable Identifier Pattern.
+ *
+ * For instance:
+ *
+ * {{{
+ * foo @ (bar, (baz, quux))
+ * }}}
+ *
+ * is a variable pattern; if the structure matches,
+ * then the remainder is inevitable.
+ *
+ * The following are not variable patterns.
+ *
+ * {{{
+ * foo @ (bar, (`baz`, quux)) // back quoted ident, not at top level
+ * foo @ (bar, Quux) // UpperCase ident, not at top level
+ * }}}
+ *
+ * If the pattern is a simple identifier, it is always
+ * a variable pattern. For example, the following
+ * introduce new bindings:
+ *
+ * {{{
+ * for { X <- xs } yield X
+ * for { `backquoted` <- xs } yield `backquoted`
+ * }}}
+ *
+ * Note that this differs from a case clause:
+ *
+ * {{{
+ * object X
+ * scrut match {
+ * case X => // case _ if scrut == X
+ * }
+ * }}}
+ *
+ * Background: [[https://groups.google.com/d/msg/scala-internals/qwa_XOw_7Ks/IktkeTBYqg0J]]
+ *
+ */
+ def isVarPatternDeep(tree: Tree): Boolean = {
+ def isVarPatternDeep0(tree: Tree): Boolean = {
+ tree match {
+ case Bind(name, pat) => isVarPatternDeep0(pat)
+ case Ident(name) => isVarPattern(tree)
+ case Apply(sel, args) =>
+ ( isReferenceToScalaMember(sel, TupleClass(args.size).name.toTermName)
+ && (args forall isVarPatternDeep0)
+ )
+ case _ => false
+ }
+ }
+ tree match {
+ case Ident(name) => true
+ case _ => isVarPatternDeep0(tree)
+ }
+ }
+
/** Is tree a variable pattern? */
def isVarPattern(pat: Tree): Boolean = pat match {
case x: Ident => !x.isBackquoted && nme.isVariableName(x.name)
@@ -330,24 +392,6 @@ abstract class TreeInfo {
case _ => false
}
- /** Is this tree comprised of nothing but identifiers,
- * but possibly in bindings or tuples? For instance
- *
- * foo @ (bar, (baz, quux))
- *
- * is a variable pattern; if the structure matches,
- * then the remainder is inevitable.
- */
- def isVariablePattern(tree: Tree): Boolean = tree match {
- case Bind(name, pat) => isVariablePattern(pat)
- case Ident(name) => true
- case Apply(sel, args) =>
- ( isReferenceToScalaMember(sel, TupleClass(args.size).name.toTermName)
- && (args forall isVariablePattern)
- )
- case _ => false
- }
-
/** Is this argument node of the form <expr> : _* ?
*/
def isWildcardStarArg(tree: Tree): Boolean = tree match {
@@ -0,0 +1,5 @@
+Found NotNull
+Found lower
+Found 2
+A single ident is always a pattern
+A single ident is always a pattern
@@ -0,0 +1,19 @@
+sealed trait ColumnOption
+case object NotNull extends ColumnOption
+case object PrimaryKey extends ColumnOption
+case object lower extends ColumnOption
+
+object Test {
+ def main(args: Array[String]) {
+ val l = List(PrimaryKey, NotNull, lower)
+
+ // withFilter must be generated in these
+ for (option @ NotNull <- l) println("Found " + option)
+ for (option @ `lower` <- l) println("Found " + option)
+ for ((`lower`, i) <- l.zipWithIndex) println("Found " + i)
+
+ // no withFilter
+ for (X <- List("A single ident is always a pattern")) println(X)
+ for (`x` <- List("A single ident is always a pattern")) println(`x`)
+ }
+}

0 comments on commit ea87ecb

Please sign in to comment.