Skip to content

Commit c0bce0d

Browse files
committed
don't crash when keys are not unique in macro expansion
1 parent 9c91502 commit c0bce0d

File tree

2 files changed

+45
-4
lines changed

2 files changed

+45
-4
lines changed

Diff for: Sources/SwiftSyntaxMacroExpansion/MacroReplacement.swift

+6-4
Original file line numberDiff line numberDiff line change
@@ -363,19 +363,21 @@ extension MacroDeclSyntax {
363363
// FIXME: Do real call-argument matching between the argument list and the
364364
// macro parameter list, porting over from the compiler.
365365
let parameterReplacements = Dictionary(
366-
uniqueKeysWithValues: replacements.map { replacement in
366+
replacements.map { replacement in
367367
(replacement.reference, replacement.parameterIndex)
368-
}
368+
},
369+
uniquingKeysWith: { l, r in l }
369370
)
370371
let arguments: [ExprSyntax] =
371372
argumentList?.map { element in
372373
element.expression
373374
} ?? []
374375

375376
let genericReplacements = Dictionary(
376-
uniqueKeysWithValues: genericReplacements.map { replacement in
377+
genericReplacements.map { replacement in
377378
(replacement.reference, replacement.parameterIndex)
378-
}
379+
},
380+
uniquingKeysWith: { l, r in l }
379381
)
380382
let genericArguments: [TypeSyntax] =
381383
genericArgumentList?.arguments.map { element in

Diff for: Tests/SwiftSyntaxMacroExpansionTest/MacroReplacementTests.swift

+39
Original file line numberDiff line numberDiff line change
@@ -301,4 +301,43 @@ final class MacroReplacementTests: XCTestCase {
301301
"""
302302
)
303303
}
304+
305+
func testMacroExpansion_dontCrashOnDuplicates() throws {
306+
let macro: DeclSyntax =
307+
"""
308+
macro gen(a: Array<Int>) = #other<A>(first: a)
309+
"""
310+
311+
let use: ExprSyntax =
312+
"""
313+
#otheren<Int>(a: [1, 2, 3])
314+
"""
315+
316+
let macroDecl = macro.as(MacroDeclSyntax.self)!
317+
let definition = try macroDecl.checkDefinition()
318+
guard case let .expansion(expansion, replacements, genericReplacements) = definition else {
319+
XCTFail("not a normal expansion")
320+
return
321+
}
322+
323+
var replacementsWithDupes = replacements
324+
replacementsWithDupes.append(contentsOf: replacements)
325+
var genericReplacementsWithDupes = genericReplacements
326+
genericReplacementsWithDupes.append(contentsOf: genericReplacements)
327+
328+
XCTAssertEqual(genericReplacements.count, 0)
329+
330+
let expandedSyntax = macroDecl.expand(
331+
use.as(MacroExpansionExprSyntax.self)!,
332+
definition: expansion,
333+
replacements: replacementsWithDupes,
334+
genericReplacements: genericReplacementsWithDupes
335+
)
336+
assertStringsEqualWithDiff(
337+
expandedSyntax.description,
338+
"""
339+
#other<A>(first: [1, 2, 3])
340+
"""
341+
)
342+
}
304343
}

0 commit comments

Comments
 (0)