@@ -2,6 +2,8 @@ package dotty.tools
2
2
package dotc
3
3
package inlines
4
4
5
+ import scala .collection .mutable
6
+
5
7
import dotty .tools .dotc .ast .{Trees , tpd , untpd }
6
8
import Trees ._
7
9
import core ._
@@ -22,14 +24,20 @@ import transform.SymUtils.*
22
24
import config .Printers .inlining
23
25
import util .Property
24
26
import 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 }
25
30
26
31
object PrepareInlineable {
27
32
import tpd ._
28
33
29
34
private val InlineAccessorsKey = new Property .Key [InlineAccessors ]
35
+ private val InlineAccessorsModuleKey = new Property .Key [mutable.Map [Symbol , Symbol ]]
30
36
31
37
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)
33
41
34
42
def makeInlineable (tree : Tree )(using Context ): Tree =
35
43
ctx.property(InlineAccessorsKey ).get.makeInlineable(tree)
@@ -39,6 +47,36 @@ object PrepareInlineable {
39
47
case Some (inlineAccessors) => inlineAccessors.addAccessorDefs(cls, body)
40
48
case _ => body
41
49
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
+
42
80
class InlineAccessors extends AccessProxies {
43
81
44
82
/** If an inline accessor name wraps a unique inline name, this is taken as indication
@@ -107,10 +145,25 @@ object PrepareInlineable {
107
145
report.error(" Implementation restriction: cannot use private constructors in inline methods" , tree.srcPos)
108
146
tree // TODO: create a proper accessor for the private constructor
109
147
}
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)
111
163
case _ =>
112
164
tree
113
165
}
166
+
114
167
override def ifNoHost (reference : RefTree )(using Context ): Tree = reference
115
168
}
116
169
0 commit comments