Skip to content

Commit 1d7ae0c

Browse files
committed
Change how erased classes are treated as erased arguments
Parameters that are erased classes are now marked `erased` at Typer phase (with an annotation), and in later phases, they are not taken into account when considering erasedness.
1 parent 42d4d09 commit 1d7ae0c

File tree

4 files changed

+35
-2
lines changed

4 files changed

+35
-2
lines changed

compiler/src/dotty/tools/dotc/cc/Setup.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import transform.Recheck.*
1212
import CaptureSet.IdentityCaptRefMap
1313
import Synthetics.isExcluded
1414
import util.Property
15+
import dotty.tools.dotc.core.Annotations.Annotation
1516

1617
/** A tree traverser that prepares a compilation unit to be capture checked.
1718
* It does the following:
@@ -259,7 +260,11 @@ extends tpd.TreeTraverser:
259260
private def expandThrowsAlias(tp: Type)(using Context) = tp match
260261
case AppliedType(tycon, res :: exc :: Nil) if tycon.typeSymbol == defn.throwsAlias =>
261262
// hard-coded expansion since $throws aliases in stdlib are defined with `?=>` rather than `?->`
262-
defn.FunctionOf(defn.CanThrowClass.typeRef.appliedTo(exc) :: Nil, res, isContextual = true)
263+
defn.FunctionOf(
264+
AnnotatedType(defn.CanThrowClass.typeRef.appliedTo(exc), Annotation(defn.ErasedParamAnnot, defn.CanThrowClass.span)) :: Nil,
265+
res,
266+
isContextual = true
267+
)
263268
case _ => tp
264269

265270
private def expandThrowsAliases(using Context) = new TypeMap:

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3920,7 +3920,7 @@ object Types {
39203920
companion.eq(ContextualMethodType)
39213921

39223922
override def erasedParams(using Context): List[Boolean] =
3923-
paramInfos.map(p => p.hasAnnotation(defn.ErasedParamAnnot) || p.isErasedClass)
3923+
paramInfos.map(p => p.hasAnnotation(defn.ErasedParamAnnot))
39243924

39253925
protected def prefixString: String = companion.prefixString
39263926
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,6 +1355,12 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
13551355
val mt = appDef.symbol.info.asInstanceOf[MethodType]
13561356
if (mt.isParamDependent)
13571357
report.error(em"$mt is an illegal function type because it has inter-parameter dependencies", tree.srcPos)
1358+
// Restart typechecking if there are erased classes that we want to mark erased
1359+
if mt.erasedParams.zip(mt.paramInfos.map(_.isErasedClass)).exists((paramErased, classErased) => classErased && !paramErased) then
1360+
val newParams = params3.zipWithConserve(mt.paramInfos.map(_.isErasedClass)) { (arg, isErasedClass) =>
1361+
if isErasedClass then arg.withAddedFlags(Erased) else arg
1362+
}
1363+
return typedDependent(newParams)
13581364
val resTpt = TypeTree(mt.nonDependentResultApprox).withSpan(body.span)
13591365
val typeArgs = appDef.termParamss.head.map(_.tpt) :+ resTpt
13601366
val core =
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
erased class A
2+
3+
erased class B(val x: Int) extends A
4+
5+
type T = (x: A, y: Int) => Int
6+
7+
type TSub[-T <: A] = (erased x: T, y: Int) => Int
8+
9+
def useT(f: T) = f(new A, 5)
10+
11+
def useTSub(f: TSub[B]) = f(new B(5), 5)
12+
13+
@main def Test() =
14+
val tInfer = (x: A, y: Int) => y + 1
15+
val tExpl: T = (x, y) => y + 1
16+
assert(useT((erased x, y) => y + 1) == 6)
17+
assert(useT(tInfer) == 6)
18+
assert(useT(tExpl) == 6)
19+
20+
val tSub: TSub[A] = (x, y) => y + 1
21+
assert(useT(tSub) == 6)
22+
assert(useTSub(tSub) == 6)

0 commit comments

Comments
 (0)