diff options
author | Dmitry Petrashko <dark@d-d.me> | 2016-05-27 17:50:56 +0200 |
---|---|---|
committer | Dmitry Petrashko <dark@d-d.me> | 2016-05-27 17:50:56 +0200 |
commit | a77bf9f325daf54c158c654965917ba5f3d0b30f (patch) | |
tree | 8557c353de260fe1e770728572fe2b590da144e8 | |
parent | cf2ae5ed82599b988f8c1a625e31fb03b5c1a0fe (diff) | |
parent | 0d604a4c9b21eec23cda0c82ab769c48d3d0c47a (diff) | |
download | dotty-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.scala | 5 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/TreeChecker.scala | 12 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/ReTyper.scala | 1 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 13 | ||||
-rw-r--r-- | tests/disabled/pos/t3480.scala | 2 | ||||
-rw-r--r-- | tests/pos/t9795.scala | 7 | ||||
-rw-r--r-- | tests/pos/vararg-pattern.scala | 5 | ||||
-rw-r--r-- | tests/run/correct-bind.check | 1 | ||||
-rw-r--r-- | tests/run/correct-bind.scala | 4 |
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) +} |