@@ -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,21 @@ 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 }
30
+ import dotty .tools .dotc .typer .TopLevelExtensionModules .newAccessorModule
25
31
26
32
object PrepareInlineable {
27
33
import tpd ._
28
34
29
35
private val InlineAccessorsKey = new Property .Key [InlineAccessors ]
36
+ private val InlineAccessorsModuleKey = new Property .Key [mutable.Map [Symbol , Symbol ]]
30
37
31
38
def initContext (ctx : Context ): Context =
32
- ctx.fresh.setProperty(InlineAccessorsKey , new InlineAccessors )
39
+ ctx.fresh
40
+ .setProperty(InlineAccessorsKey , new InlineAccessors )
41
+ .setProperty(InlineAccessorsModuleKey , mutable.Map .empty)
33
42
34
43
def makeInlineable (tree : Tree )(using Context ): Tree =
35
44
ctx.property(InlineAccessorsKey ).get.makeInlineable(tree)
@@ -39,6 +48,19 @@ object PrepareInlineable {
39
48
case Some (inlineAccessors) => inlineAccessors.addAccessorDefs(cls, body)
40
49
case _ => body
41
50
51
+ def inlineAccessorsModule (topLevelClass : Symbol )(using Context ): Symbol =
52
+ assert(topLevelClass.asClass.owner.is(Package ), topLevelClass)
53
+ ctx.property(InlineAccessorsModuleKey ).get.getOrElse(topLevelClass, NoSymbol )
54
+
55
+ def requiredInlineAccessorsModule (topLevelClass : Symbol )(using Context ): Symbol =
56
+ assert(topLevelClass.asClass.owner.is(Package ), topLevelClass)
57
+ ctx.property(InlineAccessorsModuleKey ) match
58
+ case Some (inlineAccessorsModule) =>
59
+ inlineAccessorsModule.getOrElseUpdate(
60
+ topLevelClass,
61
+ newAccessorModule(str.TOPLEVEL_INLINE_SUFFIX ))
62
+ case None => NoSymbol
63
+
42
64
class InlineAccessors extends AccessProxies {
43
65
44
66
/** If an inline accessor name wraps a unique inline name, this is taken as indication
@@ -99,18 +121,33 @@ object PrepareInlineable {
99
121
* advantage that we can re-use the receiver as is. But it is only
100
122
* possible if the receiver is essentially this or an outer this, which is indicated
101
123
* by the test that we can find a host for the accessor.
124
+ *
125
+ * @param inlineSym symbol of the inline method
126
+ * @param compat use inline accessor format of 3.0-3.2
102
127
*/
103
- class MakeInlineableDirect (inlineSym : Symbol ) extends MakeInlineableMap (inlineSym) {
128
+ class MakeInlineableDirect (inlineSym : Symbol , compat : Boolean ) extends MakeInlineableMap (inlineSym) {
104
129
def preTransform (tree : Tree )(using Context ): Tree = tree match {
105
130
case tree : RefTree if needsAccessor(tree.symbol) =>
106
131
if (tree.symbol.isConstructor) {
107
132
report.error(" Implementation restriction: cannot use private constructors in inline methods" , tree.srcPos)
108
133
tree // TODO: create a proper accessor for the private constructor
109
134
}
110
- else useAccessor(tree)
135
+ else if compat then
136
+ // Generate the accessor for backwards compatibility with 3.0-3.3
137
+ val nearestHost = AccessProxies .hostForAccessorOf(tree.symbol)
138
+ val host = if nearestHost.is(Package ) then ctx.owner.topLevelClass else nearestHost
139
+ useAccessor(tree, host)
140
+ else
141
+ // Generate the accessor for 3.4+
142
+ val nearestHost = AccessProxies .hostForAccessorOf(tree.symbol)
143
+ if nearestHost.is(Package ) || (tree.symbol.owner.isStaticOwner && ! nearestHost.isStaticOwner) then
144
+ useAccessor(tree, requiredInlineAccessorsModule(ctx.owner.topLevelClass))
145
+ else
146
+ useAccessor(tree, nearestHost)
111
147
case _ =>
112
148
tree
113
149
}
150
+
114
151
override def ifNoHost (reference : RefTree )(using Context ): Tree = reference
115
152
}
116
153
@@ -226,8 +263,12 @@ object PrepareInlineable {
226
263
// so no accessors are needed for them.
227
264
tree
228
265
else
266
+ // Generate inline accessors for 3.0-3.3
267
+ new MakeInlineablePassing (inlineSym).transform(
268
+ new MakeInlineableDirect (inlineSym, compat = true ).transform(tree))
269
+ // Generate and use inline accessors for 3.4+
229
270
new MakeInlineablePassing (inlineSym).transform(
230
- new MakeInlineableDirect (inlineSym).transform(tree))
271
+ new MakeInlineableDirect (inlineSym, compat = false ).transform(tree))
231
272
}
232
273
}
233
274
0 commit comments