Skip to content

Commit

Permalink
Improve escape hatch for filter in generator
Browse files Browse the repository at this point in the history
Allow `for (x @ (_: T) <- ts)` workaround using
underscore as shown. Because the rewrite happens
after patterns are transformed, it was taken as
a straight typed pattern.
  • Loading branch information
som-snytt committed Oct 31, 2020
1 parent 200c122 commit 68a6ae9
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 9 deletions.
22 changes: 13 additions & 9 deletions src/reflect/scala/reflect/internal/TreeGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -857,10 +857,11 @@ abstract class TreeGen {
*/
private def matchVarPattern(tree: Tree): Option[(Name, Tree)] = {
import nme.{WILDCARD => WC}
val forFor = tree.hasAttachment[ForAttachment.type] // exclude user-written x @ _
tree match {
case id @ Ident(name) if name.toTermName != WC || id.isBackquoted => Some((name, TypeTree()))
case Bind(name, Ident(x)) if x.toTermName == WC => Some((name, TypeTree()))
case Bind(name, Typed(Ident(x), tpt)) if x.toTermName == WC => Some((name, tpt))
case id @ Ident(name) if name.toTermName != WC || id.isBackquoted => Some((name, TypeTree()))
case Bind(name, Ident(x)) if forFor && x.toTermName == WC => Some((name, TypeTree()))
case Bind(name, Typed(Ident(x), tpt)) if forFor && x.toTermName == WC => Some((name, tpt))
case Typed(id @ Ident(name), tpt) if name.toTermName != WC || id.isBackquoted => Some((name, tpt))
case _ => None
}
Expand Down Expand Up @@ -934,15 +935,18 @@ abstract class TreeGen {
override def transform(tree: Tree): Tree = tree match {
case Ident(name) if treeInfo.isVarPattern(tree) && name != nme.WILDCARD =>
atPos(tree.pos) {
val b = Bind(name, atPos(tree.pos.focus) (Ident(nme.WILDCARD)))
if (forFor && isPatVarWarnable) b updateAttachment NoWarnAttachment
else b
val b = Bind(name, atPos(tree.pos.focus) { Ident(nme.WILDCARD) })
if (forFor) {
b.updateAttachment(ForAttachment)
if (isPatVarWarnable) b.updateAttachment(NoWarnAttachment)
}
b
}
case Typed(id @ Ident(name), tpt) if treeInfo.isVarPattern(id) && name != nme.WILDCARD =>
atPos(tree.pos.withPoint(id.pos.point)) {
Bind(name, atPos(tree.pos.withStart(tree.pos.point)) {
Typed(Ident(nme.WILDCARD), tpt)
})
val b = Bind(name, atPos(tree.pos.withStart(tree.pos.point)) { Typed(Ident(nme.WILDCARD), tpt) })
if (forFor) b.updateAttachment(ForAttachment)
b
}
case Apply(fn @ Apply(_, _), args) =>
treeCopy.Apply(tree, transform(fn), transformTrees(args))
Expand Down
20 changes: 20 additions & 0 deletions test/files/pos/t900-workaround.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

trait T {
val xs = Seq(Some(1), None)

def f() = for (x @ (_x: Some[_]) <- xs) yield x

def g() = for (x @ (_: Some[_]) <- xs) yield x
}

/*
* The second form was not translated to a partial function:
val res1 = xs.withFilter(((check$ifrefutable$1) => check$ifrefutable$1: @scala.unchecked match {
case (x @ (_: Some[(_ @ <empty>)])) => true
case _ => false
})).map(((x: Some[(_ @ <empty>)]) => x))
*
* error: type mismatch;
* found : Some[_] => Some[Any]
* required: Option[Int] => ?
*/

0 comments on commit 68a6ae9

Please sign in to comment.