Skip to content

Commit 7116773

Browse files
committed
Split notion of rawNodeArena and allocationArena
The `arena` parameter to `replacingSelf` and `replacingChild` served two purposes: To keep the arena of `raw`/`newChild` alive and to specify which arena new nodes should be allocated in. In almost all cases, these areneas coincided but for `SyntaxRewriter.rewrite` they diverged, causing an arena to be added as a child arena after it itself has children, causing a precondition failure. Split these different purposes of arenas into two different parameters.
1 parent f242e73 commit 7116773

File tree

18 files changed

+932
-384
lines changed

18 files changed

+932
-384
lines changed

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftparser/ParserEntryFile.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ let parserEntryFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
7272
defer { withExtendedLifetime(parser) {} }
7373
let node = parser.\(raw: parserFunction)()
7474
let raw = RawSyntax(parser.parseRemainder(into: node))
75-
return Syntax(raw: raw, arena: raw.arena).cast(Self.self)
75+
return Syntax(raw: raw, rawNodeArena: raw.arena).cast(Self.self)
7676
}
7777
}
7878
"""

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftsyntax/SyntaxNodesFile.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ func syntaxNode(emitKind: SyntaxNodeKind) -> SourceFileSyntax {
129129
"""
130130
)
131131
}
132-
StmtSyntax("return SyntaxData.forRoot(raw, arena: arena)")
132+
StmtSyntax("return SyntaxData.forRoot(raw, rawNodeArena: arena)")
133133
}
134134
)
135135

@@ -207,7 +207,7 @@ func syntaxNode(emitKind: SyntaxNodeKind) -> SourceFileSyntax {
207207
collection = RawSyntax.makeLayout(kind: SyntaxKind.\(raw: childNode.varOrCaseName),
208208
from: [element.raw], arena: arena)
209209
}
210-
let newData = data.replacingChild(at: \(raw: index), with: collection, arena: arena)
210+
let newData = data.replacingChild(at: \(raw: index), with: collection, rawNodeArena: arena, allocationArena: arena)
211211
return \(node.kind.syntaxType)(newData)
212212
}
213213
"""

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftsyntax/SyntaxRewriterFile.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
326326
let newRaw = node.raw.layoutView!.replacingLayout(with: Array(newLayout), arena: arena)
327327
// 'withExtendedLifetime' to keep 'SyntaxArena's of them alive until here.
328328
return withExtendedLifetime(rewrittens) {
329-
Syntax(raw: newRaw, arena: arena).cast(SyntaxType.self)
329+
Syntax(raw: newRaw, rawNodeArena: arena).cast(SyntaxType.self)
330330
}
331331
} else {
332332
// No child node was rewritten. So no need to change this node as well.
@@ -343,7 +343,7 @@ let syntaxRewriterFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
343343
public func rewrite(_ node: Syntax) -> Syntax {
344344
let rewritten = self.visit(node)
345345
return withExtendedLifetime(rewritten) {
346-
return Syntax(node.data.replacingSelf(rewritten.raw, arena: rewritten.raw.arena))
346+
return Syntax(node.data.replacingSelf(rewritten.raw, rawNodeArena: rewritten.raw.arena, allocationArena: SyntaxArena()))
347347
}
348348
}
349349
"""

Sources/SwiftParser/generated/Parser+Entry.swift

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ extension AccessorDeclSyntax: SyntaxParseable {
5555
}
5656
let node = parser.parseAccessorDecl()
5757
let raw = RawSyntax(parser.parseRemainder(into: node))
58-
return Syntax(raw: raw, arena: raw.arena).cast(Self.self)
58+
return Syntax(raw: raw, rawNodeArena: raw.arena).cast(Self.self)
5959
}
6060
}
6161

@@ -73,7 +73,7 @@ extension AttributeSyntax: SyntaxParseable {
7373
}
7474
let node = parser.parseAttribute()
7575
let raw = RawSyntax(parser.parseRemainder(into: node))
76-
return Syntax(raw: raw, arena: raw.arena).cast(Self.self)
76+
return Syntax(raw: raw, rawNodeArena: raw.arena).cast(Self.self)
7777
}
7878
}
7979

@@ -91,7 +91,7 @@ extension CatchClauseSyntax: SyntaxParseable {
9191
}
9292
let node = parser.parseCatchClause()
9393
let raw = RawSyntax(parser.parseRemainder(into: node))
94-
return Syntax(raw: raw, arena: raw.arena).cast(Self.self)
94+
return Syntax(raw: raw, rawNodeArena: raw.arena).cast(Self.self)
9595
}
9696
}
9797

@@ -109,7 +109,7 @@ extension ClosureParameterSyntax: SyntaxParseable {
109109
}
110110
let node = parser.parseClosureParameter()
111111
let raw = RawSyntax(parser.parseRemainder(into: node))
112-
return Syntax(raw: raw, arena: raw.arena).cast(Self.self)
112+
return Syntax(raw: raw, rawNodeArena: raw.arena).cast(Self.self)
113113
}
114114
}
115115

@@ -127,7 +127,7 @@ extension CodeBlockItemSyntax: SyntaxParseable {
127127
}
128128
let node = parser.parseNonOptionalCodeBlockItem()
129129
let raw = RawSyntax(parser.parseRemainder(into: node))
130-
return Syntax(raw: raw, arena: raw.arena).cast(Self.self)
130+
return Syntax(raw: raw, rawNodeArena: raw.arena).cast(Self.self)
131131
}
132132
}
133133

@@ -145,7 +145,7 @@ extension DeclSyntax: SyntaxParseable {
145145
}
146146
let node = parser.parseDeclaration()
147147
let raw = RawSyntax(parser.parseRemainder(into: node))
148-
return Syntax(raw: raw, arena: raw.arena).cast(Self.self)
148+
return Syntax(raw: raw, rawNodeArena: raw.arena).cast(Self.self)
149149
}
150150
}
151151

@@ -163,7 +163,7 @@ extension EnumCaseParameterSyntax: SyntaxParseable {
163163
}
164164
let node = parser.parseEnumCaseParameter()
165165
let raw = RawSyntax(parser.parseRemainder(into: node))
166-
return Syntax(raw: raw, arena: raw.arena).cast(Self.self)
166+
return Syntax(raw: raw, rawNodeArena: raw.arena).cast(Self.self)
167167
}
168168
}
169169

@@ -181,7 +181,7 @@ extension ExprSyntax: SyntaxParseable {
181181
}
182182
let node = parser.parseExpression()
183183
let raw = RawSyntax(parser.parseRemainder(into: node))
184-
return Syntax(raw: raw, arena: raw.arena).cast(Self.self)
184+
return Syntax(raw: raw, rawNodeArena: raw.arena).cast(Self.self)
185185
}
186186
}
187187

@@ -199,7 +199,7 @@ extension FunctionParameterSyntax: SyntaxParseable {
199199
}
200200
let node = parser.parseFunctionParameter()
201201
let raw = RawSyntax(parser.parseRemainder(into: node))
202-
return Syntax(raw: raw, arena: raw.arena).cast(Self.self)
202+
return Syntax(raw: raw, rawNodeArena: raw.arena).cast(Self.self)
203203
}
204204
}
205205

@@ -217,7 +217,7 @@ extension GenericParameterClauseSyntax: SyntaxParseable {
217217
}
218218
let node = parser.parseGenericParameters()
219219
let raw = RawSyntax(parser.parseRemainder(into: node))
220-
return Syntax(raw: raw, arena: raw.arena).cast(Self.self)
220+
return Syntax(raw: raw, rawNodeArena: raw.arena).cast(Self.self)
221221
}
222222
}
223223

@@ -235,7 +235,7 @@ extension MemberDeclBlockSyntax: SyntaxParseable {
235235
}
236236
let node = parser.parseMemberDeclList()
237237
let raw = RawSyntax(parser.parseRemainder(into: node))
238-
return Syntax(raw: raw, arena: raw.arena).cast(Self.self)
238+
return Syntax(raw: raw, rawNodeArena: raw.arena).cast(Self.self)
239239
}
240240
}
241241

@@ -253,7 +253,7 @@ extension PatternSyntax: SyntaxParseable {
253253
}
254254
let node = parser.parsePattern()
255255
let raw = RawSyntax(parser.parseRemainder(into: node))
256-
return Syntax(raw: raw, arena: raw.arena).cast(Self.self)
256+
return Syntax(raw: raw, rawNodeArena: raw.arena).cast(Self.self)
257257
}
258258
}
259259

@@ -271,7 +271,7 @@ extension SourceFileSyntax: SyntaxParseable {
271271
}
272272
let node = parser.parseSourceFile()
273273
let raw = RawSyntax(parser.parseRemainder(into: node))
274-
return Syntax(raw: raw, arena: raw.arena).cast(Self.self)
274+
return Syntax(raw: raw, rawNodeArena: raw.arena).cast(Self.self)
275275
}
276276
}
277277

@@ -289,7 +289,7 @@ extension StmtSyntax: SyntaxParseable {
289289
}
290290
let node = parser.parseStatement()
291291
let raw = RawSyntax(parser.parseRemainder(into: node))
292-
return Syntax(raw: raw, arena: raw.arena).cast(Self.self)
292+
return Syntax(raw: raw, rawNodeArena: raw.arena).cast(Self.self)
293293
}
294294
}
295295

@@ -307,7 +307,7 @@ extension SwitchCaseSyntax: SyntaxParseable {
307307
}
308308
let node = parser.parseSwitchCase()
309309
let raw = RawSyntax(parser.parseRemainder(into: node))
310-
return Syntax(raw: raw, arena: raw.arena).cast(Self.self)
310+
return Syntax(raw: raw, rawNodeArena: raw.arena).cast(Self.self)
311311
}
312312
}
313313

@@ -325,7 +325,7 @@ extension TypeSyntax: SyntaxParseable {
325325
}
326326
let node = parser.parseType()
327327
let raw = RawSyntax(parser.parseRemainder(into: node))
328-
return Syntax(raw: raw, arena: raw.arena).cast(Self.self)
328+
return Syntax(raw: raw, rawNodeArena: raw.arena).cast(Self.self)
329329
}
330330
}
331331

Sources/SwiftSyntax/Raw/RawSyntaxLayoutView.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ public struct RawSyntaxLayoutView {
5454
}
5555

5656
/// Creates a new node of the same kind but with children replaced by `elements`.
57+
///
58+
/// The newly created syntax node is allocated in `arena`.
5759
@_spi(RawSyntax)
5860
public func replacingLayout(
5961
with elements: some Collection<RawSyntax?>,

Sources/SwiftSyntax/Syntax.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ public struct Syntax: SyntaxProtocol, SyntaxHashable {
6969
}
7070

7171
@_spi(RawSyntax)
72-
public init(raw: RawSyntax, arena: __shared SyntaxArena) {
73-
self.init(.forRoot(raw, arena: arena))
72+
public init(raw: RawSyntax, rawNodeArena: __shared SyntaxArena) {
73+
self.init(.forRoot(raw, rawNodeArena: rawNodeArena))
7474
}
7575

7676
/// Create a ``Syntax`` node from a specialized syntax node.
@@ -229,7 +229,7 @@ extension SyntaxProtocol {
229229
// Make sure `self` (and thus the arena of `self.raw`) can’t get deallocated
230230
// before the detached node can be created.
231231
return withExtendedLifetime(self) {
232-
return Syntax(raw: self.raw, arena: self.raw.arena).cast(Self.self)
232+
return Syntax(raw: self.raw, rawNodeArena: self.raw.arena).cast(Self.self)
233233
}
234234
}
235235

Sources/SwiftSyntax/SyntaxCollection.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ extension SyntaxCollection {
4040
from: children.map { $0.raw },
4141
arena: arena
4242
)
43-
self.init(SyntaxData.forRoot(raw, arena: arena))
43+
self.init(SyntaxData.forRoot(raw, rawNodeArena: arena))
4444
}
4545

4646
/// The number of elements, `present` or `missing`, in this collection.
@@ -57,7 +57,7 @@ extension SyntaxCollection {
5757
internal func replacingLayout(_ layout: [RawSyntax?]) -> Self {
5858
let arena = SyntaxArena()
5959
let newRaw = layoutView.replacingLayout(with: layout, arena: arena)
60-
let newData = data.replacingSelf(newRaw, arena: arena)
60+
let newData = data.replacingSelf(newRaw, rawNodeArena: arena, allocationArena: arena)
6161
return Syntax(newData).cast(Self.self)
6262
}
6363

Sources/SwiftSyntax/SyntaxData.swift

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,9 @@ struct SyntaxData {
278278
/// `arena` must be the arena in which `raw` is allocated. It is passed to
279279
/// make sure the arena doesn’t get de-allocated before the ``SyntaxData`` has
280280
/// a chance to retain it.
281-
static func forRoot(_ raw: RawSyntax, arena: SyntaxArena) -> SyntaxData {
282-
precondition(arena === raw.arena)
283-
return SyntaxData(raw, info: .root(.init(arena: arena)))
281+
static func forRoot(_ raw: RawSyntax, rawNodeArena: SyntaxArena) -> SyntaxData {
282+
precondition(rawNodeArena === raw.arena)
283+
return SyntaxData(raw, info: .root(.init(arena: rawNodeArena)))
284284
}
285285

286286
/// Returns the child data at the provided index in this data's layout.
@@ -304,19 +304,23 @@ struct SyntaxData {
304304
/// Creates a copy of `self` and recursively creates `SyntaxData` nodes up to
305305
/// the root.
306306
///
307-
/// `arena` is the arena in which `newRaw` resides. The new nodes will be
308-
/// allocated in this arena.
309-
func replacingSelf(_ newRaw: RawSyntax, arena: SyntaxArena) -> SyntaxData {
310-
precondition(newRaw.arena === arena)
307+
/// - Parameters:
308+
/// - newRaw: The node that should replace `self`
309+
/// - rawNodeArena: The arena in which `newRaw` resides
310+
/// - arena: The arena in which new nodes should be allocated
311+
/// - Returns: A syntax tree with all parents where this node has been
312+
/// replaced by `newRaw`
313+
func replacingSelf(_ newRaw: RawSyntax, rawNodeArena: SyntaxArena, allocationArena: SyntaxArena) -> SyntaxData {
314+
precondition(newRaw.arena === rawNodeArena)
311315
// If we have a parent already, then ask our current parent to copy itself
312316
// recursively up to the root.
313317
if let parent {
314-
let parentData = parent.replacingChild(at: indexInParent, with: newRaw, arena: arena)
318+
let parentData = parent.replacingChild(at: indexInParent, with: newRaw, rawNodeArena: rawNodeArena, allocationArena: allocationArena)
315319
let newParent = Syntax(parentData)
316320
return SyntaxData(absoluteRaw.replacingSelf(newRaw, newRootId: parentData.nodeId.rootId), parent: newParent)
317321
} else {
318322
// Otherwise, we're already the root, so return the new root data.
319-
return .forRoot(newRaw, arena: arena)
323+
return .forRoot(newRaw, rawNodeArena: rawNodeArena)
320324
}
321325
}
322326

@@ -327,43 +331,50 @@ struct SyntaxData {
327331
/// - index: The index pointing to where in the raw layout to place this
328332
/// child.
329333
/// - newChild: The raw syntax for the new child to replace.
334+
/// - newChildArena: The arena in which `newChild` resides.
330335
/// - arena: The arena in which the new node will be allocated.
331336
/// - Returns: The new root node created by this operation, and the new child
332337
/// syntax data.
333338
/// - SeeAlso: replacingSelf(_:)
334-
func replacingChild(at index: Int, with newChild: RawSyntax?, arena: SyntaxArena) -> SyntaxData {
335-
let newRaw = raw.layoutView!.replacingChild(at: index, with: newChild, arena: arena)
336-
return replacingSelf(newRaw, arena: arena)
339+
func replacingChild(at index: Int, with newChild: RawSyntax?, rawNodeArena: SyntaxArena?, allocationArena: SyntaxArena) -> SyntaxData {
340+
precondition(newChild?.arena === rawNodeArena || newChild == nil)
341+
// After newRaw has been allocated in `allocationArena`, `rawNodeArena` will
342+
// be a child arena of `allocationArena` and thus, `allocationArena` will
343+
// keep `newChild` alive.
344+
let newRaw = withExtendedLifetime(rawNodeArena) {
345+
raw.layoutView!.replacingChild(at: index, with: newChild, arena: allocationArena)
346+
}
347+
return replacingSelf(newRaw, rawNodeArena: allocationArena, allocationArena: allocationArena)
337348
}
338349

339350
/// Identical to `replacingChild(at: Int, with: RawSyntax?, arena: SyntaxArena)`
340351
/// that ensures that the arena of`newChild` doesn’t get de-allocated before
341352
/// `newChild` has been addded to the result.
342353
func replacingChild(at index: Int, with newChild: SyntaxData?, arena: SyntaxArena) -> SyntaxData {
343354
return withExtendedLifetime(newChild) {
344-
return replacingChild(at: index, with: newChild?.raw, arena: arena)
355+
return replacingChild(at: index, with: newChild?.raw, rawNodeArena: newChild?.raw.arena, allocationArena: arena)
345356
}
346357
}
347358

348359
func withLeadingTrivia(_ leadingTrivia: Trivia, arena: SyntaxArena) -> SyntaxData {
349360
if let raw = raw.withLeadingTrivia(leadingTrivia, arena: arena) {
350-
return replacingSelf(raw, arena: arena)
361+
return replacingSelf(raw, rawNodeArena: arena, allocationArena: arena)
351362
} else {
352363
return self
353364
}
354365
}
355366

356367
func withTrailingTrivia(_ trailingTrivia: Trivia, arena: SyntaxArena) -> SyntaxData {
357368
if let raw = raw.withTrailingTrivia(trailingTrivia, arena: arena) {
358-
return replacingSelf(raw, arena: arena)
369+
return replacingSelf(raw, rawNodeArena: arena, allocationArena: arena)
359370
} else {
360371
return self
361372
}
362373
}
363374

364375
func withPresence(_ presence: SourcePresence, arena: SyntaxArena) -> SyntaxData {
365376
if let raw = raw.tokenView?.withPresence(presence, arena: arena) {
366-
return replacingSelf(raw, arena: arena)
377+
return replacingSelf(raw, rawNodeArena: arena, allocationArena: arena)
367378
} else {
368379
return self
369380
}

Sources/SwiftSyntax/TokenSyntax.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public struct TokenSyntax: SyntaxProtocol, SyntaxHashable {
5858
tokenDiagnostic: nil,
5959
arena: arena
6060
)
61-
self.init(SyntaxData.forRoot(raw, arena: arena))
61+
self.init(SyntaxData.forRoot(raw, rawNodeArena: arena))
6262
}
6363

6464
/// Whether the token is present or missing.
@@ -107,7 +107,7 @@ public struct TokenSyntax: SyntaxProtocol, SyntaxHashable {
107107
}
108108
let arena = SyntaxArena()
109109
let newRaw = tokenView.withKind(newValue, arena: arena)
110-
let newData = data.replacingSelf(newRaw, arena: arena)
110+
let newData = data.replacingSelf(newRaw, rawNodeArena: arena, allocationArena: arena)
111111
self = TokenSyntax(newData)
112112
}
113113
}

Sources/SwiftSyntax/generated/SyntaxRewriter.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7184,7 +7184,7 @@ open class SyntaxRewriter {
71847184
let newRaw = node.raw.layoutView!.replacingLayout(with: Array(newLayout), arena: arena)
71857185
// 'withExtendedLifetime' to keep 'SyntaxArena's of them alive until here.
71867186
return withExtendedLifetime(rewrittens) {
7187-
Syntax(raw: newRaw, arena: arena).cast(SyntaxType.self)
7187+
Syntax(raw: newRaw, rawNodeArena: arena).cast(SyntaxType.self)
71887188
}
71897189
} else {
71907190
// No child node was rewritten. So no need to change this node as well.
@@ -7197,7 +7197,7 @@ open class SyntaxRewriter {
71977197
public func rewrite(_ node: Syntax) -> Syntax {
71987198
let rewritten = self.visit(node)
71997199
return withExtendedLifetime(rewritten) {
7200-
return Syntax(node.data.replacingSelf(rewritten.raw, arena: rewritten.raw.arena))
7200+
return Syntax(node.data.replacingSelf(rewritten.raw, rawNodeArena: rewritten.raw.arena, allocationArena: SyntaxArena()))
72017201
}
72027202
}
72037203
}

0 commit comments

Comments
 (0)