Skip to content

Commit f18465b

Browse files
committed
Add realization check to erased definitions typer
1 parent 8de6d88 commit f18465b

File tree

2 files changed

+25
-0
lines changed

2 files changed

+25
-0
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,11 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
350350
if (fn.symbol != defn.ChildAnnot.primaryConstructor)
351351
// Make an exception for ChildAnnot, which should really have AnyKind bounds
352352
Checking.checkBounds(args, fn.tpe.widen.asInstanceOf[PolyType])
353+
if fn.symbol eq defn.Compiletime_erasedValue then
354+
// Check the instantiated type of erasedValue for realizibility
355+
for arg <- args do
356+
Checking.checkRealizable(arg.tpe, arg.srcPos, "type application of erasedValue")
357+
353358
fn match {
354359
case sel: Select =>
355360
val args1 = transform(args)
@@ -484,6 +489,9 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
484489
private def checkErasedDef(tree: ValOrDefDef)(using Context): Unit =
485490
if tree.symbol.is(Erased, butNot = Macro) then
486491
val tpe = tree.rhs.tpe
492+
if !tree.symbol.isOneOf(TermParamOrAccessor) && !tree.symbol.eq(defn.Compiletime_erasedValue) then // Only need to check non-parameters, since parameters have their own path checks.
493+
// We want all erased definitions to have a realizable type
494+
Checking.checkRealizable(tree.tpt.tpe, tree.srcPos, "erased type")
487495
if tpe.derivesFrom(defn.NothingClass) then
488496
report.error("`erased` definition cannot be implemented with en expression of type Nothing", tree.srcPos)
489497
else if tpe.derivesFrom(defn.NullClass) then
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// See https://github.com/lampepfl/dotty/issues/4060#issuecomment-445808377
2+
import scala.language.experimental.erasedDefinitions
3+
4+
object App {
5+
trait A { type L >: Any}
6+
//def upcast(a: A, x: Any): a.L = x
7+
def upcast(erased a: A)(x: Any): a.L = x
8+
//lazy val p: A { type L <: Nothing } = p
9+
erased val p: A { type L <: Nothing } = p // error
10+
def coerce(x: Any): Int = upcast(p)(x)
11+
12+
def coerceInline(x: Any): Int = upcast(compiletime.erasedValue[A {type L <: Nothing}])(x) // error
13+
14+
def main(args: Array[String]): Unit = {
15+
println(coerce("Uh oh!"))
16+
}
17+
}

0 commit comments

Comments
 (0)