Skip to content

Commit a77bf9f

Browse files
committed
Merge pull request #1283 from felixmulder/topic/fix-seq-binding-patternmatcher
Fix #1276: `_` binding in patternmatcher
2 parents cf2ae5e + 0d604a4 commit a77bf9f

File tree

9 files changed

+37
-13
lines changed

9 files changed

+37
-13
lines changed

src/dotty/tools/dotc/transform/PatternMatcher.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,6 +1094,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
10941094
*/
10951095
object WildcardPattern {
10961096
def unapply(pat: Tree): Boolean = pat match {
1097+
case Typed(_, arg) if arg.tpe.isRepeatedParam => true
10971098
case Bind(nme.WILDCARD, WildcardPattern()) => true // don't skip when binding an interesting symbol!
10981099
case t if (tpd.isWildcardArg(t)) => true
10991100
case x: Ident => isVarPattern(x)
@@ -1157,8 +1158,8 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
11571158

11581159
object TypeBound {
11591160
def unapply(tree: Tree): Option[Type] = tree match {
1160-
case Typed(_, _) => Some(tree.typeOpt)
1161-
case _ => None
1161+
case Typed(_, arg) if !arg.tpe.isRepeatedParam => Some(tree.typeOpt)
1162+
case _ => None
11621163
}
11631164
}
11641165

src/dotty/tools/dotc/transform/TreeChecker.scala

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,12 @@ class TreeChecker extends Phase with SymTransformer {
119119
val prevPhase = ctx.phase.prev // can be a mini-phase
120120
val squahsedPhase = ctx.squashed(prevPhase)
121121
ctx.echo(s"checking ${ctx.compilationUnit} after phase ${squahsedPhase}")
122-
val checkingCtx = ctx.fresh.setReporter(new ThrowingReporter(ctx.reporter))
122+
123+
val checkingCtx = ctx
124+
.fresh
125+
.setMode(Mode.ImplicitsEnabled)
126+
.setReporter(new ThrowingReporter(ctx.reporter))
127+
123128
val checker = new Checker(previousPhases(phasesToRun.toList)(ctx))
124129
try checker.typedExpr(ctx.compilationUnit.tpdTree)(checkingCtx)
125130
catch {
@@ -307,7 +312,9 @@ class TreeChecker extends Phase with SymTransformer {
307312
}.apply(tp)
308313

309314
def checkNotRepeated(tree: Tree)(implicit ctx: Context): tree.type = {
310-
assert(!tree.tpe.widen.isRepeatedParam, i"repeated parameter type not allowed here: $tree")
315+
def allowedRepeated = (tree.symbol.flags is Case) && tree.tpe.widen.isRepeatedParam
316+
317+
assert(!tree.tpe.widen.isRepeatedParam || allowedRepeated, i"repeated parameter type not allowed here: $tree")
311318
tree
312319
}
313320

@@ -322,6 +329,7 @@ class TreeChecker extends Phase with SymTransformer {
322329
assert(tree.isTerm || !ctx.isAfterTyper, tree.show + " at " + ctx.phase)
323330
assert(tree.isType || !needsSelect(tree.tpe), i"bad type ${tree.tpe} for $tree # ${tree.uniqueId}")
324331
assertDefined(tree)
332+
325333
checkNotRepeated(super.typedIdent(tree, pt))
326334
}
327335

src/dotty/tools/dotc/typer/ReTyper.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import config.Printers
2323
class ReTyper extends Typer {
2424
import tpd._
2525

26+
/** Checks that the given tree has been typed */
2627
protected def promote(tree: untpd.Tree)(implicit ctx: Context): tree.ThisTree[Type] = {
2728
assert(tree.hasType, i"$tree ${tree.getClass} ${tree.uniqueId}")
2829
tree.withType(tree.typeOpt)

src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -420,14 +420,19 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
420420
case _ => ifExpr
421421
}
422422
def ascription(tpt: Tree, isWildcard: Boolean) = {
423+
val underlyingTreeTpe =
424+
if (isRepeatedParamType(tpt)) TypeTree(defn.SeqType.appliedTo(pt :: Nil))
425+
else tpt
426+
423427
val expr1 =
424-
if (isWildcard) tree.expr.withType(tpt.tpe)
428+
if (isRepeatedParamType(tpt)) tree.expr.withType(defn.SeqType.appliedTo(pt :: Nil))
429+
else if (isWildcard) tree.expr.withType(tpt.tpe)
425430
else typed(tree.expr, tpt.tpe.widenSkolem)
426-
assignType(cpy.Typed(tree)(expr1, tpt), tpt)
431+
assignType(cpy.Typed(tree)(expr1, tpt), underlyingTreeTpe)
427432
}
428433
if (untpd.isWildcardStarArg(tree))
429434
cases(
430-
ifPat = ascription(TypeTree(defn.SeqType.appliedTo(pt :: Nil)), isWildcard = true),
435+
ifPat = ascription(TypeTree(defn.RepeatedParamType.appliedTo(pt)), isWildcard = true),
431436
ifExpr = seqToRepeated(typedExpr(tree.expr, defn.SeqType)),
432437
wildName = nme.WILDCARD_STAR)
433438
else {
@@ -975,7 +980,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
975980
typed(untpd.Bind(tree.name, arg).withPos(tree.pos), arg.tpe) :: Nil)
976981
case _ =>
977982
val flags = if (tree.isType) BindDefinedType else EmptyFlags
978-
val sym = ctx.newSymbol(ctx.owner, tree.name, flags, body1.tpe, coord = tree.pos)
983+
val sym = ctx.newSymbol(ctx.owner, tree.name, flags | Case, body1.tpe, coord = tree.pos)
979984
assignType(cpy.Bind(tree)(tree.name, body1), sym)
980985
}
981986
}

tests/disabled/pos/t3480.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
object Test {
22
val List(_: _*) = List(1)
3-
val Array( who, what : _* ) = "Eclipse plugin cannot not handle this" split (" ")
3+
val Array(who, what: _*) = "Eclipse plugin cannot not handle this" split (" ")
44
}

tests/pos/t9795.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
case class A(v: Int)
2+
class B(v: Int) extends A(v)
3+
4+
object Test {
5+
val a = new B(1)
6+
a match { case A(_) => 1 }
7+
}

tests/pos/vararg-pattern.scala

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
object Test {
2-
32
List(1, 2, 3, 4) match {
43
case List(1, 2, xs: _*) =>
54
val ys: Seq[Int] = xs
65
println(ys)
76
}
8-
val List(1, 2, x: _*) = List(1, 2, 3, 4)
97

8+
val List(1, 2, x: _*) = List(1, 2, 3, 4)
109
}
11-
12-

tests/run/correct-bind.check

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Vector(second, third)

tests/run/correct-bind.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
object Test extends dotty.runtime.LegacyApp {
2+
val Array(who, what: _*) = "first second third" split (" ")
3+
println(what)
4+
}

0 commit comments

Comments
 (0)