diff options
author | Paul Phillips <paulp@improving.org> | 2012-03-19 18:26:55 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-03-19 20:13:36 -0700 |
commit | c82ecabad6fc050411495f3fd50c3bf79ac7e96e (patch) | |
tree | e6498f4f2843bd14e16de365079601093af1abb5 /src | |
parent | 4f565de67fcaf3818c1bcbe204e254014077e1de (diff) | |
download | scala-c82ecabad6fc050411495f3fd50c3bf79ac7e96e.tar.gz scala-c82ecabad6fc050411495f3fd50c3bf79ac7e96e.tar.bz2 scala-c82ecabad6fc050411495f3fd50c3bf79ac7e96e.zip |
Finally did something about broken irrefutability.
The parser has always been confused about tuple patterns in
for comprehensions. It thinks it can fail to recognize an
irrefutable pattern and have it removed in refchecks, but it
is sadly mistaken, because the unnecessary filter has a tendency
to fail the compile in typer.
Look more intently for irrefutable patterns and don't insert
the unnecessary filter. Closes SI-5589, SI-1336.
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/reflect/internal/TreeInfo.scala | 20 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala | 34 |
2 files changed, 34 insertions, 20 deletions
diff --git a/src/compiler/scala/reflect/internal/TreeInfo.scala b/src/compiler/scala/reflect/internal/TreeInfo.scala index 769d7a9ed1..ce3de94335 100644 --- a/src/compiler/scala/reflect/internal/TreeInfo.scala +++ b/src/compiler/scala/reflect/internal/TreeInfo.scala @@ -17,7 +17,7 @@ abstract class TreeInfo { val global: SymbolTable import global._ - import definitions.{ isVarArgsList, isCastSymbol, ThrowableClass } + import definitions.{ isVarArgsList, isCastSymbol, ThrowableClass, TupleClass } /* Does not seem to be used. Not sure what it does anyway. def isOwnerDefinition(tree: Tree): Boolean = tree match { @@ -312,6 +312,24 @@ 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 { diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index 0d2fbc5372..80c258e456 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -262,29 +262,25 @@ abstract class TreeBuilder { else if (stats.length == 1) stats.head else Block(stats.init, stats.last) + def makeFilter(tree: Tree, condition: Tree, scrutineeName: String): Tree = { + val cases = List( + CaseDef(condition, EmptyTree, Literal(Constant(true))), + CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(Constant(false))) + ) + val matchTree = makeVisitor(cases, false, scrutineeName) + + atPos(tree.pos)(Apply(Select(tree, nme.filter), matchTree :: Nil)) + } + /** Create tree for for-comprehension generator <val pat0 <- rhs0> */ def makeGenerator(pos: Position, pat: Tree, valeq: Boolean, rhs: Tree): Enumerator = { val pat1 = patvarTransformer.transform(pat) val rhs1 = - if (valeq) rhs - else matchVarPattern(pat1) match { - case Some(_) => - rhs - case None => - atPos(rhs.pos) { - Apply( - Select(rhs, nme.filter), - List( - makeVisitor( - List( - CaseDef(pat1.duplicate, EmptyTree, Literal(Constant(true))), - CaseDef(Ident(nme.WILDCARD), EmptyTree, Literal(Constant(false)))), - false, - nme.CHECK_IF_REFUTABLE_STRING - ))) - } - } - if (valeq) ValEq(pos, pat1, rhs1) else ValFrom(pos, pat1, rhs1) + if (valeq || treeInfo.isVariablePattern(pat)) rhs + else makeFilter(rhs, pat1.duplicate, nme.CHECK_IF_REFUTABLE_STRING) + + if (valeq) ValEq(pos, pat1, rhs1) + else ValFrom(pos, pat1, rhs1) } def makeParam(pname: TermName, tpe: Tree) = |