Skip to content

Commit 8144f98

Browse files
authored
Merge pull request #6531 from dotty-staging/tc-derive
Test case for new typeclass derivation scheme
2 parents 2ae2dea + 2afa89c commit 8144f98

37 files changed

+1528
-762
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import reporting.diagnostic.messages._
1515
import reporting.trace
1616
import annotation.constructorOnly
1717
import printing.Formatting.hl
18+
import config.Printers
1819

1920
import scala.annotation.internal.sharable
2021

@@ -51,7 +52,7 @@ object desugar {
5152
private type VarInfo = (NameTree, Tree)
5253

5354
/** Is `name` the name of a method that can be invalidated as a compiler-generated
54-
* case class method that clashes with a user-defined method?
55+
* case class method if it clashes with a user-defined method?
5556
*/
5657
def isRetractableCaseClassMethodName(name: Name)(implicit ctx: Context): Boolean = name match {
5758
case nme.apply | nme.unapply | nme.unapplySeq | nme.copy => true
@@ -765,7 +766,7 @@ object desugar {
765766
}
766767

767768
flatTree(cdef1 :: companions ::: implicitWrappers)
768-
}
769+
}.reporting(res => i"desugared: $res", Printers.desugar)
769770

770771
/** Expand
771772
*
@@ -848,8 +849,7 @@ object desugar {
848849
fwd
849850
}
850851
val moduleName = tdef.name.toTermName
851-
val localRef = Select(Ident(moduleName), tdef.name)
852-
localRef.pushAttachment(SuppressAccessCheck, ())
852+
val localRef = Select(Ident(moduleName), tdef.name).withAttachment(SuppressAccessCheck, ())
853853
val aliasType = cpy.TypeDef(tdef)(rhs = completeForwarder(localRef)).withSpan(tdef.span.startPos)
854854
val localType = tdef.withMods(Modifiers(Synthetic | Opaque).withPrivateWithin(tdef.name))
855855

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import Symbols._, StdNames._, Trees._
88
import Decorators._
99
import util.{Property, SourceFile}
1010
import typer.ErrorReporting._
11+
import transform.SyntheticMembers.ExtendsSingletonMirror
1112

1213
import scala.annotation.internal.sharable
1314

@@ -115,11 +116,16 @@ object DesugarEnums {
115116
val toStringDef =
116117
DefDef(nme.toString_, Nil, Nil, TypeTree(), Ident(nme.name))
117118
.withFlags(Override)
118-
def creator = New(Template(emptyConstructor, enumClassRef :: Nil, Nil, EmptyValDef,
119-
List(enumTagDef, toStringDef) ++ registerCall))
119+
val creator = New(Template(
120+
constr = emptyConstructor,
121+
parents = enumClassRef :: Nil,
122+
derived = Nil,
123+
self = EmptyValDef,
124+
body = List(enumTagDef, toStringDef) ++ registerCall
125+
).withAttachment(ExtendsSingletonMirror, ()))
120126
DefDef(nme.DOLLAR_NEW, Nil,
121127
List(List(param(nme.tag, defn.IntType), param(nme.name, defn.StringType))),
122-
TypeTree(), creator)
128+
TypeTree(), creator).withFlags(Private | Synthetic)
123129
}
124130

125131
/** The return type of an enum case apply method and any widening methods in which
@@ -259,6 +265,7 @@ object DesugarEnums {
259265
.withFlags(Override)
260266
val (tagMeth, scaffolding) = enumTagMeth(CaseKind.Object)
261267
val impl1 = cpy.Template(impl)(body = List(tagMeth, toStringMeth) ++ registerCall)
268+
.withAttachment(ExtendsSingletonMirror, ())
262269
val vdef = ValDef(name, TypeTree(), New(impl1)).withMods(mods | Final)
263270
flatTree(scaffolding ::: vdef :: Nil).withSpan(span)
264271
}

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,26 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
400400
case ConstantType(value) => Literal(value)
401401
}
402402

403+
/** A path that corresponds to the given type `tp`. Error if `tp` is not a refinement
404+
* of an addressable singleton type.
405+
*/
406+
def pathFor(tp: Type)(implicit ctx: Context): Tree = {
407+
def recur(tp: Type): Tree = tp match {
408+
case tp: NamedType =>
409+
tp.info match {
410+
case TypeAlias(alias) => recur(alias)
411+
case _: TypeBounds => EmptyTree
412+
case _ => singleton(tp)
413+
}
414+
case tp: TypeProxy => recur(tp.superType)
415+
case _ => EmptyTree
416+
}
417+
recur(tp).orElse {
418+
ctx.error(em"$tp is not an addressable singleton type")
419+
TypeTree(tp)
420+
}
421+
}
422+
403423
/** A tree representing a `newXYZArray` operation of the right
404424
* kind for the given element type in `elemTpe`. No type arguments or
405425
* `length` arguments are given.

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
263263
}
264264

265265
/** Install the derived type tree as a dependency on `sym` */
266-
def watching(sym: Symbol): this.type = {
267-
pushAttachment(OriginalSymbol, sym)
268-
this
269-
}
266+
def watching(sym: Symbol): this.type = withAttachment(OriginalSymbol, sym)
270267

271268
/** A hook to ensure that all necessary symbols are completed so that
272269
* OriginalSymbol attachments are propagated to this tree

compiler/src/dotty/tools/dotc/config/Printers.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ object Printers {
1919
val cyclicErrors: Printer = noPrinter
2020
val debug = noPrinter // no type annotation here to force inlining
2121
val derive: Printer = noPrinter
22+
val desugar: Printer = noPrinter
2223
val dottydoc: Printer = noPrinter
2324
val exhaustivity: Printer = noPrinter
2425
val gadts: Printer = noPrinter

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

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -692,16 +692,23 @@ class Definitions {
692692
lazy val ModuleSerializationProxyConstructor: TermSymbol =
693693
ModuleSerializationProxyClass.requiredMethod(nme.CONSTRUCTOR, List(ClassType(TypeBounds.empty)))
694694

695-
lazy val GenericType: TypeRef = ctx.requiredClassRef("scala.reflect.Generic")
696-
def GenericClass(implicit ctx: Context): ClassSymbol = GenericType.symbol.asClass
697-
lazy val ShapeType: TypeRef = ctx.requiredClassRef("scala.compiletime.Shape")
698-
def ShapeClass(implicit ctx: Context): ClassSymbol = ShapeType.symbol.asClass
699-
lazy val ShapeCaseType: TypeRef = ctx.requiredClassRef("scala.compiletime.Shape.Case")
700-
def ShapeCaseClass(implicit ctx: Context): ClassSymbol = ShapeCaseType.symbol.asClass
701-
lazy val ShapeCasesType: TypeRef = ctx.requiredClassRef("scala.compiletime.Shape.Cases")
702-
def ShapeCasesClass(implicit ctx: Context): ClassSymbol = ShapeCasesType.symbol.asClass
703-
lazy val MirrorType: TypeRef = ctx.requiredClassRef("scala.reflect.Mirror")
704-
lazy val GenericClassType: TypeRef = ctx.requiredClassRef("scala.reflect.GenericClass")
695+
lazy val MirrorType: TypeRef = ctx.requiredClassRef("scala.deriving.Mirror")
696+
def MirrorClass(implicit ctx: Context): ClassSymbol = MirrorType.symbol.asClass
697+
698+
lazy val Mirror_ProductType: TypeRef = ctx.requiredClassRef("scala.deriving.Mirror.Product")
699+
def Mirror_ProductClass(implicit ctx: Context): ClassSymbol = Mirror_ProductType.symbol.asClass
700+
701+
lazy val Mirror_Product_fromProductR: TermRef = Mirror_ProductClass.requiredMethodRef(nme.fromProduct)
702+
def Mirror_Product_fromProduct(implicit ctx: Context): Symbol = Mirror_Product_fromProductR.symbol
703+
704+
lazy val Mirror_SumType: TypeRef = ctx.requiredClassRef("scala.deriving.Mirror.Sum")
705+
def Mirror_SumClass(implicit ctx: Context): ClassSymbol = Mirror_SumType.symbol.asClass
706+
707+
lazy val Mirror_SingletonType: TypeRef = ctx.requiredClassRef("scala.deriving.Mirror.Singleton")
708+
def Mirror_SingletonClass(implicit ctx: Context): ClassSymbol = Mirror_SingletonType.symbol.asClass
709+
710+
lazy val Mirror_SingletonProxyType: TypeRef = ctx.requiredClassRef("scala.deriving.Mirror.SingletonProxy")
711+
def Mirror_SingletonProxyClass(implicit ctx: Context): ClassSymbol = Mirror_SingletonProxyType.symbol.asClass
705712

706713
lazy val LanguageModuleRef: TermSymbol = ctx.requiredModule("scala.language")
707714
def LanguageModuleClass(implicit ctx: Context): ClassSymbol = LanguageModuleRef.moduleClass.asClass

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@ object Flags {
628628

629629
/** An enum case */
630630
final val EnumCase: FlagConjunction = allOf(Enum, Case)
631+
final val EnumCaseVal: FlagConjunction = allOf(Enum, CaseVal)
631632

632633
/** A term parameter or parameter accessor */
633634
final val TermParamOrAccessor: FlagSet = Param | ParamAccessor

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,11 @@ object StdNames {
339339
val LiteralAnnotArg: N = "LiteralAnnotArg"
340340
val longHash: N = "longHash"
341341
val MatchCase: N = "MatchCase"
342+
val MirroredElemTypes: N = "MirroredElemTypes"
343+
val MirroredElemLabels: N = "MirroredElemLabels"
344+
val MirroredLabel: N = "MirroredLabel"
345+
val MirroredMonoType: N = "MirroredMonoType"
346+
val MirroredType: N = "MirroredType"
342347
val Modifiers: N = "Modifiers"
343348
val NestedAnnotArg: N = "NestedAnnotArg"
344349
val NoFlags: N = "NoFlags"
@@ -432,6 +437,7 @@ object StdNames {
432437
val flagsFromBits : N = "flagsFromBits"
433438
val flatMap: N = "flatMap"
434439
val foreach: N = "foreach"
440+
val fromProduct: N = "fromProduct"
435441
val genericArrayOps: N = "genericArrayOps"
436442
val genericClass: N = "genericClass"
437443
val get: N = "get"

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

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2313,19 +2313,30 @@ class TrackingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
23132313
cas
23142314
}
23152315
def widenAbstractTypes(tp: Type): Type = new TypeMap {
2316+
var seen = Set[TypeParamRef]()
23162317
def apply(tp: Type) = tp match {
23172318
case tp: TypeRef =>
2318-
if (tp.symbol.isAbstractOrParamType | tp.symbol.isOpaqueAlias)
2319-
WildcardType
2320-
else tp.info match {
2321-
case TypeAlias(alias) =>
2322-
val alias1 = widenAbstractTypes(alias)
2323-
if (alias1 ne alias) alias1 else tp
2324-
case _ => mapOver(tp)
2319+
tp.info match {
2320+
case info: MatchAlias =>
2321+
mapOver(tp)
2322+
// TODO: We should follow the alias in this case, but doing so
2323+
// risks infinite recursion
2324+
case TypeBounds(lo, hi) =>
2325+
if (hi frozen_<:< lo) {
2326+
val alias = apply(lo)
2327+
if (alias ne lo) alias else mapOver(tp)
2328+
}
2329+
else WildcardType
2330+
case _ =>
2331+
mapOver(tp)
23252332
}
2326-
2333+
case tp: TypeLambda =>
2334+
val saved = seen
2335+
seen ++= tp.paramRefs
2336+
try mapOver(tp)
2337+
finally seen = saved
23272338
case tp: TypeVar if !tp.isInstantiated => WildcardType
2328-
case _: TypeParamRef => WildcardType
2339+
case tp: TypeParamRef if !seen.contains(tp) => WildcardType
23292340
case _ => mapOver(tp)
23302341
}
23312342
}.apply(tp)

compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ class PlainPrinter(_ctx: Context) extends Printer {
547547
val saved = maxSummarized
548548
maxSummarized = ctx.base.toTextRecursions + depth
549549
try op
550-
finally maxSummarized = depth
550+
finally maxSummarized = saved
551551
}
552552

553553
def summarized[T](op: => T): T = summarized(summarizeDepth)(op)

0 commit comments

Comments
 (0)