|
| 1 | +package dotty.tools.dotc |
| 2 | +package transform |
| 3 | + |
| 4 | +import core._ |
| 5 | +import Flags._ |
| 6 | +import Contexts._ |
| 7 | +import Symbols._ |
| 8 | +import SymUtils._ |
| 9 | +import dotty.tools.dotc.ast.tpd |
| 10 | +import dotty.tools.dotc.ast.Trees._ |
| 11 | +import dotty.tools.dotc.quoted._ |
| 12 | +import dotty.tools.dotc.inlines.Inlines |
| 13 | +import dotty.tools.dotc.ast.TreeMapWithImplicits |
| 14 | +import dotty.tools.dotc.core.DenotTransformers.SymTransformer |
| 15 | +import dotty.tools.dotc.staging.StagingLevel |
| 16 | +import dotty.tools.dotc.core.SymDenotations.SymDenotation |
| 17 | +import dotty.tools.dotc.core.StdNames.{str, nme} |
| 18 | +import dotty.tools.dotc.core.Types.* |
| 19 | +import dotty.tools.dotc.core.Names.{Name, TermName} |
| 20 | + |
| 21 | +import scala.collection.mutable.ListBuffer |
| 22 | + |
| 23 | +class SpecializeInlineTraits extends MacroTransform, SymTransformer { |
| 24 | + |
| 25 | + import tpd._ |
| 26 | + |
| 27 | + override def phaseName: String = SpecializeInlineTraits.name |
| 28 | + |
| 29 | + override def description: String = SpecializeInlineTraits.description |
| 30 | + |
| 31 | + override def changesMembers: Boolean = true |
| 32 | + |
| 33 | + override def changesParents: Boolean = true |
| 34 | + |
| 35 | + override def run(using Context): Unit = |
| 36 | + try super.run |
| 37 | + catch case _: CompilationUnit.SuspendException => () |
| 38 | + |
| 39 | + override def newTransformer(using Context): Transformer = new Transformer { |
| 40 | + override def transform(tree: Tree)(using Context): Tree = tree match { |
| 41 | + case tree: TypeDef if tree.symbol.isInlineTrait => |
| 42 | + transformInlineTrait(tree) |
| 43 | + case tree: TypeDef if Inlines.needsInlining(tree) => |
| 44 | + val tree1 = super.transform(tree).asInstanceOf[TypeDef] |
| 45 | + if tree1.tpe.isError then tree1 |
| 46 | + else if tree1.symbol.isInlineTrait then transformInlineTrait(tree1) |
| 47 | + else Inlines.inlineParentInlineTraits(tree1) |
| 48 | + case _ => super.transform(tree) |
| 49 | + } |
| 50 | + } |
| 51 | + |
| 52 | + override def transformSym(symd: SymDenotation)(using Context): SymDenotation = |
| 53 | + if symd.isClass && symd.owner.isInlineTrait && !symd.is(Module) then |
| 54 | + symd.copySymDenotation(name = SpecializeInlineTraits.newInnerClassName(symd.name), initFlags = (symd.flags &~ Final) | Trait) |
| 55 | + else |
| 56 | + symd |
| 57 | + |
| 58 | + override def checkPostCondition(tree: Tree)(using Context): Unit = |
| 59 | + tree match { |
| 60 | + // TODO |
| 61 | + case _ => |
| 62 | + } |
| 63 | + |
| 64 | + extension (tree: Tree) |
| 65 | + private def hasSpecializedVersion: Boolean = |
| 66 | + false |
| 67 | + |
| 68 | + private def transformInlineTrait(inlineTrait: TypeDef)(using Context): TypeDef = |
| 69 | + val tpd.TypeDef(_, tmpl: Template) = inlineTrait: @unchecked |
| 70 | + val body1 = tmpl.body.flatMap { |
| 71 | + case innerClass: TypeDef if innerClass.symbol.isClass => |
| 72 | + val newTrait = makeTraitFromInnerClass(innerClass) |
| 73 | + val newType = makeTypeFromInnerClass(inlineTrait.symbol, innerClass, newTrait.symbol) |
| 74 | + List(newTrait, newType) |
| 75 | + case member: MemberDef => |
| 76 | + List(member) |
| 77 | + case _ => |
| 78 | + // Remove non-memberdefs, as they are normally placed into $init() |
| 79 | + Nil |
| 80 | + } |
| 81 | + val tmpl1 = cpy.Template(tmpl)(body = body1) |
| 82 | + cpy.TypeDef(inlineTrait)(rhs = tmpl1) |
| 83 | + end transformInlineTrait |
| 84 | + |
| 85 | + private def makeTraitFromInnerClass(innerClass: TypeDef)(using Context): TypeDef = |
| 86 | + val TypeDef(name, tmpl: Template) = innerClass: @unchecked |
| 87 | + val newInnerParents = tmpl.parents.mapConserve(ConcreteParentStripper.apply) |
| 88 | + val tmpl1 = cpy.Template(tmpl)(parents = newInnerParents) // TODO .withType(???) |
| 89 | + val newTrait = cpy.TypeDef(innerClass)(name = SpecializeInlineTraits.newInnerClassName(name), rhs = tmpl1) |
| 90 | + newTrait.symbol.setFlag(Synthetic) |
| 91 | + newTrait |
| 92 | + end makeTraitFromInnerClass |
| 93 | + |
| 94 | + private def makeTypeFromInnerClass(parentSym: Symbol, innerClass: TypeDef, newTraitSym: Symbol)(using Context): TypeDef = |
| 95 | + val upperBound = innerClass.symbol.primaryConstructor.info match { |
| 96 | + case _: MethodType => |
| 97 | + newTraitSym.typeRef |
| 98 | + case poly: PolyType => |
| 99 | + HKTypeLambda(poly.paramNames)(tl => poly.paramInfos, tl => newTraitSym.typeRef.appliedTo(tl.paramRefs.head)) |
| 100 | + } |
| 101 | + val newTypeSym = newSymbol( |
| 102 | + owner = parentSym, |
| 103 | + name = newTraitSym.name.asTypeName, |
| 104 | + flags = innerClass.symbol.flags & (Private | Protected) | Synthetic, |
| 105 | + info = TypeBounds.upper(upperBound), |
| 106 | + privateWithin = innerClass.symbol.privateWithin, |
| 107 | + coord = innerClass.symbol.coord, |
| 108 | + nestingLevel = innerClass.symbol.nestingLevel, |
| 109 | + ).asType |
| 110 | + TypeDef(newTypeSym) |
| 111 | + end makeTypeFromInnerClass |
| 112 | + |
| 113 | + private object ConcreteParentStripper extends TreeAccumulator[Tree] { |
| 114 | + def apply(tree: Tree)(using Context): Tree = apply(tree, tree) |
| 115 | + |
| 116 | + override def apply(x: Tree, tree: Tree)(using Context): Tree = tree match { |
| 117 | + case ident: Ident => ident |
| 118 | + case tpt: TypeTree => tpt |
| 119 | + case _ => foldOver(x, tree) |
| 120 | + } |
| 121 | + } |
| 122 | +} |
| 123 | + |
| 124 | +object SpecializeInlineTraits: |
| 125 | + val name: String = "specializeInlineTraits" |
| 126 | + val description: String = "inline the code of inline traits and specialize calls to their members" |
| 127 | + |
| 128 | + private[transform] def newInnerClassName(name: Name): name.ThisName = name ++ str.INLINE_TRAIT_INNER_CLASS_SUFFIX |
0 commit comments