Skip to content

Commit 781d29f

Browse files
committed
experiment with TypeOps.refineUsingParent
1 parent 8239bb6 commit 781d29f

File tree

3 files changed

+64
-34
lines changed

3 files changed

+64
-34
lines changed

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

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -872,23 +872,36 @@ object TypeOps:
872872

873873
end healPrefix
874874

875+
def hasPathPrefix(tpe: Type): Boolean =
876+
877+
def inner(pre: Type): Boolean = pre match
878+
case pre: TermRef => inner(pre.prefix)
879+
case pre: SingletonType => true
880+
case NoPrefix => true
881+
case _ => false
882+
883+
appliedTypePrefix(tpe) match
884+
case Some(pre) => inner(pre)
885+
case _ => false
886+
887+
end hasPathPrefix
888+
875889
/** lift the prefix of an applied type, without normalisation or forcing */
876-
def appliedTypePrefix(tpe: Type)(using Context): Option[Type] =
877-
tpe match
878-
case tpe: NamedType => Some(tpe.prefix)
879-
case tpe: ThisType => appliedTypePrefix(tpe.tref)
880-
case tpe: AppliedType => appliedTypePrefix(tpe.tycon)
881-
case tpe: AnnotatedType => appliedTypePrefix(tpe.parent) // TODO: test
882-
case tpe: AndOrType => Some(NoPrefix) // TODO: test
883-
case _ =>
884-
// ignore HKTypeLambda/TypeBounds
885-
// what do do about
886-
// - MatchType -- will this occur or will it be reduced?
887-
// - TypeParamRef -- likely collapse to bounds?
888-
// - TypeVar/ExprType -- when can this occur
889-
// - RecThis -- what is the prefix of this
890-
// - RefinedOrRecType -- do we need to refine the children?
891-
// - AnnotatedType -- do we need to annotate the children?
892-
None
890+
def appliedTypePrefix(tpe: Type): Option[Type] = tpe match
891+
case tpe: NamedType => Some(tpe.prefix)
892+
case tpe: ThisType => appliedTypePrefix(tpe.tref)
893+
case tpe: AppliedType => appliedTypePrefix(tpe.tycon)
894+
case tpe: AnnotatedType => appliedTypePrefix(tpe.parent) // TODO: test
895+
case tpe: AndOrType => Some(NoPrefix) // TODO: test
896+
case _ =>
897+
// ignore HKTypeLambda/TypeBounds
898+
// what do do about
899+
// - MatchType -- will this occur or will it be reduced?
900+
// - TypeParamRef -- likely collapse to bounds?
901+
// - TypeVar/ExprType -- when can this occur
902+
// - RecThis -- what is the prefix of this
903+
// - RefinedOrRecType -- do we need to refine the children?
904+
// - AnnotatedType -- do we need to annotate the children?
905+
None
893906

894907
end TypeOps

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

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ object SyntheticMembers {
2828
val ExtendsSumMirror: Property.StickyKey[Unit] = new Property.StickyKey
2929

3030
val SubstPrefix: Property.StickyKey[Type] = new Property.StickyKey
31+
val OriginalMirroredType: Property.StickyKey[Type] = new Property.StickyKey
3132
}
3233

3334
/** Synthetic method implementations for case classes, case objects,
@@ -473,8 +474,8 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
473474
* type MirroredMonoType = C[?]
474475
* ```
475476
*/
476-
def fromProductBody(caseClass: Symbol, param: Tree, pre: Type)(using Context): Tree = {
477-
val (classRef0, methTpe) =
477+
def fromProductBody(caseClass: Symbol, param: Tree, pre: Type, mirroredType: Option[Type])(using Context): Tree = {
478+
val (classRef, methTpe) =
478479
caseClass.primaryConstructor.info match {
479480
case tl: PolyType =>
480481
val (tl1, tpts) = constrained(tl, untpd.EmptyTree, alwaysAddTypeVars = true)
@@ -487,7 +488,6 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
487488
case methTpe =>
488489
(caseClass.typeRef, methTpe)
489490
}
490-
val classRef = TypeOps.healPrefix(classRef0, pre).getOrElse(classRef0)
491491
methTpe match {
492492
case methTpe: MethodType =>
493493
val elems =
@@ -517,13 +517,18 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
517517
* a wildcard for each type parameter. The normalized type of an object
518518
* O is O.type.
519519
*/
520-
def ordinalBody(cls: Symbol, param: Tree, pre: Type)(using Context): Tree =
520+
def ordinalBody(cls: Symbol, param: Tree, pre: Type, mirroredType: Option[Type])(using Context): Tree =
521521
if (cls.is(Enum)) param.select(nme.ordinal).ensureApplied
522522
else {
523523
val cases =
524524
for ((child, idx) <- cls.children.zipWithIndex) yield {
525525
val patType0 = if child.isTerm then child.termRef else child.rawTypeRef
526526
val patType = TypeOps.healPrefix(patType0, pre).getOrElse(patType0)
527+
// val patType = mirroredType.map { tpe =>
528+
// TypeOps.refineUsingParent(tpe, child)
529+
// }.getOrElse {
530+
// if child.isTerm then child.reachableTermRef else child.reachableRawTypeRef
531+
// }
527532
val pat = Typed(untpd.Ident(nme.WILDCARD).withType(patType), TypeTree(patType))
528533
CaseDef(pat, EmptyTree, Literal(Constant(idx)))
529534
}
@@ -572,32 +577,33 @@ class SyntheticMembers(thisPhase: DenotTransformer) {
572577
}
573578
def makeSingletonMirror() =
574579
addParent(defn.Mirror_SingletonClass.typeRef)
575-
def makeProductMirror(cls: Symbol, pre: Type) = {
580+
def makeProductMirror(cls: Symbol, pre: Type, mirroredType: Option[Type]) = {
576581
addParent(defn.Mirror_ProductClass.typeRef)
577582
addMethod(nme.fromProduct, MethodType(defn.ProductClass.typeRef :: Nil, monoType.typeRef), cls,
578-
fromProductBody(_, _, pre).ensureConforms(monoType.typeRef)) // t4758.scala or i3381.scala are examples where a cast is needed
583+
fromProductBody(_, _, pre, mirroredType).ensureConforms(monoType.typeRef)) // t4758.scala or i3381.scala are examples where a cast is needed
579584
}
580-
def makeSumMirror(cls: Symbol, pre: Type) = {
585+
def makeSumMirror(cls: Symbol, pre: Type, mirroredType: Option[Type]) = {
581586
addParent(defn.Mirror_SumClass.typeRef)
582587
addMethod(nme.ordinal, MethodType(monoType.typeRef :: Nil, defn.IntType), cls,
583-
ordinalBody(_, _, pre))
588+
ordinalBody(_, _, pre, mirroredType))
584589
}
585590

586591
val pre = impl.removeAttachment(SubstPrefix).getOrElse(NoPrefix)
592+
val mirroredType = impl.removeAttachment(OriginalMirroredType)
587593

588594
if (clazz.is(Module)) {
589595
if (clazz.is(Case)) makeSingletonMirror()
590-
else if (linked.isGenericProduct) makeProductMirror(linked, pre)
591-
else if (linked.isGenericSum(clazz)) makeSumMirror(linked, pre)
596+
else if (linked.isGenericProduct) makeProductMirror(linked, pre, mirroredType)
597+
else if (linked.isGenericSum(clazz)) makeSumMirror(linked, pre, mirroredType)
592598
else if (linked.is(Sealed))
593599
derive.println(i"$linked is not a sum because ${linked.whyNotGenericSum(clazz)}")
594600
}
595601
else if (impl.removeAttachment(ExtendsSingletonMirror).isDefined)
596602
makeSingletonMirror()
597603
else if (impl.removeAttachment(ExtendsProductMirror).isDefined)
598-
makeProductMirror(monoType.typeRef.dealias.classSymbol, pre)
604+
makeProductMirror(monoType.typeRef.dealias.classSymbol, pre, mirroredType)
599605
else if (impl.removeAttachment(ExtendsSumMirror).isDefined)
600-
makeSumMirror(monoType.typeRef.dealias.classSymbol, pre)
606+
makeSumMirror(monoType.typeRef.dealias.classSymbol, pre, mirroredType)
601607

602608
cpy.Template(impl)(parents = newParents, body = newBody)
603609
}

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

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
176176
/** Create an anonymous class `new Object { type MirroredMonoType = ... }`
177177
* and mark it with given attachment so that it is made into a mirror at PostTyper.
178178
*/
179-
private def anonymousMirror(monoType: Type, attachment: Property.StickyKey[Unit], substPrefix: Option[Type], span: Span)(using Context) =
179+
private def anonymousMirror(monoType: Type, mirroredType: Type, attachment: Property.StickyKey[Unit], substPrefix: Option[Type], span: Span)(using Context) =
180180
if ctx.isAfterTyper then ctx.compilationUnit.needsMirrorSupport = true
181181
val monoTypeDef = untpd.TypeDef(tpnme.MirroredMonoType, untpd.TypeTree(monoType))
182182
var newImpl = untpd.Template(
@@ -185,7 +185,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
185185
derived = Nil,
186186
self = EmptyValDef,
187187
body = monoTypeDef :: Nil
188-
).withAttachment(attachment, ())
188+
).withAttachment(attachment, ()).withAttachment(OriginalMirroredType, mirroredType)
189189

190190
substPrefix match {
191191
case Some(pre) =>
@@ -236,6 +236,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
236236
monoMap(mirroredType.resultType)
237237

238238
private def productMirror(mirroredType: Type, formal: Type, span: Span)(using Context): Tree =
239+
// val pre = NoPrefix
239240
val pre = TypeOps.appliedTypePrefix(mirroredType) match
240241
case Some(pre) => pre
241242
case _ => return EmptyTree
@@ -280,13 +281,14 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
280281
.refinedWith(tpnme.MirroredElemTypes, TypeAlias(elemsType))
281282
.refinedWith(tpnme.MirroredElemLabels, TypeAlias(elemsLabels))
282283
val mirrorRef =
283-
if (cls.is(Scala2x)) anonymousMirror(monoType, ExtendsProductMirror, Some(pre), span)
284+
if (cls.is(Scala2x)) anonymousMirror(monoType, mirroredType, ExtendsProductMirror, Some(pre), span)
284285
else companionPath(mirroredType, span)
285286
mirrorRef.cast(mirrorType)
286287
else EmptyTree
287288
end productMirror
288289

289290
private def sumMirror(mirroredType: Type, formal: Type, span: Span)(using Context): Tree =
291+
// val pre = NoPrefix
290292
val pre = TypeOps.appliedTypePrefix(mirroredType) match
291293
case Some(pre) => pre
292294
case _ => return EmptyTree
@@ -332,7 +334,16 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
332334
end solveInner
333335

334336
def solve(sym: Symbol): Either[String, Type] =
335-
TypeOps.healPrefix(solveInner(sym), pre)
337+
TypeOps.healPrefix(solveInner(sym), pre) // TODO i13332 tests will break with refineUsingParent
338+
// // it seems we may need to still do some substitution of ThisType
339+
// // or else TASTy idempotency tests fail,
340+
// // see tests/pos/anon-mirror-gen-this-a.scala
341+
// val res = TypeOps.refineUsingParent(mirroredType, sym)
342+
// report.echo(i"healed $sym with $mirroredType to $res [${res.toString}]")
343+
// // if TypeOps.hasPathPrefix(res) then
344+
// Right(res)
345+
// // else
346+
// // Left("foo")
336347

337348
val (errors, resolvedChildren) = cls.children.map(solve).partitionMap(identity)
338349
if errors.nonEmpty then
@@ -354,7 +365,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
354365
.refinedWith(tpnme.MirroredElemLabels, TypeAlias(TypeOps.nestedPairs(elemLabels)))
355366
val mirrorRef =
356367
if useCompanion then companionPath(mirroredType, span)
357-
else anonymousMirror(monoType, ExtendsSumMirror, Some(pre), span)
368+
else anonymousMirror(monoType, mirroredType, ExtendsSumMirror, Some(pre), span)
358369
mirrorRef.cast(mirrorType)
359370
else EmptyTree
360371
end sumMirror

0 commit comments

Comments
 (0)