Skip to content

Commit

Permalink
SI-6646 ident or Ident is always new binding.
Browse files Browse the repository at this point in the history
The previous commit regressed in these cases:

    // 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`)

At the top level of the LHS of a <-, such identifiers represent
new bindings, not stable identifier patterns.
  • Loading branch information
retronym committed Nov 13, 2012
1 parent 8b2caf0 commit b9e3ea7
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 25 deletions.
84 changes: 59 additions & 25 deletions src/reflect/scala/reflect/internal/TreeInfo.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -245,31 +245,65 @@ abstract class TreeInfo {
isSelfConstrCall(tree1) || isSuperConstrCall(tree1) isSelfConstrCall(tree1) || isSuperConstrCall(tree1)
} }


/** Is this tree comprised of nothing but identifiers, /**
* but possibly in bindings or tuples? For instance: * 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
* foo @ (bar, (baz, quux)) * may be no Stable Identifier Patterns.
* }}} *
* * For instance:
* is a variable pattern; if the structure matches, *
* then the remainder is inevitable. * {{{
* * foo @ (bar, (baz, quux))
* The following are not variable patterns. * }}}
* *
* {{{ * is a variable pattern; if the structure matches,
* foo @ (bar, (`baz`, Quux)) * then the remainder is inevitable.
* foo @ (bar, Quux) *
* }}} * The following are not variable patterns.
*/ *
def isVarPatternDeep(tree: Tree): Boolean = tree match { * {{{
case Bind(name, pat) => isVarPatternDeep(pat) * foo @ (bar, (`baz`, quux)) // back quoted ident, not at top level
case Ident(name) => isVarPattern(tree) * foo @ (bar, Quux) // UpperCase ident, not at top level
case Apply(sel, args) => * }}}
( isReferenceToScalaMember(sel, TupleClass(args.size).name.toTermName) *
&& (args forall isVarPatternDeep) * If the pattern is a simple identifier, it is always
) * a variable pattern. For example, the following
case _ => false * 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? */ /** Is tree a variable pattern? */
Expand Down
2 changes: 2 additions & 0 deletions test/files/run/t6646.check
Original file line number Original file line Diff line number Diff line change
@@ -1,3 +1,5 @@
Found NotNull Found NotNull
Found lower Found lower
Found 2 Found 2
A single ident is always a pattern
A single ident is always a pattern
6 changes: 6 additions & 0 deletions test/files/run/t6646.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@ case object lower extends ColumnOption
object Test { object Test {
def main(args: Array[String]) { def main(args: Array[String]) {
val l = List(PrimaryKey, NotNull, lower) val l = List(PrimaryKey, NotNull, lower)

// withFilter must be generated in these
for (option @ NotNull <- l) println("Found " + option) for (option @ NotNull <- l) println("Found " + option)
for (option @ `lower` <- l) println("Found " + option) for (option @ `lower` <- l) println("Found " + option)
for ((`lower`, i) <- l.zipWithIndex) println("Found " + i) 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 b9e3ea7

Please sign in to comment.