diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index 38ff20954c0a..a9feeae2da99 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -854,6 +854,16 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { else Assign(tree, rhs) } + /** tree @annot + * + * works differently for type trees and term trees + */ + def annotated(annot: Tree)(implicit ctx: Context): Tree = + if (tree.isTerm) + Typed(tree, TypeTree(AnnotatedType(tree.tpe.widenIfUnstable, Annotation(annot)))) + else + Annotated(tree, annot) + /** A synthetic select with that will be turned into an outer path by ExplicitOuter. * @param levels How many outer levels to select * @param tp The type of the destination of the outer path. diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala index 201609078802..eb1e5edb087c 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExpandSAMs.scala @@ -88,7 +88,7 @@ class ExpandSAMs extends MiniPhase { Bind(defaultSym, Underscore(selectorTpe)), EmptyTree, defaultValue) - val unchecked = Annotated(selector, New(ref(defn.UncheckedAnnotType))) + val unchecked = selector.annotated(New(ref(defn.UncheckedAnnotType))) cpy.Match(tree)(unchecked, cases :+ defaultCase) .subst(param.symbol :: Nil, pfParam :: Nil) // Needed because a partial function can be written as: diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 9bb608be7736..afc4e83439e1 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -546,8 +546,10 @@ trait TypeAssigner { def assignType(tree: untpd.Import, sym: Symbol)(implicit ctx: Context) = tree.withType(sym.termRef) - def assignType(tree: untpd.Annotated, arg: Tree, annot: Tree)(implicit ctx: Context) = + def assignType(tree: untpd.Annotated, arg: Tree, annot: Tree)(implicit ctx: Context) = { + assert(tree.isType) // annotating a term is done via a Typed node, can't use Annotate directly tree.withType(AnnotatedType(arg.tpe, Annotation(annot))) + } def assignType(tree: untpd.PackageDef, pid: Tree)(implicit ctx: Context) = tree.withType(pid.symbol.termRef) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 049ec5d4b5ea..c6692fdf44b1 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1658,7 +1658,7 @@ class Typer extends Namer if (ctx.mode is Mode.Type) assignType(cpy.Annotated(tree)(arg1, annot1), arg1, annot1) else { - val tpt = TypeTree(AnnotatedType(arg1.tpe, Annotation(annot1))) + val tpt = TypeTree(AnnotatedType(arg1.tpe.widenIfUnstable, Annotation(annot1))) assignType(cpy.Typed(tree)(arg1, tpt), tpt) } } diff --git a/tests/run/i4558.scala b/tests/run/i4558.scala new file mode 100644 index 000000000000..24133b5ca2d6 --- /dev/null +++ b/tests/run/i4558.scala @@ -0,0 +1,7 @@ +object Foo { + def f(z: => (Int, String)) = { + val (x, y) = z + } +} + +object Test { def main(args: Array[String]): Unit = { Foo.f { (1, "a") } } }