Skip to content

Commit 97299fc

Browse files
DougGregorAnthonyLatsis
authored andcommitted
Parse "late" specifiers for type attributes
The only "late" specifier at the moment is `nonisolated`, used by protocol conformances. Fixes issue #3109. (cherry picked from commit 1856087)
1 parent 8bab9ce commit 97299fc

File tree

2 files changed

+31
-3
lines changed

2 files changed

+31
-3
lines changed

Sources/SwiftParser/Types.swift

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ extension Parser {
100100
RawAttributedTypeSyntax(
101101
specifiers: specifiersAndAttributes.specifiers,
102102
attributes: specifiersAndAttributes.attributes,
103+
lateSpecifiers: specifiersAndAttributes.lateSpecifiers,
103104
baseType: base,
104105
arena: self.arena
105106
)
@@ -1221,7 +1222,8 @@ extension Parser {
12211222
misplacedSpecifiers: [RawTokenSyntax] = []
12221223
) -> (
12231224
specifiers: RawTypeSpecifierListSyntax,
1224-
attributes: RawAttributeListSyntax
1225+
attributes: RawAttributeListSyntax,
1226+
lateSpecifiers: RawTypeSpecifierListSyntax
12251227
)? {
12261228
var specifiers: [RawTypeSpecifierListSyntax.Element] = []
12271229
SPECIFIER_PARSING: while canHaveParameterSpecifier {
@@ -1260,7 +1262,14 @@ extension Parser {
12601262
attributes = nil
12611263
}
12621264

1263-
guard !specifiers.isEmpty || attributes != nil else {
1265+
// Only handle `nonisolated` as a late specifier.
1266+
var lateSpecifiers: [RawTypeSpecifierListSyntax.Element] = []
1267+
if self.at(.keyword(.nonisolated)) &&
1268+
!(self.peek(isAt: .leftParen) && self.peek().isAtStartOfLine) {
1269+
lateSpecifiers.append(parseNonisolatedTypeSpecifier())
1270+
}
1271+
1272+
guard !specifiers.isEmpty || attributes != nil || !lateSpecifiers.isEmpty else {
12641273
// No specifiers or attributes on this type
12651274
return nil
12661275
}
@@ -1271,9 +1280,17 @@ extension Parser {
12711280
specifierList = RawTypeSpecifierListSyntax(elements: specifiers, arena: arena)
12721281
}
12731282

1283+
let lateSpecifierList: RawTypeSpecifierListSyntax
1284+
if lateSpecifiers.isEmpty {
1285+
lateSpecifierList = self.emptyCollection(RawTypeSpecifierListSyntax.self)
1286+
} else {
1287+
lateSpecifierList = RawTypeSpecifierListSyntax(elements: lateSpecifiers, arena: arena)
1288+
}
1289+
12741290
return (
12751291
specifierList,
1276-
attributes ?? self.emptyCollection(RawAttributeListSyntax.self)
1292+
attributes ?? self.emptyCollection(RawAttributeListSyntax.self),
1293+
lateSpecifierList
12771294
)
12781295
}
12791296

Tests/SwiftParserTest/DeclarationTests.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,17 @@ final class DeclarationTests: ParserTestCase {
807807
"""
808808
)
809809

810+
assertParse(
811+
"""
812+
extension Int: @preconcurrency nonisolated Q {}
813+
"""
814+
)
815+
816+
assertParse(
817+
"""
818+
extension Int: @unsafe nonisolated Q {}
819+
"""
820+
)
810821
}
811822

812823
func testParseDynamicReplacement() {

0 commit comments

Comments
 (0)