From ca58eaa9cea5eb571ab74d9752ab67a939d4bd9f Mon Sep 17 00:00:00 2001 From: Olivier Blanvillain Date: Mon, 4 Sep 2017 14:03:01 +0200 Subject: [PATCH 1/8] Update outdated comment (ReTyper does not override typedCase) --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 0d4fb6419ba2..53010558966e 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1001,9 +1001,7 @@ class Typer extends Namer cases mapconserve (typedCase(_, pt, selType, gadtSyms)) } - /** Type a case. Overridden in ReTyper, that's why it's separate from - * typedCases. - */ + /** Type a case. */ def typedCase(tree: untpd.CaseDef, pt: Type, selType: Type, gadtSyms: Set[Symbol])(implicit ctx: Context): CaseDef = track("typedCase") { val originalCtx = ctx From cec6307ffa8193490a9c42de6d6d611cfafb5824 Mon Sep 17 00:00:00 2001 From: Olivier Blanvillain Date: Wed, 6 Sep 2017 11:45:03 +0200 Subject: [PATCH 2/8] Update ReTyper to Ycheck patterns --- .../tools/dotc/transform/TreeChecker.scala | 3 --- .../src/dotty/tools/dotc/typer/ReTyper.scala | 26 ++++++++++++++++--- .../dotty/tools/dotc/typer/TypeAssigner.scala | 1 - 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index f59d418d110d..e6567c5b31e1 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -261,9 +261,6 @@ class TreeChecker extends Phase with SymTransformer { override def typedUnadapted(tree: untpd.Tree, pt: Type)(implicit ctx: Context): tpd.Tree = { val res = tree match { - case _: untpd.UnApply => - // can't recheck patterns - tree.asInstanceOf[tpd.Tree] case _: untpd.TypedSplice | _: untpd.Thicket | _: EmptyValDef[_] => super.typedUnadapted(tree) case _ if tree.isType => diff --git a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala index b5ca1c651443..f88889464274 100644 --- a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala +++ b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala @@ -5,6 +5,7 @@ import core._ import Contexts._ import Types._ import Symbols._ +import StdNames._ import Decorators._ import typer.ProtoTypes._ import ast.{tpd, untpd} @@ -24,9 +25,12 @@ import config.Printers.typr class ReTyper extends Typer { import tpd._ + private def assertTyped(tree: untpd.Tree)(implicit ctx: Context): Unit = + assert(tree.hasType, i"$tree ${tree.getClass} ${tree.uniqueId}") + /** 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}") + assertTyped(tree) tree.withType(tree.typeOpt) } @@ -34,8 +38,7 @@ class ReTyper extends Typer { promote(tree) override def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = { - assert(tree.hasType, tree) - // a qualifier cannot be a pattern + assertTyped(tree) val qual1 = typed(tree.qualifier, AnySelectionProto)(ctx.retractMode(Mode.Pattern)) untpd.cpy.Select(tree)(qual1, tree.name).withType(tree.typeOpt) } @@ -49,11 +52,22 @@ class ReTyper extends Typer { override def typedSuper(tree: untpd.Super, pt: Type)(implicit ctx: Context): Tree = promote(tree) + override def typedTyped(tree: untpd.Typed, pt: Type)(implicit ctx: Context): Tree = { + assertTyped(tree) + val type1 = checkSimpleKinded(typedType(tree.tpt)) + val tree1 = tree.expr match { + case id: untpd.Ident if (ctx.mode is Mode.Pattern) && untpd.isVarPattern(id) && (id.name == nme.WILDCARD || id.name == nme.WILDCARD_STAR) => + tree.expr.withType(type1.tpe) + case _ => typed(tree.expr) + } + untpd.cpy.Typed(tree)(tree1, type1).withType(tree.typeOpt) + } + override def typedTypeTree(tree: untpd.TypeTree, pt: Type)(implicit ctx: Context): TypeTree = promote(tree) override def typedBind(tree: untpd.Bind, pt: Type)(implicit ctx: Context): Bind = { - assert(tree.hasType) + assertTyped(tree) val body1 = typed(tree.body, pt) untpd.cpy.Bind(tree)(tree.name, body1).withType(tree.typeOpt) } @@ -65,6 +79,10 @@ class ReTyper extends Typer { untpd.cpy.UnApply(tree)(fun1, implicits1, patterns1).withType(tree.tpe) } + override def typedUnApply(tree: untpd.Apply, selType: Type)(implicit ctx: Context): Tree = { + typedApply(tree, selType) + } + override def localDummy(cls: ClassSymbol, impl: untpd.Template)(implicit ctx: Context) = impl.symbol override def retrieveSym(tree: untpd.Tree)(implicit ctx: Context): Symbol = tree.symbol diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 36241ff23e12..d92dacee2cfe 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -265,7 +265,6 @@ trait TypeAssigner { * - typed child trees it needs to access to cpmpute that type, * - any further information it needs to access to compute that type. */ - def assignType(tree: untpd.Ident, tp: Type)(implicit ctx: Context) = tree.withType(tp) From a89407cc80994f3d37b70f4585b1f3c993c992bf Mon Sep 17 00:00:00 2001 From: Olivier Blanvillain Date: Wed, 6 Sep 2017 14:25:42 +0200 Subject: [PATCH 3/8] Fix inline of unapply nodes --- .../dotty/tools/dotc/typer/Applications.scala | 5 ++-- tests/pos/inline-i1773.scala | 14 +++++++++++ tests/pos/inline-t9232a.scala | 11 +++++++++ tests/pos/inline-t9232b.scala | 23 +++++++++++++++++++ 4 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 tests/pos/inline-i1773.scala create mode 100644 tests/pos/inline-t9232a.scala create mode 100644 tests/pos/inline-t9232b.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 4936986e88d3..418a222cf82d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -955,9 +955,10 @@ trait Applications extends Compatibility { self: Typer with Dynamic => } val dummyArg = dummyTreeOfType(ownType) val unapplyApp = typedExpr(untpd.TypedSplice(Apply(unapplyFn, dummyArg :: Nil))) - val unapplyImplicits = unapplyApp match { + def unapplyImplicits(unapp: Tree = unapplyApp): List[Tree] = unapp match { case Apply(Apply(unapply, `dummyArg` :: Nil), args2) => assert(args2.nonEmpty); args2 case Apply(unapply, `dummyArg` :: Nil) => Nil + case Inlined(u, _, _) => unapplyImplicits(u) } var argTypes = unapplyArgs(unapplyApp.tpe, unapplyFn, args, tree.pos) @@ -981,7 +982,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => List.fill(argTypes.length - args.length)(WildcardType) } val unapplyPatterns = (bunchedArgs, argTypes).zipped map (typed(_, _)) - val result = assignType(cpy.UnApply(tree)(unapplyFn, unapplyImplicits, unapplyPatterns), ownType) + val result = assignType(cpy.UnApply(tree)(unapplyFn, unapplyImplicits(), unapplyPatterns), ownType) unapp.println(s"unapply patterns = $unapplyPatterns") if ((ownType eq selType) || ownType.isError) result else tryWithClassTag(Typed(result, TypeTree(ownType)), selType) diff --git a/tests/pos/inline-i1773.scala b/tests/pos/inline-i1773.scala new file mode 100644 index 000000000000..b24f8c34d2e1 --- /dev/null +++ b/tests/pos/inline-i1773.scala @@ -0,0 +1,14 @@ +object Test { + implicit class Foo(sc: StringContext) { + object q { + inline def unapply(arg: Any): Option[(Any, Any)] = + Some((sc.parts(0), sc.parts(1))) + } + } + + def main(args: Array[String]): Unit = { + val q"class $name extends $parent" = new Object + println(name) + println(parent) + } +} diff --git a/tests/pos/inline-t9232a.scala b/tests/pos/inline-t9232a.scala new file mode 100644 index 000000000000..41f34adbe026 --- /dev/null +++ b/tests/pos/inline-t9232a.scala @@ -0,0 +1,11 @@ +final class Foo(val value: Int) + +object Foo { + inline def unapply(foo: Foo): Some[Int] = Some(foo.value) +} + +object Test { + def transformTree(f: Foo): Any = f match { + case Foo(_) => ??? + } +} diff --git a/tests/pos/inline-t9232b.scala b/tests/pos/inline-t9232b.scala new file mode 100644 index 000000000000..3cee6875097f --- /dev/null +++ b/tests/pos/inline-t9232b.scala @@ -0,0 +1,23 @@ +final class Foo(val value: Int) + +object Foo { + inline def unapplySeq(foo: Foo): Some[Seq[Int]] = Some(List(foo.value)) +} + +sealed trait Tree +case class Node1(foo: Foo) extends Tree +case class Node2() extends Tree + +object Test { + def transformTree(tree: Tree): Any = tree match { + case Node1(Foo(_: _*)) => ??? + } + + def transformTree2(tree: Tree): Any = tree match { + case Node1(Foo(1, _: _*)) => ??? + } + + def transformTree3(tree: Tree): Any = tree match { + case Node1(Foo(x, _: _*)) => ??? + } +} From e9837a25f3b11b0a9869ab6e11c151fb012d0fed Mon Sep 17 00:00:00 2001 From: Olivier Blanvillain Date: Mon, 11 Sep 2017 14:11:53 +0200 Subject: [PATCH 4/8] Fix inline-t2425.scala by removing partial pattern matching --- compiler/src/dotty/tools/dotc/typer/Inliner.scala | 2 +- tests/pos/inline-t2425.scala | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 tests/pos/inline-t2425.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 0645e3efd0db..587cc3f5153f 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -478,7 +478,7 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) { paramProxy.get(tree.tpe) match { case Some(t) if tree.isTerm && t.isSingleton => singleton(t).withPos(tree.pos) case Some(t) if tree.isType => TypeTree(t).withPos(tree.pos) - case None => tree + case _ => tree } case _ => tree }} diff --git a/tests/pos/inline-t2425.scala b/tests/pos/inline-t2425.scala new file mode 100644 index 000000000000..f5a1602a4a46 --- /dev/null +++ b/tests/pos/inline-t2425.scala @@ -0,0 +1,8 @@ +object Test extends App { + inline def foo[T](bar: T) = { + bar match { + case _ => () + } + } + foo(Array(1, 2)) +} From 11b3e2cdcc6aa5a5e1623319aeafc612039d6c52 Mon Sep 17 00:00:00 2001 From: Olivier Blanvillain Date: Tue, 12 Sep 2017 16:58:41 +0200 Subject: [PATCH 5/8] Fix inline-named-typeargs.scala by handling named type parameter patterns --- compiler/src/dotty/tools/dotc/ast/TreeInfo.scala | 4 ++-- tests/pos/inline-named-typeargs.scala | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 tests/pos/inline-named-typeargs.scala diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index f9d76d083cbd..ece6e7891b06 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -517,8 +517,8 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => val (meth, targs, argss) = decomposeCall(fn) (meth, targs, argss :+ args) case TypeApply(fn, targs) => - val (meth, Nil, Nil) = decomposeCall(fn) - (meth, targs, Nil) + val (meth, targss, args) = decomposeCall(fn) + (meth, targs ++ targss, args) case _ => (tree, Nil, Nil) } diff --git a/tests/pos/inline-named-typeargs.scala b/tests/pos/inline-named-typeargs.scala new file mode 100644 index 000000000000..9d2c5b3f4af9 --- /dev/null +++ b/tests/pos/inline-named-typeargs.scala @@ -0,0 +1,5 @@ +object t1 { + inline def construct[Elem, Coll[_]](xs: List[Elem]): Coll[Elem] = ??? + + val xs3 = construct[Coll = List](List(1, 2, 3)) +} From 30097fe9268c7302ebf839751f92d2cf35ceea57 Mon Sep 17 00:00:00 2001 From: Olivier Blanvillain Date: Fri, 8 Sep 2017 17:30:20 +0200 Subject: [PATCH 6/8] Fix inline-i2570.scala by removing special treatment of InfixOpBlock --- compiler/src/dotty/tools/dotc/typer/Typer.scala | 8 +------- tests/pos/inline-i2570.scala | 4 ++++ 2 files changed, 5 insertions(+), 7 deletions(-) create mode 100644 tests/pos/inline-i2570.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 53010558966e..b30f56b1f7f0 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -664,13 +664,7 @@ class Typer extends Namer def typedBlock(tree: untpd.Block, pt: Type)(implicit ctx: Context) = track("typedBlock") { val (exprCtx, stats1) = typedBlockStats(tree.stats) - val ept = - if (tree.isInstanceOf[untpd.InfixOpBlock]) - // Right-binding infix operations are expanded to InfixBlocks, which may be followed by arguments. - // Example: `(a /: bs)(op)` expands to `{ val x = a; bs./:(x) } (op)` where `{...}` is an InfixBlock. - pt - else pt.notApplied - val expr1 = typedExpr(tree.expr, ept)(exprCtx) + val expr1 = typedExpr(tree.expr, pt.notApplied)(exprCtx) ensureNoLocalRefs( cpy.Block(tree)(stats1, expr1).withType(expr1.tpe), pt, localSyms(stats1)) } diff --git a/tests/pos/inline-i2570.scala b/tests/pos/inline-i2570.scala new file mode 100644 index 000000000000..d68ae1dc8934 --- /dev/null +++ b/tests/pos/inline-i2570.scala @@ -0,0 +1,4 @@ +object Test { + inline def sum2(ys: List[Int]): Int = (1 /: ys)(_ + _) + val h1: ((List[Int]) => Int) = sum2 +} From 954e080d05743122f07aeca01a2ab40516628392 Mon Sep 17 00:00:00 2001 From: Olivier Blanvillain Date: Thu, 18 Jan 2018 11:06:12 +0100 Subject: [PATCH 7/8] Address review --- compiler/src/dotty/tools/dotc/typer/Applications.scala | 4 ++-- compiler/src/dotty/tools/dotc/typer/ReTyper.scala | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 418a222cf82d..29073874c152 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -955,7 +955,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => } val dummyArg = dummyTreeOfType(ownType) val unapplyApp = typedExpr(untpd.TypedSplice(Apply(unapplyFn, dummyArg :: Nil))) - def unapplyImplicits(unapp: Tree = unapplyApp): List[Tree] = unapp match { + def unapplyImplicits(unapp: Tree): List[Tree] = unapp match { case Apply(Apply(unapply, `dummyArg` :: Nil), args2) => assert(args2.nonEmpty); args2 case Apply(unapply, `dummyArg` :: Nil) => Nil case Inlined(u, _, _) => unapplyImplicits(u) @@ -982,7 +982,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => List.fill(argTypes.length - args.length)(WildcardType) } val unapplyPatterns = (bunchedArgs, argTypes).zipped map (typed(_, _)) - val result = assignType(cpy.UnApply(tree)(unapplyFn, unapplyImplicits(), unapplyPatterns), ownType) + val result = assignType(cpy.UnApply(tree)(unapplyFn, unapplyImplicits(unapplyApp), unapplyPatterns), ownType) unapp.println(s"unapply patterns = $unapplyPatterns") if ((ownType eq selType) || ownType.isError) result else tryWithClassTag(Typed(result, TypeTree(ownType)), selType) diff --git a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala index f88889464274..be4218b72bf8 100644 --- a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala +++ b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala @@ -54,13 +54,13 @@ class ReTyper extends Typer { override def typedTyped(tree: untpd.Typed, pt: Type)(implicit ctx: Context): Tree = { assertTyped(tree) - val type1 = checkSimpleKinded(typedType(tree.tpt)) - val tree1 = tree.expr match { + val tpt1 = checkSimpleKinded(typedType(tree.tpt)) + val expr1 = tree.expr match { case id: untpd.Ident if (ctx.mode is Mode.Pattern) && untpd.isVarPattern(id) && (id.name == nme.WILDCARD || id.name == nme.WILDCARD_STAR) => - tree.expr.withType(type1.tpe) + tree.expr.withType(tpt1.tpe) case _ => typed(tree.expr) } - untpd.cpy.Typed(tree)(tree1, type1).withType(tree.typeOpt) + untpd.cpy.Typed(tree)(expr1, tpt1).withType(tree.typeOpt) } override def typedTypeTree(tree: untpd.TypeTree, pt: Type)(implicit ctx: Context): TypeTree = From a506b50f343cca6ebbd5848f66f422ca90e1655f Mon Sep 17 00:00:00 2001 From: Olivier Blanvillain Date: Thu, 18 Jan 2018 11:54:01 +0100 Subject: [PATCH 8/8] Relax Ycheck's checkNotRepeated See i3248.scala for an example of a non case class pattern leaking scala.annotation.internal.Repeated. --- compiler/src/dotty/tools/dotc/transform/TreeChecker.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index e6567c5b31e1..9e0639a944f6 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -288,7 +288,7 @@ class TreeChecker extends Phase with SymTransformer { } def checkNotRepeated(tree: Tree)(implicit ctx: Context): tree.type = { - def allowedRepeated = (tree.symbol.flags is Case) && tree.tpe.widen.isRepeatedParam + def allowedRepeated = tree.tpe.widen.isRepeatedParam assert(!tree.tpe.widen.isRepeatedParam || allowedRepeated, i"repeated parameter type not allowed here: $tree") tree