@@ -2,6 +2,8 @@ package dotty.tools
22package dotc
33package inlines
44
5+ import scala .collection .mutable
6+
57import dotty .tools .dotc .ast .{Trees , tpd , untpd }
68import Trees ._
79import core ._
@@ -22,14 +24,20 @@ import transform.SymUtils.*
2224import config .Printers .inlining
2325import util .Property
2426import dotty .tools .dotc .transform .TreeMapWithStages ._
27+ import dotty .tools .dotc .ast .desugar .packageObjectName
28+ import dotty .tools .dotc .core .StdNames .str
29+ import dotty .tools .dotc .util .{Spans , SrcPos }
2530
2631object PrepareInlineable {
2732 import tpd ._
2833
2934 private val InlineAccessorsKey = new Property .Key [InlineAccessors ]
35+ private val InlineAccessorsModuleKey = new Property .Key [mutable.Map [Symbol , Symbol ]]
3036
3137 def initContext (ctx : Context ): Context =
32- ctx.fresh.setProperty(InlineAccessorsKey , new InlineAccessors )
38+ ctx.fresh
39+ .setProperty(InlineAccessorsKey , new InlineAccessors )
40+ .setProperty(InlineAccessorsModuleKey , mutable.Map .empty)
3341
3442 def makeInlineable (tree : Tree )(using Context ): Tree =
3543 ctx.property(InlineAccessorsKey ).get.makeInlineable(tree)
@@ -39,6 +47,36 @@ object PrepareInlineable {
3947 case Some (inlineAccessors) => inlineAccessors.addAccessorDefs(cls, body)
4048 case _ => body
4149
50+ def inlineAccessorsModule (topLevelClass : Symbol )(using Context ): Symbol =
51+ assert(topLevelClass.asClass.owner.is(Package ), topLevelClass)
52+ ctx.property(InlineAccessorsModuleKey ).get.getOrElse(topLevelClass, NoSymbol )
53+
54+ def requiredInlineAccessorsModule (topLevelClass : Symbol )(using Context ): Symbol =
55+ assert(topLevelClass.asClass.owner.is(Package ), topLevelClass)
56+ ctx.property(InlineAccessorsModuleKey ) match
57+ case Some (inlineAccessorsModule) => inlineAccessorsModule.getOrElseUpdate(topLevelClass, newAccessorModule())
58+ case None => NoSymbol
59+
60+ private def newAccessorModule ()(using Context ): ClassSymbol =
61+ val mod = dotc.core.Symbols .newNormalizedModuleSymbol(
62+ ctx.owner.topLevelClass.owner,
63+ inlineAccessorObjectName,
64+ ModuleValCreationFlags & Invisible ,
65+ ModuleClassCreationFlags & Invisible ,
66+ List (defn.ObjectClass .typeRef),
67+ dotc.core.Scopes .newScope,
68+ NoSymbol ,
69+ coord = ctx.owner.topLevelClass.span
70+ )
71+ val cls = mod.moduleClass.asClass
72+ cls.enter(dotc.core.Symbols .newConstructor(cls, dotc.core.Flags .Synthetic , Nil , Nil ))
73+ cls
74+
75+ private def inlineAccessorObjectName (using Context ): TermName =
76+ val fileName = ctx.source.file.name
77+ val sourceName = ctx.owner.topLevelClass.name
78+ (sourceName ++ str.TOPLEVEL_INLINE_SUFFIX ).toTermName
79+
4280 class InlineAccessors extends AccessProxies {
4381
4482 /** If an inline accessor name wraps a unique inline name, this is taken as indication
@@ -107,10 +145,25 @@ object PrepareInlineable {
107145 report.error(" Implementation restriction: cannot use private constructors in inline methods" , tree.srcPos)
108146 tree // TODO: create a proper accessor for the private constructor
109147 }
110- else useAccessor(tree)
148+ else
149+ val nearestHost = AccessProxies .hostForAccessorOf(tree.symbol)
150+ val topClass = ctx.owner.topLevelClass
151+ if tree.symbol.owner.isStaticOwner && ! nearestHost.isStaticOwner then
152+ // Generate the accessor for backwards compatibility with 3.0-3.2
153+ useAccessor(tree, nearestHost)
154+ // Generate and use the accessor for 3.3+
155+ useAccessor(tree, requiredInlineAccessorsModule(topClass))
156+ else if nearestHost.is(Package ) then
157+ // Generate the accessor for backwards compatibility with 3.0-3.2
158+ useAccessor(tree, topClass)
159+ // Generate and use the accessor for 3.3+
160+ useAccessor(tree, requiredInlineAccessorsModule(topClass))
161+ else
162+ useAccessor(tree, nearestHost)
111163 case _ =>
112164 tree
113165 }
166+
114167 override def ifNoHost (reference : RefTree )(using Context ): Tree = reference
115168 }
116169
0 commit comments