Skip to content

Commit 1f4d125

Browse files
authored
Merge pull request scala#12513 from dotty-staging/refactor-typed
Tighten Ycheck of type ascriptions
2 parents 2bfa8e2 + 7029ee1 commit 1f4d125

File tree

3 files changed

+42
-8
lines changed

3 files changed

+42
-8
lines changed

compiler/src/dotty/tools/dotc/transform/TreeChecker.scala

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,30 @@ class TreeChecker extends Phase with SymTransformer {
422422
assert(tree.qual.tpe.isInstanceOf[ThisType], i"expect prefix of Super to be This, actual = ${tree.qual}")
423423
super.typedSuper(tree, pt)
424424

425+
override def typedTyped(tree: untpd.Typed, pt: Type)(using Context): Tree =
426+
val tpt1 = checkSimpleKinded(typedType(tree.tpt))
427+
val expr1 = tree.expr match
428+
case id: untpd.Ident if (ctx.mode is Mode.Pattern) && untpd.isVarPattern(id) && (id.name == nme.WILDCARD || id.name == nme.WILDCARD_STAR) =>
429+
tree.expr.withType(tpt1.tpe)
430+
case _ =>
431+
var pt1 = tpt1.tpe
432+
if pt1.isRepeatedParam then
433+
pt1 = pt1.translateFromRepeated(toArray = tree.expr.typeOpt.derivesFrom(defn.ArrayClass))
434+
val isAfterInlining =
435+
val inliningPhase = ctx.base.inliningPhase
436+
inliningPhase.exists && ctx.phase.id > inliningPhase.id
437+
if isAfterInlining then
438+
// The staging phase destroys in PCPCheckAndHeal the property that
439+
// tree.expr.tpe <:< pt1. A test case where this arises is run-macros/enum-nat-macro.
440+
// We should follow up why this happens. If the problem is fixed, we can
441+
// drop the isAfterInlining special case. To reproduce the problem, just
442+
// change the condition from `isAfterInlining` to `false`.
443+
typed(tree.expr)
444+
else
445+
//println(i"typing $tree, ${tree.expr.typeOpt}, $pt1, ${ctx.mode is Mode.Pattern}")
446+
typed(tree.expr, pt1)
447+
untpd.cpy.Typed(tree)(expr1, tpt1).withType(tree.typeOpt)
448+
425449
private def checkOwner(tree: untpd.Tree)(using Context): Unit = {
426450
def ownerMatches(symOwner: Symbol, ctxOwner: Symbol): Boolean =
427451
symOwner == ctxOwner ||

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -814,11 +814,9 @@ class Typer extends Namer
814814
val underlyingTreeTpe =
815815
if (isRepeatedParamType(tpt)) TypeTree(defn.SeqType.appliedTo(pt :: Nil))
816816
else tpt
817-
818817
val expr1 =
819-
if (isRepeatedParamType(tpt)) tree.expr.withType(defn.SeqType.appliedTo(pt :: Nil))
820-
else if (isWildcard) tree.expr.withType(tpt.tpe)
821-
else typed(tree.expr, tpt.tpe.widenSkolem)
818+
if isWildcard then tree.expr.withType(underlyingTreeTpe.tpe)
819+
else typed(tree.expr, underlyingTreeTpe.tpe.widenSkolem)
822820
assignType(cpy.Typed(tree)(expr1, tpt), underlyingTreeTpe)
823821
.withNotNullInfo(expr1.notNullInfo)
824822
}
@@ -844,8 +842,10 @@ class Typer extends Namer
844842
// We need to make sure its type is no longer nullable
845843
expr0.castToNonNullable
846844
else expr0
847-
val fromCls = if expr1.tpe.derivesFrom(defn.ArrayClass)
848-
then defn.ArrayClass else defn.SeqClass
845+
val fromCls =
846+
if expr1.tpe.derivesFrom(defn.ArrayClass)
847+
then defn.ArrayClass
848+
else defn.SeqClass
849849
val tpt1 = TypeTree(expr1.tpe.widen.translateToRepeated(fromCls)).withSpan(tree.tpt.span)
850850
assignType(cpy.Typed(tree)(expr1, tpt1), tpt1)
851851
}
@@ -1055,7 +1055,14 @@ class Typer extends Namer
10551055
val expr1 = ascribeType(expr, pt)
10561056
cpy.Block(block)(stats, expr1) withType expr1.tpe // no assignType here because avoid is redundant
10571057
case _ =>
1058-
Typed(tree, TypeTree(pt.simplified))
1058+
val target = pt.simplified
1059+
if tree.tpe <:< target then Typed(tree, TypeTree(pt.simplified))
1060+
else
1061+
// This case should not normally arise. It currently does arise in test cases
1062+
// pos/t4080b.scala and pos/i7067.scala. In that case, a type ascription is wrong
1063+
// and would not pass Ycheck. We have to use a cast instead. TODO: follow-up why
1064+
// the cases arise and eliminate them, if possible.
1065+
tree.cast(target)
10591066
}
10601067
def noLeaks(t: Tree): Boolean = escapingRefs(t, localSyms).isEmpty
10611068
if (noLeaks(tree)) tree
@@ -3693,7 +3700,7 @@ class Typer extends Namer
36933700
gadts.println(i"GADT-approximated $wtp ~~ $gadtApprox")
36943701
if pt.isMatchedBy(gadtApprox) then
36953702
gadts.println(i"Member selection healed by GADT approximation")
3696-
tpd.Typed(tree, TypeTree(gadtApprox))
3703+
tree.cast(gadtApprox)
36973704
else tree
36983705
else tree // other adaptations for selections are handled in typedSelect
36993706
case _ if ctx.mode.is(Mode.ImplicitsEnabled) && tree.tpe.isValueType =>

compiler/test/dotc/pos-from-tasty.blacklist

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,6 @@ rbtree.scala
1111

1212
# transitive reduction of match types
1313
i10511.scala
14+
15+
# Violates tightened condition in Retyper#typedTyped
16+
i11247.scala

0 commit comments

Comments
 (0)