Skip to content

Commit 52ec016

Browse files
committed
WIP handle erased classes
1 parent 5a9ef2d commit 52ec016

File tree

5 files changed

+45
-19
lines changed

5 files changed

+45
-19
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1909,18 +1909,22 @@ object desugar {
19091909
}
19101910

19111911
/** Make erased function definitions use only ValDefs */
1912-
def makeErasedFunctionValDefs(tree: FunctionWithMods, pt: Type)(using Context): Function = {
1913-
val isErased = tree.isErased
1912+
def makeErasedFunctionValDefs(tree: Function, pt: Type)(using Context): Function = {
19141913
val Function(args, result) = tree
1914+
val flags = tree match
1915+
case tree: FunctionWithMods => tree.mods.flags
1916+
case _ => EmptyFlags
19151917
args match {
19161918
case (_ : ValDef) :: _ => tree // ValDef case can be easily handled
1917-
case _ if !isErased.contains(true) => tree // not erased
19181919
case _ if !ctx.mode.is(Mode.Type) => tree
19191920
case _ =>
19201921
val applyVParams = args.zipWithIndex.map {
1921-
case (p, n) => makeSyntheticParameter(n + 1, p).withAddedFlags(tree.mods.flags)
1922+
case (p, n) => makeSyntheticParameter(n + 1, p).withAddedFlags(flags)
19221923
}
1923-
untpd.FunctionWithMods(applyVParams, tree.body, tree.mods, isErased)
1924+
tree match
1925+
case tree: FunctionWithMods =>
1926+
untpd.FunctionWithMods(applyVParams, tree.body, tree.mods, tree.isErased)
1927+
case _ => untpd.Function(applyVParams, result)
19241928
}
19251929
}
19261930

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1097,7 +1097,7 @@ class Definitions {
10971097
val fnType =
10981098
FunctionType(args.length, isContextual, isErased = isErasedFn).appliedTo(args ::: resultType :: Nil)
10991099
if isErasedFn then
1100-
val mt = MethodType.companion(isContextual, false, isErased)(args, resultType)
1100+
val mt = MethodType.companion(isContextual, false, erasedParams)(args, resultType)
11011101
RefinedType(fnType, nme.apply, mt)
11021102
else fnType
11031103
def unapply(ft: Type)(using Context): Option[(List[Type], Type, Boolean, List[Boolean])] = {

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import util.common._
2424
import typer.ProtoTypes.NoViewsAllowed
2525
import collection.mutable.ListBuffer
2626

27+
import reporting._
28+
2729
/** Denotations represent the meaning of symbols and named types.
2830
* The following diagram shows how the principal types of denotations
2931
* and their denoting entities relate to each other. Lines ending in
@@ -542,11 +544,7 @@ object Denotations {
542544
tp2 match
543545
case tp2: MethodType
544546
if TypeComparer.matchingMethodParams(tp1, tp2)
545-
&& tp1.isImplicitMethod == tp2.isImplicitMethod
546-
&& tp1.isErasedMethod == tp2.isErasedMethod
547-
&& (!tp1.isErasedMethod || ( // same set of erased parameters
548-
tp1.companion.asInstanceOf[ErasedMethodCompanion].isErased ==
549-
tp2.companion.asInstanceOf[ErasedMethodCompanion].isErased)) =>
547+
&& tp1.isImplicitMethod == tp2.isImplicitMethod =>
550548
val resType = infoMeet(tp1.resType, tp2.resType.subst(tp2, tp1), safeIntersection)
551549
if resType.exists then
552550
tp1.derivedLambdaType(mergeParamNames(tp1, tp2), tp1.paramInfos, resType)

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

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import scala.annotation.internal.sharable
4343
import scala.annotation.threadUnsafe
4444

4545
import dotty.tools.dotc.transform.SymUtils._
46+
import dotty.tools.dotc.transform.TypeUtils.isErasedClass
4647

4748
object Types {
4849

@@ -3926,6 +3927,26 @@ object Types {
39263927
}
39273928
newCompanion(paramNames)(paramInfosExp, resultTypeExp)
39283929

3930+
// Mark erased classes as erased parameters as well.
3931+
def markErasedClasses(using Context): MethodType =
3932+
val isErasedClass = paramInfos.map(_.isErasedClass)
3933+
if isErasedClass.contains(true) then companion match
3934+
case c: ErasedMethodCompanion =>
3935+
val isErased = c.isErased.zipWithConserve(isErasedClass) { (a, b) => a || b }
3936+
if isErased == c.isErased then this
3937+
else MethodType.companion(
3938+
isContextual = isContextualMethod,
3939+
isImplicit = isImplicitMethod,
3940+
isErased = isErased
3941+
)(paramNames)(paramInfosExp, resultTypeExp)
3942+
case _ =>
3943+
MethodType.companion(
3944+
isContextual = isContextualMethod,
3945+
isImplicit = isImplicitMethod,
3946+
isErased = isErasedClass
3947+
)(paramNames)(paramInfosExp, resultTypeExp)
3948+
else this
3949+
39293950
protected def prefixString: String = companion.prefixString
39303951
}
39313952

@@ -4047,7 +4068,7 @@ object Types {
40474068
}
40484069
private def erasedMt(t: String, isErased: List[Boolean]) =
40494070
s"Erased${t}(${isErased.map(if _ then "erased _" else "_").mkString(", ")})"
4050-
class ErasedMethodCompanion(prefixString: String, val isErased: List[Boolean])
4071+
sealed abstract class ErasedMethodCompanion(prefixString: String, val isErased: List[Boolean])
40514072
extends MethodTypeCompanion(erasedMt(prefixString, isErased))
40524073

40534074
class ErasedMethodType(isErased: List[Boolean]) extends ErasedMethodCompanion("MethodType", isErased)

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

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,7 +1301,6 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
13011301
val numArgs = args.length
13021302
val isContextual = funFlags.is(Given)
13031303
val isImpure = funFlags.is(Impure)
1304-
val funSym = defn.FunctionSymbol(numArgs, isContextual, isErased.contains(true), isImpure)
13051304

13061305
/** Typechecks dependent function type with given parameters `params` */
13071306
def typedDependent(params: List[untpd.ValDef])(using Context): Tree =
@@ -1322,9 +1321,10 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
13221321
val appDef0 = untpd.DefDef(nme.apply, List(params3), body, EmptyTree).withSpan(tree.span)
13231322
index(appDef0 :: Nil)
13241323
val appDef = typed(appDef0).asInstanceOf[DefDef]
1325-
val mt = appDef.symbol.info.asInstanceOf[MethodType]
1324+
val mt = appDef.symbol.info.asInstanceOf[MethodType].markErasedClasses
13261325
if (mt.isParamDependent)
13271326
report.error(em"$mt is an illegal function type because it has inter-parameter dependencies", tree.srcPos)
1327+
val funSym = defn.FunctionSymbol(numArgs, isContextual, mt.isErasedMethod, isImpure)
13281328
val resTpt = TypeTree(mt.nonDependentResultApprox).withSpan(body.span)
13291329
val typeArgs = appDef.termParamss.head.map(_.tpt) :+ resTpt
13301330
val tycon = TypeTree(funSym.typeRef)
@@ -1338,12 +1338,15 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
13381338
using ctx.fresh.setOwner(newRefinedClassSymbol(tree.span)).setNewScope)
13391339
case _ =>
13401340
if isErased.contains(true) then
1341-
typedFunctionType(
1342-
desugar.makeErasedFunctionValDefs(tree.asInstanceOf[untpd.FunctionWithMods], pt),
1343-
pt
1344-
)
1341+
typedFunctionType(desugar.makeErasedFunctionValDefs(tree, pt), pt)
13451342
else
1346-
typed(cpy.AppliedTypeTree(tree)(untpd.TypeTree(funSym.typeRef), args :+ body), pt)
1343+
val funSym = defn.FunctionSymbol(numArgs, isContextual, false, isImpure)
1344+
val result = typed(cpy.AppliedTypeTree(tree)(untpd.TypeTree(funSym.typeRef), args :+ body), pt)
1345+
// if there are any erased classes, we need to re-do the typecheck.
1346+
result match
1347+
case r: AppliedTypeTree if r.args.exists(_.tpe.isErasedClass) =>
1348+
typedFunctionType(desugar.makeErasedFunctionValDefs(tree, pt), pt)
1349+
case _ => result
13471350
}
13481351
}
13491352

0 commit comments

Comments
 (0)