Skip to content

Commit e1a4242

Browse files
committed
Check realizability of references to erased terms
1 parent 4cbd4b5 commit e1a4242

File tree

2 files changed

+46
-8
lines changed

2 files changed

+46
-8
lines changed

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

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import Names.TermName
1010
import NameKinds.{InlineAccessorName, InlineBinderName, InlineScrutineeName}
1111
import config.Printers.inlining
1212
import util.SimpleIdentityMap
13+
import CheckRealizable.{Realizable, realizability}
1314

1415
import collection.mutable
1516

@@ -417,19 +418,34 @@ class InlineReducer(inliner: Inliner)(using Context):
417418
for (bindings, expr) <- recur(cases) yield
418419
// drop unusable vals and check that no referenes to unusable symbols remain
419420
val cleanupUnusable = new TreeMap:
421+
422+
/** Whether we are currently in a type position */
423+
var inType: Boolean = false
424+
420425
override def transform(tree: Tree)(using Context): Tree =
421-
if tree.isType then return tree
422426
tree match
423427
case tree: ValDef if unusable.contains(tree.symbol) => EmptyTree
424428
case id: Ident if unusable.contains(id.symbol) =>
425-
report.error(
426-
em"""${id.symbol} is unusable in ${ctx.owner} because it refers to an erased expression
427-
|in the selector of an inline match that reduces to
428-
|
429-
|${Block(bindings, expr)}""",
430-
tree.srcPos)
429+
// This conditions allows references to erased values in type
430+
// positions provided the types of these references are
431+
// realizable. See erased-inline-product.scala and
432+
// tests/neg/erased-inline-unrealizable-path.scala.
433+
if !inType || !(realizability(id.tpe.widen) eq Realizable) then
434+
report.error(
435+
em"""${id.symbol} is unusable in ${ctx.owner} because it refers to an erased expression
436+
|in the selector of an inline match that reduces to
437+
|
438+
|${Block(bindings, expr)}""",
439+
tree.srcPos)
431440
tree
432-
case _ => super.transform(tree)
441+
case _ if tree.isType =>
442+
val saved = inType
443+
inType = true
444+
val tree1 = super.transform(tree)
445+
inType = saved
446+
tree1
447+
case _ =>
448+
super.transform(tree)
433449

434450
val bindings1 = bindings.mapConserve(cleanupUnusable.transform).collect:
435451
case mdef: MemberDef => mdef
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import scala.compiletime.erasedValue
2+
3+
class Box[T]
4+
5+
trait T:
6+
type L
7+
8+
class A extends T:
9+
type L <: Int
10+
11+
class B extends T:
12+
type L >: String
13+
14+
inline def f() =
15+
inline erasedValue[A & B] match
16+
case x: (A & B) =>
17+
val y: String = "String"
18+
val z: x.L = y
19+
z: Int
20+
21+
@main def Test =
22+
println(f().abs) // error

0 commit comments

Comments
 (0)