diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index 4180cd4e6a88..c3630d74ec3d 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -519,8 +519,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/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index f59d418d110d..9e0639a944f6 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 => @@ -291,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 diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 155893ad6573..8d2733878d91 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -957,9 +957,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): 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) @@ -983,7 +984,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/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/compiler/src/dotty/tools/dotc/typer/ReTyper.scala b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala index b5ca1c651443..be4218b72bf8 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 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(tpt1.tpe) + case _ => typed(tree.expr) + } + untpd.cpy.Typed(tree)(expr1, tpt1).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 99a53ba8b870..3ba549c9d301 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) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 34802d197556..fc56b72eef12 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -664,8 +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 = 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)) } @@ -996,9 +995,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 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-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 +} 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)) +} 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)) +} 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, _: _*)) => ??? + } +}