Skip to content

Commit d605bc5

Browse files
Partially implement inner traits
There are still issues with symbols being changed, but not their types
1 parent 34f77f6 commit d605bc5

File tree

4 files changed

+74
-26
lines changed

4 files changed

+74
-26
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ object StdNames {
2626
inline val LOCALDUMMY_PREFIX = "<local " // owner of local blocks
2727
inline val ANON_CLASS = "$anon"
2828
inline val ANON_FUN = "$anonfun"
29+
inline val INLINE_TRAIT_INNER_CLASS_SUFFIX = "$trait"
2930

3031
inline val REPL_SESSION_LINE = "rs$line$"
3132
inline val REPL_ASSIGN_SUFFIX = "$assign"

compiler/src/dotty/tools/dotc/inlines/Inlines.scala

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -64,21 +64,21 @@ object Inlines:
6464

6565
/** Should call be inlined in this context? */
6666
def needsInlining(tree: Tree)(using Context): Boolean =
67-
val isInlineableInCtx =
67+
def isInlineableInCtx =
6868
StagingLevel.level == 0
6969
&& (
7070
ctx.phase == Phases.inliningPhase
7171
|| (ctx.phase == Phases.typerPhase && needsTransparentInlining(tree))
7272
)
7373
&& !ctx.typer.hasInliningErrors
7474
&& !ctx.base.stopInlining
75-
&& !ctx.owner.isInlineTrait
75+
&& !ctx.owner.ownersIterator.exists(_.isInlineTrait)
7676

7777
tree match
7878
case Block(_, expr) =>
7979
needsInlining(expr)
8080
case tdef @ TypeDef(_, impl: Template) =>
81-
!tdef.symbol.isInlineTrait && impl.parents.map(symbolFromParent).exists(_.isInlineTrait) && isInlineableInCtx
81+
impl.parents.map(symbolFromParent).exists(_.isInlineTrait) && isInlineableInCtx
8282
case _ =>
8383
isInlineable(tree.symbol) && !tree.tpe.widenTermRefExpr.isInstanceOf[MethodOrPoly] && isInlineableInCtx
8484

@@ -571,16 +571,22 @@ object Inlines:
571571
inlinedValDef(stat, inlinedSym)
572572
case stat: DefDef =>
573573
inlinedDefDef(stat, inlinedSym)
574-
case stat @ TypeDef(_, impl: Template) =>
575-
inlinedClassDef(stat, impl, inlinedSym.asClass)
574+
case stat @ TypeDef(_, _: Template) =>
575+
inlinedClassDef(stat, inlinedSym.asClass)
576576
case stat: TypeDef =>
577577
inlinedTypeDef(stat, inlinedSym)
578578

579579
private def inlinedMember(sym: Symbol)(using Context): Symbol =
580580
sym.info match {
581581
case ClassInfo(prefix, cls, declaredParents, scope, selfInfo) =>
582-
val inlinedInfo = ClassInfo(prefix, cls, declaredParents, Scopes.newScope, selfInfo) // TODO adapt parents
583-
sym.copy(owner = ctx.owner, info = inlinedInfo, coord = spanCoord(parent.span)).entered.asClass
582+
val inlinedSym = newClassSymbol(
583+
ctx.owner,
584+
sym.asType.name,
585+
sym.flags | Synthetic,
586+
clsSym => ClassInfo(inlinerTypeMap(prefix), clsSym, declaredParents :+ ThisType.raw(ctx.owner.typeRef).select(sym), Scopes.newScope, selfInfo)
587+
)
588+
inlinedSym.setTargetName(sym.name ++ str.NAME_JOIN ++ ctx.owner.name)
589+
inlinedSym
584590
case _ =>
585591
var name = sym.name
586592
var flags = sym.flags | Synthetic
@@ -598,11 +604,13 @@ object Inlines:
598604
coord = spanCoord(parent.span)).entered
599605
}
600606

601-
private def inlinedStat(stat: Tree)(using Context): Tree = stat match {
602-
// TODO check if symbols must be copied
603-
case tree: DefDef => inlinedDefDef(tree, tree.symbol)
604-
case tree: ValDef => inlinedValDef(tree, tree.symbol)
605-
}
607+
private def inlinedStat(stat: Tree)(using Context): Tree =
608+
val inlinedSym = inlinedMember(stat.symbol)
609+
stat match {
610+
// TODO check if symbols must be copied
611+
case tree: DefDef => inlinedDefDef(tree, inlinedSym)
612+
case tree: ValDef => inlinedValDef(tree, inlinedSym)
613+
}
606614

607615
private def inlinedValDef(vdef: ValDef, inlinedSym: Symbol)(using Context): ValDef =
608616
val rhs =
@@ -625,14 +633,18 @@ object Inlines:
625633

626634
private def inlinedPrimaryConstructorDefDef(ddef: DefDef)(using Context): DefDef =
627635
// TODO check if symbol must be copied
628-
val constr = inlinedDefDef(ddef, ddef.symbol)
636+
val inlinedSym = inlinedMember(ddef.symbol)
637+
inlinedSym.resetFlag(Override)
638+
val constr = inlinedDefDef(ddef, inlinedSym)
629639
cpy.DefDef(constr)(tpt = TypeTree(defn.UnitType), rhs = EmptyTree)
630640

631-
private def inlinedClassDef(clDef: TypeDef, impl: Template, inlinedCls: ClassSymbol)(using Context): Tree =
632-
val (constr, body) = inContext(ctx.withOwner(inlinedCls)) {
633-
(inlinedPrimaryConstructorDefDef(impl.constr), impl.body.map(inlinedStat))
641+
private def inlinedClassDef(clsDef: TypeDef, inlinedSym: ClassSymbol)(using Context): Tree =
642+
val TypeDef(_, tmpl: Template) = clsDef: @unchecked
643+
val (constr, body) = inContext(ctx.withOwner(inlinedSym)) {
644+
(inlinedPrimaryConstructorDefDef(tmpl.constr), tmpl.body.map(inlinedStat))
634645
}
635-
inlined(tpd.ClassDefWithParents(inlinedCls, constr, impl.parents, body))._2.withSpan(clDef.span) // TODO adapt parents
646+
val clsDef1 = tpd.ClassDefWithParents(inlinedSym, constr, tmpl.parents :+ This(ctx.owner.asClass).select(clsDef.symbol), body)
647+
inlined(clsDef1)._2.withSpan(clsDef.span) // TODO adapt parents
636648

637649
private def inlinedTypeDef(tdef: TypeDef, inlinedSym: Symbol)(using Context): TypeDef =
638650
tpd.TypeDef(inlinedSym.asType).withSpan(parent.span)

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

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@ import dotty.tools.dotc.ast.Trees._
1111
import dotty.tools.dotc.quoted._
1212
import dotty.tools.dotc.inlines.Inlines
1313
import dotty.tools.dotc.ast.TreeMapWithImplicits
14-
import dotty.tools.dotc.core.DenotTransformers.IdentityDenotTransformer
14+
import dotty.tools.dotc.core.DenotTransformers.SymTransformer
1515
import dotty.tools.dotc.staging.StagingLevel
16+
import dotty.tools.dotc.core.SymDenotations.SymDenotation
17+
import dotty.tools.dotc.core.StdNames.str
1618

1719
import scala.collection.mutable.ListBuffer
1820

1921
/** Inlines all calls to inline methods that are not in an inline method or a quote */
20-
class Inlining extends MacroTransform {
22+
class Inlining extends MacroTransform, SymTransformer {
2123

2224
import tpd._
2325

@@ -58,6 +60,33 @@ class Inlining extends MacroTransform {
5860
new InliningTreeMap().transform(tree)
5961
}
6062

63+
override def transformSym(sym: SymDenotation)(using Context): SymDenotation =
64+
if sym.isClass && sym.owner.isInlineTrait && !sym.is(Module) then
65+
sym.copySymDenotation(name = sym.name ++ str.INLINE_TRAIT_INNER_CLASS_SUFFIX, initFlags = (sym.flags &~ Final) | Trait)
66+
else
67+
sym
68+
69+
def transformInlineClasses(tree: Tree)(using Context): Tree =
70+
val tpd.TypeDef(name, tmpl: Template) = tree: @unchecked
71+
val body1 = tmpl.body.flatMap {
72+
case tdef @ tpd.TypeDef(name, tmpl1: Template) =>
73+
val newTrait = cpy.TypeDef(tdef)(name = name ++ str.INLINE_TRAIT_INNER_CLASS_SUFFIX)
74+
val newTypeSym = newSymbol(
75+
owner = tree.symbol,
76+
name = name.asTypeName,
77+
flags = tdef.symbol.flags & (Private | Protected),
78+
info = Types.TypeBounds.upper(newTrait.symbol.typeRef),
79+
privateWithin = tdef.symbol.privateWithin,
80+
coord = tdef.symbol.coord,
81+
nestingLevel = tdef.symbol.nestingLevel,
82+
).asType
83+
List(newTrait, TypeDef(newTypeSym))
84+
case member =>
85+
List(member)
86+
}
87+
val tmpl1 = cpy.Template(tmpl)(body = body1)
88+
cpy.TypeDef(tree)(name, tmpl1)
89+
6190
private class InliningTreeMap extends TreeMapWithImplicits {
6291

6392
/** List of top level classes added by macro annotation in a package object.
@@ -67,9 +96,12 @@ class Inlining extends MacroTransform {
6796

6897
override def transform(tree: Tree)(using Context): Tree = {
6998
tree match
99+
case tree: TypeDef if tree.symbol.isInlineTrait =>
100+
transformInlineClasses(tree)
70101
case tree: TypeDef if Inlines.needsInlining(tree) =>
71102
val tree1 = super.transform(tree)
72103
if tree1.tpe.isError then tree1
104+
else if tree1.symbol.isInlineTrait then transformInlineClasses(tree1)
73105
else Inlines.inlineParentInlineTraits(tree1)
74106
case tree: MemberDef =>
75107
if tree.symbol.is(Inline) then tree

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

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,8 @@ object RefChecks {
340340
* of class `clazz` are met.
341341
*/
342342
def checkOverride(checkSubType: (Type, Type) => Context ?=> Boolean, member: Symbol, other: Symbol): Unit =
343+
def overridesInlineTraitMember = other.owner.ownersIterator.exists(_.isInlineTrait) && member.is(Synthetic)
344+
343345
def memberTp(self: Type) =
344346
if (member.isClass) TypeAlias(member.typeRef.EtaExpand(member.typeParams))
345347
else self.memberInfo(member)
@@ -415,12 +417,13 @@ object RefChecks {
415417

416418
def overrideTargetNameError() =
417419
val otherTargetName = i"@targetName(${other.targetName})"
418-
if member.hasTargetName(member.name) then
419-
overrideError(i"misses a target name annotation $otherTargetName")
420-
else if other.hasTargetName(other.name) then
421-
overrideError(i"should not have a @targetName annotation since the overridden member hasn't one either")
422-
else
423-
overrideError(i"has a different target name annotation; it should be $otherTargetName")
420+
if !overridesInlineTraitMember then
421+
if member.hasTargetName(member.name) then
422+
overrideError(i"misses a target name annotation $otherTargetName")
423+
else if other.hasTargetName(other.name) then
424+
overrideError(i"should not have a @targetName annotation since the overridden member hasn't one either")
425+
else
426+
overrideError(i"has a different target name annotation; it should be $otherTargetName")
424427

425428
//Console.println(infoString(member) + " overrides " + infoString(other) + " in " + clazz);//DEBUG
426429

@@ -465,7 +468,7 @@ object RefChecks {
465468
overrideError("cannot be used here - opaque type aliases cannot be overridden")
466469
else if (!other.is(Deferred) && member.isClass)
467470
overrideError("cannot be used here - classes can only override abstract types")
468-
else if other.isEffectivelyFinal && !(other.owner.isInlineTrait && member.is(Synthetic)) then // (1.2)
471+
else if (other.isEffectivelyFinal && !overridesInlineTraitMember) then // (1.2)
469472
overrideError(i"cannot override final member ${other.showLocated}")
470473
else if (member.is(ExtensionMethod) && !other.is(ExtensionMethod)) // (1.3)
471474
overrideError("is an extension method, cannot override a normal method")

0 commit comments

Comments
 (0)