diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index 5946e0b07d9b..f7308c021fd3 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -422,6 +422,30 @@ class TreeChecker extends Phase with SymTransformer { assert(tree.qual.tpe.isInstanceOf[ThisType], i"expect prefix of Super to be This, actual = ${tree.qual}") super.typedSuper(tree, pt) + override def typedTyped(tree: untpd.Typed, pt: Type)(using Context): 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 _ => + var pt1 = tpt1.tpe + if pt1.isRepeatedParam then + pt1 = pt1.translateFromRepeated(toArray = tree.expr.typeOpt.derivesFrom(defn.ArrayClass)) + val isAfterInlining = + val inliningPhase = ctx.base.inliningPhase + inliningPhase.exists && ctx.phase.id > inliningPhase.id + if isAfterInlining then + // The staging phase destroys in PCPCheckAndHeal the property that + // tree.expr.tpe <:< pt1. A test case where this arises is run-macros/enum-nat-macro. + // We should follow up why this happens. If the problem is fixed, we can + // drop the isAfterInlining special case. To reproduce the problem, just + // change the condition from `isAfterInlining` to `false`. + typed(tree.expr) + else + //println(i"typing $tree, ${tree.expr.typeOpt}, $pt1, ${ctx.mode is Mode.Pattern}") + typed(tree.expr, pt1) + untpd.cpy.Typed(tree)(expr1, tpt1).withType(tree.typeOpt) + private def checkOwner(tree: untpd.Tree)(using Context): Unit = { def ownerMatches(symOwner: Symbol, ctxOwner: Symbol): Boolean = symOwner == ctxOwner || diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index cda1daafd252..9f75637e1386 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -814,11 +814,9 @@ class Typer extends Namer val underlyingTreeTpe = if (isRepeatedParamType(tpt)) TypeTree(defn.SeqType.appliedTo(pt :: Nil)) else tpt - val expr1 = - 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) + if isWildcard then tree.expr.withType(underlyingTreeTpe.tpe) + else typed(tree.expr, underlyingTreeTpe.tpe.widenSkolem) assignType(cpy.Typed(tree)(expr1, tpt), underlyingTreeTpe) .withNotNullInfo(expr1.notNullInfo) } @@ -844,8 +842,10 @@ class Typer extends Namer // We need to make sure its type is no longer nullable expr0.castToNonNullable else expr0 - val fromCls = if expr1.tpe.derivesFrom(defn.ArrayClass) - then defn.ArrayClass else defn.SeqClass + val fromCls = + if expr1.tpe.derivesFrom(defn.ArrayClass) + then defn.ArrayClass + else defn.SeqClass val tpt1 = TypeTree(expr1.tpe.widen.translateToRepeated(fromCls)).withSpan(tree.tpt.span) assignType(cpy.Typed(tree)(expr1, tpt1), tpt1) } @@ -1055,7 +1055,14 @@ class Typer extends Namer val expr1 = ascribeType(expr, pt) cpy.Block(block)(stats, expr1) withType expr1.tpe // no assignType here because avoid is redundant case _ => - Typed(tree, TypeTree(pt.simplified)) + val target = pt.simplified + if tree.tpe <:< target then Typed(tree, TypeTree(pt.simplified)) + else + // This case should not normally arise. It currently does arise in test cases + // pos/t4080b.scala and pos/i7067.scala. In that case, a type ascription is wrong + // and would not pass Ycheck. We have to use a cast instead. TODO: follow-up why + // the cases arise and eliminate them, if possible. + tree.cast(target) } def noLeaks(t: Tree): Boolean = escapingRefs(t, localSyms).isEmpty if (noLeaks(tree)) tree @@ -3693,7 +3700,7 @@ class Typer extends Namer gadts.println(i"GADT-approximated $wtp ~~ $gadtApprox") if pt.isMatchedBy(gadtApprox) then gadts.println(i"Member selection healed by GADT approximation") - tpd.Typed(tree, TypeTree(gadtApprox)) + tree.cast(gadtApprox) else tree else tree // other adaptations for selections are handled in typedSelect case _ if ctx.mode.is(Mode.ImplicitsEnabled) && tree.tpe.isValueType => diff --git a/compiler/test/dotc/pos-from-tasty.blacklist b/compiler/test/dotc/pos-from-tasty.blacklist index b0ea2e35caec..e8eaebe9f1e7 100644 --- a/compiler/test/dotc/pos-from-tasty.blacklist +++ b/compiler/test/dotc/pos-from-tasty.blacklist @@ -11,3 +11,6 @@ rbtree.scala # transitive reduction of match types i10511.scala + +# Violates tightened condition in Retyper#typedTyped +i11247.scala