aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Petrashko <dark@d-d.me>2016-05-27 17:50:56 +0200
committerDmitry Petrashko <dark@d-d.me>2016-05-27 17:50:56 +0200
commita77bf9f325daf54c158c654965917ba5f3d0b30f (patch)
tree8557c353de260fe1e770728572fe2b590da144e8
parentcf2ae5ed82599b988f8c1a625e31fb03b5c1a0fe (diff)
parent0d604a4c9b21eec23cda0c82ab769c48d3d0c47a (diff)
downloaddotty-a77bf9f325daf54c158c654965917ba5f3d0b30f.tar.gz
dotty-a77bf9f325daf54c158c654965917ba5f3d0b30f.tar.bz2
dotty-a77bf9f325daf54c158c654965917ba5f3d0b30f.zip
Merge pull request #1283 from felixmulder/topic/fix-seq-binding-patternmatcher
Fix #1276: `_` binding in patternmatcher
-rw-r--r--src/dotty/tools/dotc/transform/PatternMatcher.scala5
-rw-r--r--src/dotty/tools/dotc/transform/TreeChecker.scala12
-rw-r--r--src/dotty/tools/dotc/typer/ReTyper.scala1
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala13
-rw-r--r--tests/disabled/pos/t3480.scala2
-rw-r--r--tests/pos/t9795.scala7
-rw-r--r--tests/pos/vararg-pattern.scala5
-rw-r--r--tests/run/correct-bind.check1
-rw-r--r--tests/run/correct-bind.scala4
9 files changed, 37 insertions, 13 deletions
diff --git a/src/dotty/tools/dotc/transform/PatternMatcher.scala b/src/dotty/tools/dotc/transform/PatternMatcher.scala
index 24d0e9ae0..d77dcaae4 100644
--- a/src/dotty/tools/dotc/transform/PatternMatcher.scala
+++ b/src/dotty/tools/dotc/transform/PatternMatcher.scala
@@ -1094,6 +1094,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
*/
object WildcardPattern {
def unapply(pat: Tree): Boolean = pat match {
+ case Typed(_, arg) if arg.tpe.isRepeatedParam => true
case Bind(nme.WILDCARD, WildcardPattern()) => true // don't skip when binding an interesting symbol!
case t if (tpd.isWildcardArg(t)) => true
case x: Ident => isVarPattern(x)
@@ -1157,8 +1158,8 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
object TypeBound {
def unapply(tree: Tree): Option[Type] = tree match {
- case Typed(_, _) => Some(tree.typeOpt)
- case _ => None
+ case Typed(_, arg) if !arg.tpe.isRepeatedParam => Some(tree.typeOpt)
+ case _ => None
}
}
diff --git a/src/dotty/tools/dotc/transform/TreeChecker.scala b/src/dotty/tools/dotc/transform/TreeChecker.scala
index a27c9c5f3..0dce0fd36 100644
--- a/src/dotty/tools/dotc/transform/TreeChecker.scala
+++ b/src/dotty/tools/dotc/transform/TreeChecker.scala
@@ -119,7 +119,12 @@ class TreeChecker extends Phase with SymTransformer {
val prevPhase = ctx.phase.prev // can be a mini-phase
val squahsedPhase = ctx.squashed(prevPhase)
ctx.echo(s"checking ${ctx.compilationUnit} after phase ${squahsedPhase}")
- val checkingCtx = ctx.fresh.setReporter(new ThrowingReporter(ctx.reporter))
+
+ val checkingCtx = ctx
+ .fresh
+ .setMode(Mode.ImplicitsEnabled)
+ .setReporter(new ThrowingReporter(ctx.reporter))
+
val checker = new Checker(previousPhases(phasesToRun.toList)(ctx))
try checker.typedExpr(ctx.compilationUnit.tpdTree)(checkingCtx)
catch {
@@ -307,7 +312,9 @@ class TreeChecker extends Phase with SymTransformer {
}.apply(tp)
def checkNotRepeated(tree: Tree)(implicit ctx: Context): tree.type = {
- assert(!tree.tpe.widen.isRepeatedParam, i"repeated parameter type not allowed here: $tree")
+ def allowedRepeated = (tree.symbol.flags is Case) && tree.tpe.widen.isRepeatedParam
+
+ assert(!tree.tpe.widen.isRepeatedParam || allowedRepeated, i"repeated parameter type not allowed here: $tree")
tree
}
@@ -322,6 +329,7 @@ class TreeChecker extends Phase with SymTransformer {
assert(tree.isTerm || !ctx.isAfterTyper, tree.show + " at " + ctx.phase)
assert(tree.isType || !needsSelect(tree.tpe), i"bad type ${tree.tpe} for $tree # ${tree.uniqueId}")
assertDefined(tree)
+
checkNotRepeated(super.typedIdent(tree, pt))
}
diff --git a/src/dotty/tools/dotc/typer/ReTyper.scala b/src/dotty/tools/dotc/typer/ReTyper.scala
index 225451886..a4f92271a 100644
--- a/src/dotty/tools/dotc/typer/ReTyper.scala
+++ b/src/dotty/tools/dotc/typer/ReTyper.scala
@@ -23,6 +23,7 @@ import config.Printers
class ReTyper extends Typer {
import tpd._
+ /** Checks that the given tree has been typed */
protected def promote(tree: untpd.Tree)(implicit ctx: Context): tree.ThisTree[Type] = {
assert(tree.hasType, i"$tree ${tree.getClass} ${tree.uniqueId}")
tree.withType(tree.typeOpt)
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 23e7cdb7b..4f27912f1 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -420,14 +420,19 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
case _ => ifExpr
}
def ascription(tpt: Tree, isWildcard: Boolean) = {
+ val underlyingTreeTpe =
+ if (isRepeatedParamType(tpt)) TypeTree(defn.SeqType.appliedTo(pt :: Nil))
+ else tpt
+
val expr1 =
- if (isWildcard) tree.expr.withType(tpt.tpe)
+ if (isRepeatedParamType(tpt)) tree.expr.withType(defn.SeqType.appliedTo(pt :: Nil))
+ else if (isWildcard) tree.expr.withType(tpt.tpe)
else typed(tree.expr, tpt.tpe.widenSkolem)
- assignType(cpy.Typed(tree)(expr1, tpt), tpt)
+ assignType(cpy.Typed(tree)(expr1, tpt), underlyingTreeTpe)
}
if (untpd.isWildcardStarArg(tree))
cases(
- ifPat = ascription(TypeTree(defn.SeqType.appliedTo(pt :: Nil)), isWildcard = true),
+ ifPat = ascription(TypeTree(defn.RepeatedParamType.appliedTo(pt)), isWildcard = true),
ifExpr = seqToRepeated(typedExpr(tree.expr, defn.SeqType)),
wildName = nme.WILDCARD_STAR)
else {
@@ -975,7 +980,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
typed(untpd.Bind(tree.name, arg).withPos(tree.pos), arg.tpe) :: Nil)
case _ =>
val flags = if (tree.isType) BindDefinedType else EmptyFlags
- val sym = ctx.newSymbol(ctx.owner, tree.name, flags, body1.tpe, coord = tree.pos)
+ val sym = ctx.newSymbol(ctx.owner, tree.name, flags | Case, body1.tpe, coord = tree.pos)
assignType(cpy.Bind(tree)(tree.name, body1), sym)
}
}
diff --git a/tests/disabled/pos/t3480.scala b/tests/disabled/pos/t3480.scala
index ba2e1a4b8..55dde6634 100644
--- a/tests/disabled/pos/t3480.scala
+++ b/tests/disabled/pos/t3480.scala
@@ -1,4 +1,4 @@
object Test {
val List(_: _*) = List(1)
- val Array( who, what : _* ) = "Eclipse plugin cannot not handle this" split (" ")
+ val Array(who, what: _*) = "Eclipse plugin cannot not handle this" split (" ")
}
diff --git a/tests/pos/t9795.scala b/tests/pos/t9795.scala
new file mode 100644
index 000000000..1bb23840e
--- /dev/null
+++ b/tests/pos/t9795.scala
@@ -0,0 +1,7 @@
+case class A(v: Int)
+class B(v: Int) extends A(v)
+
+object Test {
+ val a = new B(1)
+ a match { case A(_) => 1 }
+}
diff --git a/tests/pos/vararg-pattern.scala b/tests/pos/vararg-pattern.scala
index 314d6460f..430973a28 100644
--- a/tests/pos/vararg-pattern.scala
+++ b/tests/pos/vararg-pattern.scala
@@ -1,12 +1,9 @@
object Test {
-
List(1, 2, 3, 4) match {
case List(1, 2, xs: _*) =>
val ys: Seq[Int] = xs
println(ys)
}
- val List(1, 2, x: _*) = List(1, 2, 3, 4)
+ val List(1, 2, x: _*) = List(1, 2, 3, 4)
}
-
-
diff --git a/tests/run/correct-bind.check b/tests/run/correct-bind.check
new file mode 100644
index 000000000..eb5597af8
--- /dev/null
+++ b/tests/run/correct-bind.check
@@ -0,0 +1 @@
+Vector(second, third)
diff --git a/tests/run/correct-bind.scala b/tests/run/correct-bind.scala
new file mode 100644
index 000000000..9f45012bf
--- /dev/null
+++ b/tests/run/correct-bind.scala
@@ -0,0 +1,4 @@
+object Test extends dotty.runtime.LegacyApp {
+ val Array(who, what: _*) = "first second third" split (" ")
+ println(what)
+}