From 7e8b8a53856b3c30eab368ffc1685a112c73e807 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Wed, 27 Aug 2025 09:47:58 -0700 Subject: [PATCH 1/3] Add ability to parse default types for generic parameters --- .../Sources/SyntaxSupport/GenericNodes.swift | 11 +++ Sources/SwiftParser/Declarations.swift | 31 ++++++++ .../generated/ChildNameForDiagnostics.swift | 2 + .../generated/ChildNameForKeyPath.swift | 12 ++- .../RenamedChildrenCompatibility.swift | 14 +++- .../generated/raw/RawSyntaxNodesGHI.swift | 40 ++++++++-- .../generated/raw/RawSyntaxValidation.swift | 8 +- .../syntaxNodes/SyntaxNodesGHI.swift | 73 +++++++++++++++++-- 8 files changed, 168 insertions(+), 23 deletions(-) diff --git a/CodeGeneration/Sources/SyntaxSupport/GenericNodes.swift b/CodeGeneration/Sources/SyntaxSupport/GenericNodes.swift index c6254e9ebd1..61ea38f5293 100644 --- a/CodeGeneration/Sources/SyntaxSupport/GenericNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/GenericNodes.swift @@ -125,6 +125,17 @@ public let GENERIC_NODES: [Node] = [ nameForDiagnostics: "inherited type", isOptional: true ), + Child( + name: "equal", + kind: .token(choices: [.token(.equal)]), + isOptional: true + ), + Child( + name: "defaultType", + kind: .node(kind: .type), + nameForDiagnostics: "default type", + isOptional: true + ), Child( name: "trailingComma", kind: .token(choices: [.token(.comma)]), diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index 97e2c3e2c8b..4418b236db9 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -675,6 +675,34 @@ extension Parser { unexpectedBeforeInherited = nil inherited = nil } + + // Parse the '=' followed by a type. + let equal = self.consume(if: .equal) + let unexpectedBeforeDefault: RawUnexpectedNodesSyntax? + let defaultType: RawTypeSyntax? + if equal != nil { + if self.at(.identifier, .keyword(.protocol), .keyword(.Any)) || self.atContextualPunctuator("~") { + unexpectedBeforeDefault = nil + defaultType = self.parseType() + } else if let classKeyword = self.consume(if: .keyword(.class)) { + unexpectedBeforeDefault = RawUnexpectedNodesSyntax([classKeyword], arena: self.arena) + defaultType = RawTypeSyntax( + RawIdentifierTypeSyntax( + moduleSelector: nil, + name: missingToken(.identifier, text: "AnyObject"), + genericArgumentClause: nil, + arena: self.arena + ) + ) + } else { + unexpectedBeforeDefault = nil + defaultType = RawTypeSyntax(RawMissingTypeSyntax(arena: self.arena)) + } + } else { + unexpectedBeforeDefault = nil + defaultType = nil + } + keepGoing = self.consume(if: .comma) elements.append( RawGenericParameterSyntax( @@ -686,6 +714,9 @@ extension Parser { colon: colon, unexpectedBeforeInherited, inheritedType: inherited, + equal: equal, + unexpectedBeforeDefault, + defaultType: defaultType, trailingComma: keepGoing, arena: self.arena ) diff --git a/Sources/SwiftParserDiagnostics/generated/ChildNameForDiagnostics.swift b/Sources/SwiftParserDiagnostics/generated/ChildNameForDiagnostics.swift index f047dc2cc51..0d8ddfe59ed 100644 --- a/Sources/SwiftParserDiagnostics/generated/ChildNameForDiagnostics.swift +++ b/Sources/SwiftParserDiagnostics/generated/ChildNameForDiagnostics.swift @@ -175,6 +175,8 @@ private func childNameForDiagnostics(_ keyPath: AnyKeyPath) -> String? { return "name" case \GenericParameterSyntax.inheritedType: return "inherited type" + case \GenericParameterSyntax.defaultType: + return "default type" case \GuardStmtSyntax.conditions: return "condition" case \GuardStmtSyntax.body: diff --git a/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift b/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift index 7f199475e8b..64903ac2bb8 100644 --- a/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift +++ b/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift @@ -1596,8 +1596,16 @@ public func childName(_ keyPath: AnyKeyPath) -> String? { return "unexpectedBetweenColonAndInheritedType" case \GenericParameterSyntax.inheritedType: return "inheritedType" - case \GenericParameterSyntax.unexpectedBetweenInheritedTypeAndTrailingComma: - return "unexpectedBetweenInheritedTypeAndTrailingComma" + case \GenericParameterSyntax.unexpectedBetweenInheritedTypeAndEqual: + return "unexpectedBetweenInheritedTypeAndEqual" + case \GenericParameterSyntax.equal: + return "equal" + case \GenericParameterSyntax.unexpectedBetweenEqualAndDefaultType: + return "unexpectedBetweenEqualAndDefaultType" + case \GenericParameterSyntax.defaultType: + return "defaultType" + case \GenericParameterSyntax.unexpectedBetweenDefaultTypeAndTrailingComma: + return "unexpectedBetweenDefaultTypeAndTrailingComma" case \GenericParameterSyntax.trailingComma: return "trailingComma" case \GenericParameterSyntax.unexpectedAfterTrailingComma: diff --git a/Sources/SwiftSyntax/generated/RenamedChildrenCompatibility.swift b/Sources/SwiftSyntax/generated/RenamedChildrenCompatibility.swift index 1d82e4cbad3..dcb4c1e6de4 100644 --- a/Sources/SwiftSyntax/generated/RenamedChildrenCompatibility.swift +++ b/Sources/SwiftSyntax/generated/RenamedChildrenCompatibility.swift @@ -3678,7 +3678,7 @@ extension GenericParameterSyntax { } } - @available(*, deprecated, renamed: "init(leadingTrivia:_:attributes:_:specifier:_:name:_:colon:_:inheritedType:_:trailingComma:_:trailingTrivia:)") + @available(*, deprecated, renamed: "init(leadingTrivia:_:attributes:_:specifier:_:name:_:colon:_:inheritedType:_:equal:_:defaultType:_:trailingComma:_:trailingTrivia:)") @_disfavoredOverload public init( leadingTrivia: Trivia? = nil, @@ -3692,7 +3692,11 @@ extension GenericParameterSyntax { colon: TokenSyntax? = nil, _ unexpectedBetweenColonAndInheritedType: UnexpectedNodesSyntax? = nil, inheritedType: (some TypeSyntaxProtocol)? = TypeSyntax?.none, - _ unexpectedBetweenInheritedTypeAndTrailingComma: UnexpectedNodesSyntax? = nil, + _ unexpectedBetweenInheritedTypeAndEqual: UnexpectedNodesSyntax? = nil, + equal: TokenSyntax? = nil, + _ unexpectedBetweenEqualAndDefaultType: UnexpectedNodesSyntax? = nil, + defaultType: (some TypeSyntaxProtocol)? = TypeSyntax?.none, + _ unexpectedBetweenDefaultTypeAndTrailingComma: UnexpectedNodesSyntax? = nil, trailingComma: TokenSyntax? = nil, _ unexpectedAfterTrailingComma: UnexpectedNodesSyntax? = nil, trailingTrivia: Trivia? = nil @@ -3709,7 +3713,11 @@ extension GenericParameterSyntax { colon: colon, unexpectedBetweenColonAndInheritedType, inheritedType: inheritedType, - unexpectedBetweenInheritedTypeAndTrailingComma, + unexpectedBetweenInheritedTypeAndEqual, + equal: equal, + unexpectedBetweenEqualAndDefaultType, + defaultType: defaultType, + unexpectedBetweenDefaultTypeAndTrailingComma, trailingComma: trailingComma, unexpectedAfterTrailingComma, trailingTrivia: trailingTrivia diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesGHI.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesGHI.swift index 76ca3886071..00d2066409e 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesGHI.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesGHI.swift @@ -435,13 +435,17 @@ public struct RawGenericParameterSyntax: RawSyntaxNodeProtocol { colon: RawTokenSyntax?, _ unexpectedBetweenColonAndInheritedType: RawUnexpectedNodesSyntax? = nil, inheritedType: RawTypeSyntax?, - _ unexpectedBetweenInheritedTypeAndTrailingComma: RawUnexpectedNodesSyntax? = nil, + _ unexpectedBetweenInheritedTypeAndEqual: RawUnexpectedNodesSyntax? = nil, + equal: RawTokenSyntax?, + _ unexpectedBetweenEqualAndDefaultType: RawUnexpectedNodesSyntax? = nil, + defaultType: RawTypeSyntax?, + _ unexpectedBetweenDefaultTypeAndTrailingComma: RawUnexpectedNodesSyntax? = nil, trailingComma: RawTokenSyntax?, _ unexpectedAfterTrailingComma: RawUnexpectedNodesSyntax? = nil, arena: __shared RawSyntaxArena ) { let raw = RawSyntax.makeLayout( - kind: .genericParameter, uninitializedCount: 13, arena: arena) { layout in + kind: .genericParameter, uninitializedCount: 17, arena: arena) { layout in layout.initialize(repeating: nil) layout[0] = unexpectedBeforeAttributes?.raw layout[1] = attributes.raw @@ -453,9 +457,13 @@ public struct RawGenericParameterSyntax: RawSyntaxNodeProtocol { layout[7] = colon?.raw layout[8] = unexpectedBetweenColonAndInheritedType?.raw layout[9] = inheritedType?.raw - layout[10] = unexpectedBetweenInheritedTypeAndTrailingComma?.raw - layout[11] = trailingComma?.raw - layout[12] = unexpectedAfterTrailingComma?.raw + layout[10] = unexpectedBetweenInheritedTypeAndEqual?.raw + layout[11] = equal?.raw + layout[12] = unexpectedBetweenEqualAndDefaultType?.raw + layout[13] = defaultType?.raw + layout[14] = unexpectedBetweenDefaultTypeAndTrailingComma?.raw + layout[15] = trailingComma?.raw + layout[16] = unexpectedAfterTrailingComma?.raw } self.init(unchecked: raw) } @@ -500,17 +508,33 @@ public struct RawGenericParameterSyntax: RawSyntaxNodeProtocol { layoutView.children[9].map(RawTypeSyntax.init(raw:)) } - public var unexpectedBetweenInheritedTypeAndTrailingComma: RawUnexpectedNodesSyntax? { + public var unexpectedBetweenInheritedTypeAndEqual: RawUnexpectedNodesSyntax? { layoutView.children[10].map(RawUnexpectedNodesSyntax.init(raw:)) } - public var trailingComma: RawTokenSyntax? { + public var equal: RawTokenSyntax? { layoutView.children[11].map(RawTokenSyntax.init(raw:)) } - public var unexpectedAfterTrailingComma: RawUnexpectedNodesSyntax? { + public var unexpectedBetweenEqualAndDefaultType: RawUnexpectedNodesSyntax? { layoutView.children[12].map(RawUnexpectedNodesSyntax.init(raw:)) } + + public var defaultType: RawTypeSyntax? { + layoutView.children[13].map(RawTypeSyntax.init(raw:)) + } + + public var unexpectedBetweenDefaultTypeAndTrailingComma: RawUnexpectedNodesSyntax? { + layoutView.children[14].map(RawUnexpectedNodesSyntax.init(raw:)) + } + + public var trailingComma: RawTokenSyntax? { + layoutView.children[15].map(RawTokenSyntax.init(raw:)) + } + + public var unexpectedAfterTrailingComma: RawUnexpectedNodesSyntax? { + layoutView.children[16].map(RawUnexpectedNodesSyntax.init(raw:)) + } } @_spi(RawSyntax) diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift index a768f46192f..bdb059f5a33 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift @@ -1497,7 +1497,7 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { } } func validateGenericParameterSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { - assert(layout.count == 13) + assert(layout.count == 17) assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self)) assertNoError(kind, 1, verify(layout[1], as: RawAttributeListSyntax.self)) assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) @@ -1509,8 +1509,12 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { assertNoError(kind, 8, verify(layout[8], as: RawUnexpectedNodesSyntax?.self)) assertNoError(kind, 9, verify(layout[9], as: RawTypeSyntax?.self)) assertNoError(kind, 10, verify(layout[10], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 11, verify(layout[11], as: RawTokenSyntax?.self, tokenChoices: [.tokenKind(.comma)])) + assertNoError(kind, 11, verify(layout[11], as: RawTokenSyntax?.self, tokenChoices: [.tokenKind(.equal)])) assertNoError(kind, 12, verify(layout[12], as: RawUnexpectedNodesSyntax?.self)) + assertNoError(kind, 13, verify(layout[13], as: RawTypeSyntax?.self)) + assertNoError(kind, 14, verify(layout[14], as: RawUnexpectedNodesSyntax?.self)) + assertNoError(kind, 15, verify(layout[15], as: RawTokenSyntax?.self, tokenChoices: [.tokenKind(.comma)])) + assertNoError(kind, 16, verify(layout[16], as: RawUnexpectedNodesSyntax?.self)) } func validateGenericRequirementListSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { for (index, element) in layout.enumerated() { diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift index 3806f606106..b093211bb98 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift @@ -636,6 +636,8 @@ public struct GenericParameterClauseSyntax: SyntaxProtocol, SyntaxHashable, _Lea /// - `name`: `` /// - `colon`: `:`? /// - `inheritedType`: ``TypeSyntax``? +/// - `equal`: `=`? +/// - `defaultType`: ``TypeSyntax``? /// - `trailingComma`: `,`? /// /// ### Contained in @@ -671,7 +673,11 @@ public struct GenericParameterSyntax: SyntaxProtocol, SyntaxHashable, _LeafSynta colon: TokenSyntax? = nil, _ unexpectedBetweenColonAndInheritedType: UnexpectedNodesSyntax? = nil, inheritedType: (some TypeSyntaxProtocol)? = TypeSyntax?.none, - _ unexpectedBetweenInheritedTypeAndTrailingComma: UnexpectedNodesSyntax? = nil, + _ unexpectedBetweenInheritedTypeAndEqual: UnexpectedNodesSyntax? = nil, + equal: TokenSyntax? = nil, + _ unexpectedBetweenEqualAndDefaultType: UnexpectedNodesSyntax? = nil, + defaultType: (some TypeSyntaxProtocol)? = TypeSyntax?.none, + _ unexpectedBetweenDefaultTypeAndTrailingComma: UnexpectedNodesSyntax? = nil, trailingComma: TokenSyntax? = nil, _ unexpectedAfterTrailingComma: UnexpectedNodesSyntax? = nil, trailingTrivia: Trivia? = nil @@ -689,7 +695,11 @@ public struct GenericParameterSyntax: SyntaxProtocol, SyntaxHashable, _LeafSynta colon, unexpectedBetweenColonAndInheritedType, inheritedType, - unexpectedBetweenInheritedTypeAndTrailingComma, + unexpectedBetweenInheritedTypeAndEqual, + equal, + unexpectedBetweenEqualAndDefaultType, + defaultType, + unexpectedBetweenDefaultTypeAndTrailingComma, trailingComma, unexpectedAfterTrailingComma ))) { (arena, _) in @@ -704,7 +714,11 @@ public struct GenericParameterSyntax: SyntaxProtocol, SyntaxHashable, _LeafSynta colon?.raw, unexpectedBetweenColonAndInheritedType?.raw, inheritedType?.raw, - unexpectedBetweenInheritedTypeAndTrailingComma?.raw, + unexpectedBetweenInheritedTypeAndEqual?.raw, + equal?.raw, + unexpectedBetweenEqualAndDefaultType?.raw, + defaultType?.raw, + unexpectedBetweenDefaultTypeAndTrailingComma?.raw, trailingComma?.raw, unexpectedAfterTrailingComma?.raw ] @@ -847,7 +861,7 @@ public struct GenericParameterSyntax: SyntaxProtocol, SyntaxHashable, _LeafSynta } } - public var unexpectedBetweenInheritedTypeAndTrailingComma: UnexpectedNodesSyntax? { + public var unexpectedBetweenInheritedTypeAndEqual: UnexpectedNodesSyntax? { get { return Syntax(self).child(at: 10)?.cast(UnexpectedNodesSyntax.self) } @@ -858,8 +872,8 @@ public struct GenericParameterSyntax: SyntaxProtocol, SyntaxHashable, _LeafSynta /// ### Tokens /// - /// For syntax trees generated by the parser, this is guaranteed to be `,`. - public var trailingComma: TokenSyntax? { + /// For syntax trees generated by the parser, this is guaranteed to be `=`. + public var equal: TokenSyntax? { get { return Syntax(self).child(at: 11)?.cast(TokenSyntax.self) } @@ -868,7 +882,7 @@ public struct GenericParameterSyntax: SyntaxProtocol, SyntaxHashable, _LeafSynta } } - public var unexpectedAfterTrailingComma: UnexpectedNodesSyntax? { + public var unexpectedBetweenEqualAndDefaultType: UnexpectedNodesSyntax? { get { return Syntax(self).child(at: 12)?.cast(UnexpectedNodesSyntax.self) } @@ -877,6 +891,45 @@ public struct GenericParameterSyntax: SyntaxProtocol, SyntaxHashable, _LeafSynta } } + public var defaultType: TypeSyntax? { + get { + return Syntax(self).child(at: 13)?.cast(TypeSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 13, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(GenericParameterSyntax.self) + } + } + + public var unexpectedBetweenDefaultTypeAndTrailingComma: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 14)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 14, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(GenericParameterSyntax.self) + } + } + + /// ### Tokens + /// + /// For syntax trees generated by the parser, this is guaranteed to be `,`. + public var trailingComma: TokenSyntax? { + get { + return Syntax(self).child(at: 15)?.cast(TokenSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 15, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(GenericParameterSyntax.self) + } + } + + public var unexpectedAfterTrailingComma: UnexpectedNodesSyntax? { + get { + return Syntax(self).child(at: 16)?.cast(UnexpectedNodesSyntax.self) + } + set(value) { + self = Syntax(self).replacingChild(at: 16, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(GenericParameterSyntax.self) + } + } + public static let structure: SyntaxNodeStructure = .layout([ \Self.unexpectedBeforeAttributes, \Self.attributes, @@ -888,7 +941,11 @@ public struct GenericParameterSyntax: SyntaxProtocol, SyntaxHashable, _LeafSynta \Self.colon, \Self.unexpectedBetweenColonAndInheritedType, \Self.inheritedType, - \Self.unexpectedBetweenInheritedTypeAndTrailingComma, + \Self.unexpectedBetweenInheritedTypeAndEqual, + \Self.equal, + \Self.unexpectedBetweenEqualAndDefaultType, + \Self.defaultType, + \Self.unexpectedBetweenDefaultTypeAndTrailingComma, \Self.trailingComma, \Self.unexpectedAfterTrailingComma ]) From 244fcd74ff807b74432fa4cdca7558322f2fd76e Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Fri, 19 Sep 2025 11:34:08 -0700 Subject: [PATCH 2/3] Add behind experimental feature flag --- .../SyntaxSupport/ExperimentalFeatures.swift | 5 + .../Sources/SyntaxSupport/GenericNodes.swift | 12 +- Sources/SwiftParser/Declarations.swift | 39 +++---- .../generated/ExperimentalFeatures.swift | 5 + .../generated/ChildNameForDiagnostics.swift | 2 +- .../generated/ChildNameForKeyPath.swift | 16 +-- .../RenamedChildrenCompatibility.swift | 63 ++++++++-- .../generated/raw/RawSyntaxNodesGHI.swift | 42 +++---- .../generated/raw/RawSyntaxValidation.swift | 8 +- .../syntaxNodes/SyntaxNodesGHI.swift | 77 ++++--------- .../syntaxNodes/SyntaxNodesTUVWXYZ.swift | 1 + .../SwiftParserTest/DefaultGenericsTest.swift | 109 ++++++++++++++++++ 12 files changed, 239 insertions(+), 140 deletions(-) create mode 100644 Tests/SwiftParserTest/DefaultGenericsTest.swift diff --git a/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift b/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift index f14f1de8e9d..b3d6e6dfa1e 100644 --- a/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift +++ b/CodeGeneration/Sources/SyntaxSupport/ExperimentalFeatures.swift @@ -23,6 +23,7 @@ public enum ExperimentalFeature: String, CaseIterable { case oldOwnershipOperatorSpellings case defaultIsolationPerFile case moduleSelector + case defaultGenerics /// The name of the feature as it is written in the compiler's `Features.def` file. public var featureName: String { @@ -47,6 +48,8 @@ public enum ExperimentalFeature: String, CaseIterable { return "DefaultIsolationPerFile" case .moduleSelector: return "ModuleSelector" + case .defaultGenerics: + return "DefaultGenerics" } } @@ -73,6 +76,8 @@ public enum ExperimentalFeature: String, CaseIterable { return "set default actor isolation for a file" case .moduleSelector: return "Module selector syntax (`ModName::identifier`)" + case .defaultGenerics: + return "default generics" } } diff --git a/CodeGeneration/Sources/SyntaxSupport/GenericNodes.swift b/CodeGeneration/Sources/SyntaxSupport/GenericNodes.swift index 61ea38f5293..668443d6f1b 100644 --- a/CodeGeneration/Sources/SyntaxSupport/GenericNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/GenericNodes.swift @@ -126,15 +126,11 @@ public let GENERIC_NODES: [Node] = [ isOptional: true ), Child( - name: "equal", - kind: .token(choices: [.token(.equal)]), - isOptional: true - ), - Child( - name: "defaultType", - kind: .node(kind: .type), + name: "initializer", + kind: .node(kind: .typeInitializerClause), + experimentalFeature: .defaultGenerics, nameForDiagnostics: "default type", - isOptional: true + isOptional: true, ), Child( name: "trailingComma", diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index 4418b236db9..399f60a6d64 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -676,30 +676,19 @@ extension Parser { inherited = nil } - // Parse the '=' followed by a type. - let equal = self.consume(if: .equal) - let unexpectedBeforeDefault: RawUnexpectedNodesSyntax? - let defaultType: RawTypeSyntax? - if equal != nil { - if self.at(.identifier, .keyword(.protocol), .keyword(.Any)) || self.atContextualPunctuator("~") { - unexpectedBeforeDefault = nil - defaultType = self.parseType() - } else if let classKeyword = self.consume(if: .keyword(.class)) { - unexpectedBeforeDefault = RawUnexpectedNodesSyntax([classKeyword], arena: self.arena) - defaultType = RawTypeSyntax( - RawIdentifierTypeSyntax( - moduleSelector: nil, - name: missingToken(.identifier, text: "AnyObject"), - genericArgumentClause: nil, - arena: self.arena - ) - ) - } else { - unexpectedBeforeDefault = nil - defaultType = RawTypeSyntax(RawMissingTypeSyntax(arena: self.arena)) - } + // Parse the default type, if any. We only have defaults of regular + // type parameters, not parameter packs or value generics yet. + let defaultType: RawTypeInitializerClauseSyntax? + if self.experimentalFeatures.contains(.defaultGenerics), + specifier == nil, + let equal = self.consume(if: .equal) { + let type = self.parseType() + defaultType = RawTypeInitializerClauseSyntax( + equal: equal, + value: type, + arena: self.arena + ) } else { - unexpectedBeforeDefault = nil defaultType = nil } @@ -714,9 +703,7 @@ extension Parser { colon: colon, unexpectedBeforeInherited, inheritedType: inherited, - equal: equal, - unexpectedBeforeDefault, - defaultType: defaultType, + initializer: defaultType, trailingComma: keepGoing, arena: self.arena ) diff --git a/Sources/SwiftParser/generated/ExperimentalFeatures.swift b/Sources/SwiftParser/generated/ExperimentalFeatures.swift index 1c12c14a148..29bc7437c89 100644 --- a/Sources/SwiftParser/generated/ExperimentalFeatures.swift +++ b/Sources/SwiftParser/generated/ExperimentalFeatures.swift @@ -55,6 +55,9 @@ extension Parser.ExperimentalFeatures { /// Whether to enable the parsing of Module selector syntax (`ModName::identifier`). public static let moduleSelector = Self (rawValue: 1 << 9) + /// Whether to enable the parsing of default generics. + public static let defaultGenerics = Self (rawValue: 1 << 10) + /// Creates a new value representing the experimental feature with the /// given name, or returns nil if the name is not recognized. public init?(name: String) { @@ -79,6 +82,8 @@ extension Parser.ExperimentalFeatures { self = .defaultIsolationPerFile case "ModuleSelector": self = .moduleSelector + case "DefaultGenerics": + self = .defaultGenerics default: return nil } diff --git a/Sources/SwiftParserDiagnostics/generated/ChildNameForDiagnostics.swift b/Sources/SwiftParserDiagnostics/generated/ChildNameForDiagnostics.swift index 0d8ddfe59ed..1294c5ee333 100644 --- a/Sources/SwiftParserDiagnostics/generated/ChildNameForDiagnostics.swift +++ b/Sources/SwiftParserDiagnostics/generated/ChildNameForDiagnostics.swift @@ -175,7 +175,7 @@ private func childNameForDiagnostics(_ keyPath: AnyKeyPath) -> String? { return "name" case \GenericParameterSyntax.inheritedType: return "inherited type" - case \GenericParameterSyntax.defaultType: + case \GenericParameterSyntax.initializer: return "default type" case \GuardStmtSyntax.conditions: return "condition" diff --git a/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift b/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift index 64903ac2bb8..7c7ea60224e 100644 --- a/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift +++ b/Sources/SwiftSyntax/generated/ChildNameForKeyPath.swift @@ -1596,16 +1596,12 @@ public func childName(_ keyPath: AnyKeyPath) -> String? { return "unexpectedBetweenColonAndInheritedType" case \GenericParameterSyntax.inheritedType: return "inheritedType" - case \GenericParameterSyntax.unexpectedBetweenInheritedTypeAndEqual: - return "unexpectedBetweenInheritedTypeAndEqual" - case \GenericParameterSyntax.equal: - return "equal" - case \GenericParameterSyntax.unexpectedBetweenEqualAndDefaultType: - return "unexpectedBetweenEqualAndDefaultType" - case \GenericParameterSyntax.defaultType: - return "defaultType" - case \GenericParameterSyntax.unexpectedBetweenDefaultTypeAndTrailingComma: - return "unexpectedBetweenDefaultTypeAndTrailingComma" + case \GenericParameterSyntax.unexpectedBetweenInheritedTypeAndInitializer: + return "unexpectedBetweenInheritedTypeAndInitializer" + case \GenericParameterSyntax.initializer: + return "initializer" + case \GenericParameterSyntax.unexpectedBetweenInitializerAndTrailingComma: + return "unexpectedBetweenInitializerAndTrailingComma" case \GenericParameterSyntax.trailingComma: return "trailingComma" case \GenericParameterSyntax.unexpectedAfterTrailingComma: diff --git a/Sources/SwiftSyntax/generated/RenamedChildrenCompatibility.swift b/Sources/SwiftSyntax/generated/RenamedChildrenCompatibility.swift index dcb4c1e6de4..acb8298040d 100644 --- a/Sources/SwiftSyntax/generated/RenamedChildrenCompatibility.swift +++ b/Sources/SwiftSyntax/generated/RenamedChildrenCompatibility.swift @@ -3648,6 +3648,15 @@ extension GenericParameterClauseSyntax { } extension GenericParameterSyntax { + public var unexpectedBetweenInheritedTypeAndTrailingComma: UnexpectedNodesSyntax? { + get { + return unexpectedBetweenInheritedTypeAndInitializer + } + set { + unexpectedBetweenInheritedTypeAndInitializer = newValue + } + } + @available(*, deprecated, renamed: "unexpectedBetweenAttributesAndSpecifier") public var unexpectedBetweenAttributesAndEachKeyword: UnexpectedNodesSyntax? { get { @@ -3678,7 +3687,45 @@ extension GenericParameterSyntax { } } - @available(*, deprecated, renamed: "init(leadingTrivia:_:attributes:_:specifier:_:name:_:colon:_:inheritedType:_:equal:_:defaultType:_:trailingComma:_:trailingTrivia:)") + public init( + leadingTrivia: Trivia? = nil, + _ unexpectedBeforeAttributes: UnexpectedNodesSyntax? = nil, + attributes: AttributeListSyntax = [], + _ unexpectedBetweenAttributesAndSpecifier: UnexpectedNodesSyntax? = nil, + specifier: TokenSyntax? = nil, + _ unexpectedBetweenSpecifierAndName: UnexpectedNodesSyntax? = nil, + name: TokenSyntax, + _ unexpectedBetweenNameAndColon: UnexpectedNodesSyntax? = nil, + colon: TokenSyntax? = nil, + _ unexpectedBetweenColonAndInheritedType: UnexpectedNodesSyntax? = nil, + inheritedType: (some TypeSyntaxProtocol)? = TypeSyntax?.none, + _ unexpectedBetweenInheritedTypeAndTrailingComma: UnexpectedNodesSyntax? = nil, + trailingComma: TokenSyntax? = nil, + _ unexpectedAfterTrailingComma: UnexpectedNodesSyntax? = nil, + trailingTrivia: Trivia? = nil + ) { + self.init( + leadingTrivia: leadingTrivia, + unexpectedBeforeAttributes, + attributes: attributes, + unexpectedBetweenAttributesAndSpecifier, + specifier: specifier, + unexpectedBetweenSpecifierAndName, + name: name, + unexpectedBetweenNameAndColon, + colon: colon, + unexpectedBetweenColonAndInheritedType, + inheritedType: inheritedType, + unexpectedBetweenInheritedTypeAndTrailingComma, + initializer: nil, + nil, + trailingComma: trailingComma, + unexpectedAfterTrailingComma, + trailingTrivia: trailingTrivia + ) + } + + @available(*, deprecated, renamed: "init(leadingTrivia:_:attributes:_:specifier:_:name:_:colon:_:inheritedType:_:initializer:_:trailingComma:_:trailingTrivia:)") @_disfavoredOverload public init( leadingTrivia: Trivia? = nil, @@ -3692,11 +3739,7 @@ extension GenericParameterSyntax { colon: TokenSyntax? = nil, _ unexpectedBetweenColonAndInheritedType: UnexpectedNodesSyntax? = nil, inheritedType: (some TypeSyntaxProtocol)? = TypeSyntax?.none, - _ unexpectedBetweenInheritedTypeAndEqual: UnexpectedNodesSyntax? = nil, - equal: TokenSyntax? = nil, - _ unexpectedBetweenEqualAndDefaultType: UnexpectedNodesSyntax? = nil, - defaultType: (some TypeSyntaxProtocol)? = TypeSyntax?.none, - _ unexpectedBetweenDefaultTypeAndTrailingComma: UnexpectedNodesSyntax? = nil, + _ unexpectedBetweenInheritedTypeAndTrailingComma: UnexpectedNodesSyntax? = nil, trailingComma: TokenSyntax? = nil, _ unexpectedAfterTrailingComma: UnexpectedNodesSyntax? = nil, trailingTrivia: Trivia? = nil @@ -3713,11 +3756,9 @@ extension GenericParameterSyntax { colon: colon, unexpectedBetweenColonAndInheritedType, inheritedType: inheritedType, - unexpectedBetweenInheritedTypeAndEqual, - equal: equal, - unexpectedBetweenEqualAndDefaultType, - defaultType: defaultType, - unexpectedBetweenDefaultTypeAndTrailingComma, + unexpectedBetweenInheritedTypeAndTrailingComma, + initializer: nil, + nil, trailingComma: trailingComma, unexpectedAfterTrailingComma, trailingTrivia: trailingTrivia diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesGHI.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesGHI.swift index 00d2066409e..d8c434ff576 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesGHI.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxNodesGHI.swift @@ -435,17 +435,15 @@ public struct RawGenericParameterSyntax: RawSyntaxNodeProtocol { colon: RawTokenSyntax?, _ unexpectedBetweenColonAndInheritedType: RawUnexpectedNodesSyntax? = nil, inheritedType: RawTypeSyntax?, - _ unexpectedBetweenInheritedTypeAndEqual: RawUnexpectedNodesSyntax? = nil, - equal: RawTokenSyntax?, - _ unexpectedBetweenEqualAndDefaultType: RawUnexpectedNodesSyntax? = nil, - defaultType: RawTypeSyntax?, - _ unexpectedBetweenDefaultTypeAndTrailingComma: RawUnexpectedNodesSyntax? = nil, + _ unexpectedBetweenInheritedTypeAndInitializer: RawUnexpectedNodesSyntax? = nil, + initializer: RawTypeInitializerClauseSyntax?, + _ unexpectedBetweenInitializerAndTrailingComma: RawUnexpectedNodesSyntax? = nil, trailingComma: RawTokenSyntax?, _ unexpectedAfterTrailingComma: RawUnexpectedNodesSyntax? = nil, arena: __shared RawSyntaxArena ) { let raw = RawSyntax.makeLayout( - kind: .genericParameter, uninitializedCount: 17, arena: arena) { layout in + kind: .genericParameter, uninitializedCount: 15, arena: arena) { layout in layout.initialize(repeating: nil) layout[0] = unexpectedBeforeAttributes?.raw layout[1] = attributes.raw @@ -457,13 +455,11 @@ public struct RawGenericParameterSyntax: RawSyntaxNodeProtocol { layout[7] = colon?.raw layout[8] = unexpectedBetweenColonAndInheritedType?.raw layout[9] = inheritedType?.raw - layout[10] = unexpectedBetweenInheritedTypeAndEqual?.raw - layout[11] = equal?.raw - layout[12] = unexpectedBetweenEqualAndDefaultType?.raw - layout[13] = defaultType?.raw - layout[14] = unexpectedBetweenDefaultTypeAndTrailingComma?.raw - layout[15] = trailingComma?.raw - layout[16] = unexpectedAfterTrailingComma?.raw + layout[10] = unexpectedBetweenInheritedTypeAndInitializer?.raw + layout[11] = initializer?.raw + layout[12] = unexpectedBetweenInitializerAndTrailingComma?.raw + layout[13] = trailingComma?.raw + layout[14] = unexpectedAfterTrailingComma?.raw } self.init(unchecked: raw) } @@ -508,32 +504,24 @@ public struct RawGenericParameterSyntax: RawSyntaxNodeProtocol { layoutView.children[9].map(RawTypeSyntax.init(raw:)) } - public var unexpectedBetweenInheritedTypeAndEqual: RawUnexpectedNodesSyntax? { + public var unexpectedBetweenInheritedTypeAndInitializer: RawUnexpectedNodesSyntax? { layoutView.children[10].map(RawUnexpectedNodesSyntax.init(raw:)) } - public var equal: RawTokenSyntax? { - layoutView.children[11].map(RawTokenSyntax.init(raw:)) + public var initializer: RawTypeInitializerClauseSyntax? { + layoutView.children[11].map(RawTypeInitializerClauseSyntax.init(raw:)) } - public var unexpectedBetweenEqualAndDefaultType: RawUnexpectedNodesSyntax? { + public var unexpectedBetweenInitializerAndTrailingComma: RawUnexpectedNodesSyntax? { layoutView.children[12].map(RawUnexpectedNodesSyntax.init(raw:)) } - public var defaultType: RawTypeSyntax? { - layoutView.children[13].map(RawTypeSyntax.init(raw:)) - } - - public var unexpectedBetweenDefaultTypeAndTrailingComma: RawUnexpectedNodesSyntax? { - layoutView.children[14].map(RawUnexpectedNodesSyntax.init(raw:)) - } - public var trailingComma: RawTokenSyntax? { - layoutView.children[15].map(RawTokenSyntax.init(raw:)) + layoutView.children[13].map(RawTokenSyntax.init(raw:)) } public var unexpectedAfterTrailingComma: RawUnexpectedNodesSyntax? { - layoutView.children[16].map(RawUnexpectedNodesSyntax.init(raw:)) + layoutView.children[14].map(RawUnexpectedNodesSyntax.init(raw:)) } } diff --git a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift index bdb059f5a33..5127fb91e7c 100644 --- a/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift +++ b/Sources/SwiftSyntax/generated/raw/RawSyntaxValidation.swift @@ -1497,7 +1497,7 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { } } func validateGenericParameterSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { - assert(layout.count == 17) + assert(layout.count == 15) assertNoError(kind, 0, verify(layout[0], as: RawUnexpectedNodesSyntax?.self)) assertNoError(kind, 1, verify(layout[1], as: RawAttributeListSyntax.self)) assertNoError(kind, 2, verify(layout[2], as: RawUnexpectedNodesSyntax?.self)) @@ -1509,12 +1509,10 @@ func validateLayout(layout: RawSyntaxBuffer, as kind: SyntaxKind) { assertNoError(kind, 8, verify(layout[8], as: RawUnexpectedNodesSyntax?.self)) assertNoError(kind, 9, verify(layout[9], as: RawTypeSyntax?.self)) assertNoError(kind, 10, verify(layout[10], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 11, verify(layout[11], as: RawTokenSyntax?.self, tokenChoices: [.tokenKind(.equal)])) + assertNoError(kind, 11, verify(layout[11], as: RawTypeInitializerClauseSyntax?.self)) assertNoError(kind, 12, verify(layout[12], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 13, verify(layout[13], as: RawTypeSyntax?.self)) + assertNoError(kind, 13, verify(layout[13], as: RawTokenSyntax?.self, tokenChoices: [.tokenKind(.comma)])) assertNoError(kind, 14, verify(layout[14], as: RawUnexpectedNodesSyntax?.self)) - assertNoError(kind, 15, verify(layout[15], as: RawTokenSyntax?.self, tokenChoices: [.tokenKind(.comma)])) - assertNoError(kind, 16, verify(layout[16], as: RawUnexpectedNodesSyntax?.self)) } func validateGenericRequirementListSyntax(kind: SyntaxKind, layout: RawSyntaxBuffer) { for (index, element) in layout.enumerated() { diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift index b093211bb98..4883047e547 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesGHI.swift @@ -636,8 +636,7 @@ public struct GenericParameterClauseSyntax: SyntaxProtocol, SyntaxHashable, _Lea /// - `name`: `` /// - `colon`: `:`? /// - `inheritedType`: ``TypeSyntax``? -/// - `equal`: `=`? -/// - `defaultType`: ``TypeSyntax``? +/// - `initializer`: ``TypeInitializerClauseSyntax``? /// - `trailingComma`: `,`? /// /// ### Contained in @@ -661,7 +660,7 @@ public struct GenericParameterSyntax: SyntaxProtocol, SyntaxHashable, _LeafSynta /// - Parameters: /// - leadingTrivia: Trivia to be prepended to the leading trivia of the node’s first token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. /// - trailingTrivia: Trivia to be appended to the trailing trivia of the node’s last token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. - public init( + @_spi(ExperimentalLanguageFeatures) public init( leadingTrivia: Trivia? = nil, _ unexpectedBeforeAttributes: UnexpectedNodesSyntax? = nil, attributes: AttributeListSyntax = [], @@ -673,11 +672,9 @@ public struct GenericParameterSyntax: SyntaxProtocol, SyntaxHashable, _LeafSynta colon: TokenSyntax? = nil, _ unexpectedBetweenColonAndInheritedType: UnexpectedNodesSyntax? = nil, inheritedType: (some TypeSyntaxProtocol)? = TypeSyntax?.none, - _ unexpectedBetweenInheritedTypeAndEqual: UnexpectedNodesSyntax? = nil, - equal: TokenSyntax? = nil, - _ unexpectedBetweenEqualAndDefaultType: UnexpectedNodesSyntax? = nil, - defaultType: (some TypeSyntaxProtocol)? = TypeSyntax?.none, - _ unexpectedBetweenDefaultTypeAndTrailingComma: UnexpectedNodesSyntax? = nil, + _ unexpectedBetweenInheritedTypeAndInitializer: UnexpectedNodesSyntax? = nil, + initializer: TypeInitializerClauseSyntax? = nil, + _ unexpectedBetweenInitializerAndTrailingComma: UnexpectedNodesSyntax? = nil, trailingComma: TokenSyntax? = nil, _ unexpectedAfterTrailingComma: UnexpectedNodesSyntax? = nil, trailingTrivia: Trivia? = nil @@ -695,11 +692,9 @@ public struct GenericParameterSyntax: SyntaxProtocol, SyntaxHashable, _LeafSynta colon, unexpectedBetweenColonAndInheritedType, inheritedType, - unexpectedBetweenInheritedTypeAndEqual, - equal, - unexpectedBetweenEqualAndDefaultType, - defaultType, - unexpectedBetweenDefaultTypeAndTrailingComma, + unexpectedBetweenInheritedTypeAndInitializer, + initializer, + unexpectedBetweenInitializerAndTrailingComma, trailingComma, unexpectedAfterTrailingComma ))) { (arena, _) in @@ -714,11 +709,9 @@ public struct GenericParameterSyntax: SyntaxProtocol, SyntaxHashable, _LeafSynta colon?.raw, unexpectedBetweenColonAndInheritedType?.raw, inheritedType?.raw, - unexpectedBetweenInheritedTypeAndEqual?.raw, - equal?.raw, - unexpectedBetweenEqualAndDefaultType?.raw, - defaultType?.raw, - unexpectedBetweenDefaultTypeAndTrailingComma?.raw, + unexpectedBetweenInheritedTypeAndInitializer?.raw, + initializer?.raw, + unexpectedBetweenInitializerAndTrailingComma?.raw, trailingComma?.raw, unexpectedAfterTrailingComma?.raw ] @@ -861,7 +854,8 @@ public struct GenericParameterSyntax: SyntaxProtocol, SyntaxHashable, _LeafSynta } } - public var unexpectedBetweenInheritedTypeAndEqual: UnexpectedNodesSyntax? { + @_spi(ExperimentalLanguageFeatures) + public var unexpectedBetweenInheritedTypeAndInitializer: UnexpectedNodesSyntax? { get { return Syntax(self).child(at: 10)?.cast(UnexpectedNodesSyntax.self) } @@ -870,19 +864,18 @@ public struct GenericParameterSyntax: SyntaxProtocol, SyntaxHashable, _LeafSynta } } - /// ### Tokens - /// - /// For syntax trees generated by the parser, this is guaranteed to be `=`. - public var equal: TokenSyntax? { + @_spi(ExperimentalLanguageFeatures) + public var initializer: TypeInitializerClauseSyntax? { get { - return Syntax(self).child(at: 11)?.cast(TokenSyntax.self) + return Syntax(self).child(at: 11)?.cast(TypeInitializerClauseSyntax.self) } set(value) { self = Syntax(self).replacingChild(at: 11, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(GenericParameterSyntax.self) } } - public var unexpectedBetweenEqualAndDefaultType: UnexpectedNodesSyntax? { + @_spi(ExperimentalLanguageFeatures) + public var unexpectedBetweenInitializerAndTrailingComma: UnexpectedNodesSyntax? { get { return Syntax(self).child(at: 12)?.cast(UnexpectedNodesSyntax.self) } @@ -891,42 +884,24 @@ public struct GenericParameterSyntax: SyntaxProtocol, SyntaxHashable, _LeafSynta } } - public var defaultType: TypeSyntax? { - get { - return Syntax(self).child(at: 13)?.cast(TypeSyntax.self) - } - set(value) { - self = Syntax(self).replacingChild(at: 13, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(GenericParameterSyntax.self) - } - } - - public var unexpectedBetweenDefaultTypeAndTrailingComma: UnexpectedNodesSyntax? { - get { - return Syntax(self).child(at: 14)?.cast(UnexpectedNodesSyntax.self) - } - set(value) { - self = Syntax(self).replacingChild(at: 14, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(GenericParameterSyntax.self) - } - } - /// ### Tokens /// /// For syntax trees generated by the parser, this is guaranteed to be `,`. public var trailingComma: TokenSyntax? { get { - return Syntax(self).child(at: 15)?.cast(TokenSyntax.self) + return Syntax(self).child(at: 13)?.cast(TokenSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 15, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(GenericParameterSyntax.self) + self = Syntax(self).replacingChild(at: 13, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(GenericParameterSyntax.self) } } public var unexpectedAfterTrailingComma: UnexpectedNodesSyntax? { get { - return Syntax(self).child(at: 16)?.cast(UnexpectedNodesSyntax.self) + return Syntax(self).child(at: 14)?.cast(UnexpectedNodesSyntax.self) } set(value) { - self = Syntax(self).replacingChild(at: 16, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(GenericParameterSyntax.self) + self = Syntax(self).replacingChild(at: 14, with: Syntax(value), rawAllocationArena: RawSyntaxArena()).cast(GenericParameterSyntax.self) } } @@ -941,11 +916,9 @@ public struct GenericParameterSyntax: SyntaxProtocol, SyntaxHashable, _LeafSynta \Self.colon, \Self.unexpectedBetweenColonAndInheritedType, \Self.inheritedType, - \Self.unexpectedBetweenInheritedTypeAndEqual, - \Self.equal, - \Self.unexpectedBetweenEqualAndDefaultType, - \Self.defaultType, - \Self.unexpectedBetweenDefaultTypeAndTrailingComma, + \Self.unexpectedBetweenInheritedTypeAndInitializer, + \Self.initializer, + \Self.unexpectedBetweenInitializerAndTrailingComma, \Self.trailingComma, \Self.unexpectedAfterTrailingComma ]) diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesTUVWXYZ.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesTUVWXYZ.swift index bf5973151ba..7003ec9e62b 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesTUVWXYZ.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesTUVWXYZ.swift @@ -2494,6 +2494,7 @@ public struct TypeExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _LeafExprSynta /// ### Contained in /// /// - ``AssociatedTypeDeclSyntax``.``AssociatedTypeDeclSyntax/initializer`` +/// - ``GenericParameterSyntax``.``GenericParameterSyntax/initializer`` /// - ``TypeAliasDeclSyntax``.``TypeAliasDeclSyntax/initializer`` public struct TypeInitializerClauseSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodeProtocol { public let _syntaxNode: Syntax diff --git a/Tests/SwiftParserTest/DefaultGenericsTest.swift b/Tests/SwiftParserTest/DefaultGenericsTest.swift new file mode 100644 index 00000000000..24a06abb70a --- /dev/null +++ b/Tests/SwiftParserTest/DefaultGenericsTest.swift @@ -0,0 +1,109 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2025 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +@_spi(ExperimentalLanguageFeatures) import SwiftParser +import SwiftSyntax +import XCTest + +final class DefaultGenericsTest: ParserTestCase { + func testBasic() { + assertParse( + """ + struct A {} + """, + experimentalFeatures: [.defaultGenerics] + ) + + assertParse( + """ + enum A {} + """, + experimentalFeatures: [.defaultGenerics] + ) + + assertParse( + """ + class A {} + """, + experimentalFeatures: [.defaultGenerics] + ) + + // Note: We don't allow default generics on things other than types, but + // we'll diagnose it during sema. + assertParse( + """ + func foo() {} + """, + experimentalFeatures: [.defaultGenerics] + ) + + assertParse( + """ + struct A {} + """, + diagnostics: [ + DiagnosticSpec( + message: "expected type in generic parameter", + fixIts: ["insert type"] + ) + ], + fixedSource: """ + struct A> {} + """, + experimentalFeatures: [.defaultGenerics] + ) + + assertParse( + """ + struct Aℹ️ {} + """, + diagnostics: [ + DiagnosticSpec( + message: "expected '>' to end generic parameter clause", + notes: [ + NoteSpec(message: "to match this opening '<'") + ], + fixIts: ["insert '>'"] + ), + DiagnosticSpec( + message: "unexpected code '= Int>' in struct" + ) + ], + fixedSource: """ + struct A = Int> {} + """, + experimentalFeatures: [.defaultGenerics] + ) + + assertParse( + """ + struct Aℹ️ {} + """, + diagnostics: [ + DiagnosticSpec( + message: "expected '>' to end generic parameter clause", + notes: [ + NoteSpec(message: "to match this opening '<'") + ], + fixIts: ["insert '>'"] + ), + DiagnosticSpec( + message: "unexpected code '= Int>' in struct" + ) + ], + fixedSource: """ + struct A = Int> {} + """, + experimentalFeatures: [.defaultGenerics] + ) + } +} From efa33acc8605f5e1d84f3f187687a3c50c7976d4 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Fri, 19 Sep 2025 11:51:51 -0700 Subject: [PATCH 3/3] Add release notes and format --- Release Notes/603.md | 24 +++++++++++++++++++ Sources/SwiftParser/Declarations.swift | 5 ++-- .../SwiftParserTest/DefaultGenericsTest.swift | 4 ++-- 3 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 Release Notes/603.md diff --git a/Release Notes/603.md b/Release Notes/603.md new file mode 100644 index 00000000000..fa61b3f938e --- /dev/null +++ b/Release Notes/603.md @@ -0,0 +1,24 @@ +# Swift Syntax 603 Release Notes + +## New APIs + +- `GenericParameterSyntax` now has a new `initializer` property. + - Description: Generic parameters can now optionally be passed a default type. The `initializer` is a `TypeInitializerSyntax` that captures both the `=` and the parsed `TypeSyntax`. + - Pull Request: https://github.com/swiftlang/swift-syntax/pull/3152 + +## API Behavior Changes + +## Deprecations + +## API-Incompatible Changes + +## Template + +- *Affected API or two word description* + - Description: *A 1-2 sentence description of the new/modified API* + - Issue: *If an issue exists for this change, a link to the issue* + - Pull Request: *Link to the pull request(s) that introduces this change* + - Migration steps: Steps that adopters of swift-syntax should take to move to the new API (required for deprecations and API-incompatible changes). + - Notes: *In case of deprecations or API-incompatible changes, the reason why this change was made and the suggested alternative* + +*Insert entries in chronological order, with newer entries at the bottom* diff --git a/Sources/SwiftParser/Declarations.swift b/Sources/SwiftParser/Declarations.swift index 399f60a6d64..5a9dd812082 100644 --- a/Sources/SwiftParser/Declarations.swift +++ b/Sources/SwiftParser/Declarations.swift @@ -680,8 +680,9 @@ extension Parser { // type parameters, not parameter packs or value generics yet. let defaultType: RawTypeInitializerClauseSyntax? if self.experimentalFeatures.contains(.defaultGenerics), - specifier == nil, - let equal = self.consume(if: .equal) { + specifier == nil, + let equal = self.consume(if: .equal) + { let type = self.parseType() defaultType = RawTypeInitializerClauseSyntax( equal: equal, diff --git a/Tests/SwiftParserTest/DefaultGenericsTest.swift b/Tests/SwiftParserTest/DefaultGenericsTest.swift index 24a06abb70a..a2803acaf67 100644 --- a/Tests/SwiftParserTest/DefaultGenericsTest.swift +++ b/Tests/SwiftParserTest/DefaultGenericsTest.swift @@ -76,7 +76,7 @@ final class DefaultGenericsTest: ParserTestCase { ), DiagnosticSpec( message: "unexpected code '= Int>' in struct" - ) + ), ], fixedSource: """ struct A = Int> {} @@ -98,7 +98,7 @@ final class DefaultGenericsTest: ParserTestCase { ), DiagnosticSpec( message: "unexpected code '= Int>' in struct" - ) + ), ], fixedSource: """ struct A = Int> {}