Skip to content

Commit 0a416d8

Browse files
committed
Add an adaptation step in Inliner
We sometimes face a problem that we inline a reference `x: T` which upon further inlining is adapted to an expected type `x`. It only seems to occur in complicated scenarios. I could not completely narrow it down. But in any case it's safe to drop the widening cast in order to avoid a type error here. We do that in a last-effort adaptation step that's only enabled in the Inliner: Faced with an expression `x: T` and a singleton expected type `y.type` where `x.type <: y.type`, rewrite to `x`.
1 parent 2eb52e4 commit 0a416d8

File tree

3 files changed

+17
-1
lines changed

3 files changed

+17
-1
lines changed

compiler/src/dotty/tools/dotc/inlines/Inliner.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -957,6 +957,12 @@ class Inliner(val call: tpd.Tree)(using Context):
957957
case None => tree
958958
case _ =>
959959
tree
960+
961+
/** For inlining only: Given `(x: T)` with expected type `x.type`, replace the tree with `x`.
962+
*/
963+
override def healAdapt(tree: Tree, pt: Type)(using Context): Tree = (tree, pt) match
964+
case (Typed(tree1, _), pt: SingletonType) if tree1.tpe <:< pt => tree1
965+
case _ => tree
960966
end InlineTyper
961967

962968
/** Drop any side-effect-free bindings that are unused in expansion or other reachable bindings.

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4602,7 +4602,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
46024602

46034603
def recover(failure: SearchFailureType) =
46044604
if canDefineFurther(wtp) || canDefineFurther(pt) then readapt(tree)
4605-
else err.typeMismatch(tree, pt, failure)
4605+
else
4606+
val tree1 = healAdapt(tree, pt)
4607+
if tree1 ne tree then readapt(tree1)
4608+
else err.typeMismatch(tree, pt, failure)
46064609

46074610
pt match
46084611
case _: SelectionProto =>
@@ -4751,6 +4754,11 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
47514754
}
47524755
}
47534756

4757+
/** Hook for inheriting Typers to do a last-effort adaptation. If a different
4758+
* tree is returned, we will readpat that one, ptherwise we issue a type error afterwards.
4759+
*/
4760+
protected def healAdapt(tree: Tree, pt: Type)(using Context): Tree = tree
4761+
47544762
/** True if this inline typer has already issued errors */
47554763
def hasInliningErrors(using Context): Boolean = false
47564764

tests/pos/i21413.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
val x = (aaa = 1).aaa
2+
//val y = x.aaa

0 commit comments

Comments
 (0)