-
Notifications
You must be signed in to change notification settings - Fork 441
Add support for lifetime type specifiers #2433
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for lifetime type specifiers #2433
Conversation
4dd7bc7
to
e5c0834
Compare
@swift-ci Please test |
@swift-ci Please test Windows |
Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesTUVWXYZ.swift
Outdated
Show resolved
Hide resolved
e5c0834
to
366fa95
Compare
@swift-ci Please test |
@swift-ci Please test Windows |
366fa95
to
b627323
Compare
@swift-ci Please test |
b627323
to
685768d
Compare
@swift-ci Please test macOS |
5a0ecc9
to
4a1ba3b
Compare
@swift-ci Please test macOS |
4a1ba3b
to
81bf075
Compare
@swift-ci Please test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lifetime dependence changes lgtm. I added some minor comments about tests. That + changes for initializers can be done as a follow up.
Thanks for this PR! With this we are almost close to get rid of -disable-experimental-parser-round-trip
in our lifetime dependence tests!
experimentalFeatures: [.nonescapableTypes] | ||
) | ||
|
||
assertParse("func foo() -> _borrow(0) X", diagnostics: [], experimentalFeatures: [.nonescapableTypes]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add a failure test with a -ve integer ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a test case for _borrow(-1)
@@ -325,4 +325,59 @@ final class TypeTests: ParserTestCase { | |||
assertParse("func foo1(_ a: _const borrowing String) {}") | |||
assertParse("func foo2(_ a: borrowing _const String) {}") | |||
} | |||
|
|||
func testLifetimeSpecifier() { | |||
assertParse("func foo() -> _borrow(x) X", experimentalFeatures: [.nonescapableTypes]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add a failure test without the experimental feature?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a test case
81bf075
to
6c36cec
Compare
@swift-ci Please test |
@swift-ci Please test Windows |
Here’s an abbreviated summary of the new nodes. public struct AttributedTypeSyntax {
/// A list of specifiers that can be attached to the type, such as `inout`, `isolated`, or `consuming`.
public var specifiers: TypeSpecifierListSyntax
/// A list of attributes that can be attached to the type, such as `@escaping`.
public var attributes: AttributeListSyntax
/// The type to with the specifiers and attributes are applied.
public var baseType: TypeSyntax
}
/// ### Children
///
/// (``SimpleTypeSpecifierSyntax`` | ``LifetimeTypeSpecifierSyntax``) `*`
///
/// ### Contained in
///
/// - ``AttributedTypeSyntax``.``AttributedTypeSyntax/specifiers``
public struct TypeSpecifierListSyntax {
public enum Element: SyntaxChildChoices {
case `simpleTypeSpecifier`(SimpleTypeSpecifierSyntax)
case `lifetimeTypeSpecifier`(LifetimeTypeSpecifierSyntax)
}
}
/// A specifier that can be attached to a type to eg. mark a parameter as `inout` or `consuming`
///
/// ### Children
///
/// - `specifier`: (`inout` | `__shared` | `__owned` | `isolated` | `_const` | `borrowing` | `consuming` | `transferring` | `_resultDependsOn`)
///
/// ### Contained in
///
/// - ``TypeSpecifierListSyntax``
public struct SimpleTypeSpecifierSyntax {
/// The specifier token that's attached to the type.
///
/// ### Tokens
///
/// For syntax trees generated by the parser, this is guaranteed to be one of the following kinds:
/// - `inout`
/// - `__shared`
/// - `__owned`
/// - `isolated`
/// - `_const`
/// - `borrowing`
/// - `consuming`
/// - `transferring`
/// - `_resultDependsOn`
public var specifier: TokenSyntax
}
/// A specifier that specifies function parameter on whose lifetime a type depends
///
/// ### Children
///
/// - `specifier`: (`_copy` | `_consume` | `_borrow` | `_mutate`)
/// - `arguments`: ``LifetimeSpecifierArgumentsSyntax``
///
/// ### Contained in
///
/// - ``TypeSpecifierListSyntax``
public struct LifetimeTypeSpecifierSyntax {
/// The specifier token that's attached to the type.
///
/// ### Tokens
///
/// For syntax trees generated by the parser, this is guaranteed to be one of the following kinds:
/// - `_copy`
/// - `_consume`
/// - `_borrow`
/// - `_mutate`
public var specifier: TokenSyntax
public var arguments: LifetimeSpecifierArgumentsSyntax
}
/// ### Children
///
/// ``LifetimeSpecifierArgumentSyntax`` `*`
///
/// ### Contained in
///
/// - ``LifetimeSpecifierArgumentsSyntax``.``LifetimeSpecifierArgumentsSyntax/arguments``
public struct LifetimeSpecifierArgumentListSyntax {
public typealias Element = LifetimeSpecifierArgumentSyntax
}
/// An optional argument passed to a type parameter.
///
/// ### Example
/// `borrow(data)` in `func foo(data: Array<Item>) -> borrow(data) ComplexReferenceType`
///
/// ### Children
///
/// - `leftParen`: `(`
/// - `arguments`: ``LifetimeSpecifierArgumentListSyntax``
/// - `rightParen`: `)`
///
/// ### Contained in
///
/// - ``LifetimeTypeSpecifierSyntax``.``LifetimeTypeSpecifierSyntax/arguments``
public struct LifetimeSpecifierArgumentsSyntax {
/// ### Tokens
///
/// For syntax trees generated by the parser, this is guaranteed to be `(`.
public var leftParen: TokenSyntax
/// The function parameters that the lifetime of the annotated type depends on.
public var arguments: LifetimeSpecifierArgumentListSyntax
/// ### Tokens
///
/// For syntax trees generated by the parser, this is guaranteed to be `)`.
public var rightParen: TokenSyntax
}
/// A single argument that can be added to a lifetime specifier like `borrow`, `mutate`, `consume` or `copy`.
///
/// ### Example
/// `data` in `func foo(data: Array<Item>) -> borrow(data) ComplexReferenceType`
///
/// ### Children
///
/// - `parameter`: (`<identifier>` | `self` | `<integerLiteral>`)
/// - `trailingComma`: `,`?
///
/// ### Contained in
///
/// - ``LifetimeSpecifierArgumentListSyntax``
public struct LifetimeSpecifierArgumentSyntax {
/// The parameter on which the lifetime of this type depends.
///
/// This can be an identifier referring to an external parameter name, an integer literal to refer to an unnamed
/// parameter or `self` if the type's lifetime depends on the object the method is called on.
///
/// ### Tokens
///
/// For syntax trees generated by the parser, this is guaranteed to be one of the following kinds:
/// - `<identifier>`
/// - `self`
/// - `<integerLiteral>`
public var parameter: TokenSyntax
/// ### Tokens
///
/// For syntax trees generated by the parser, this is guaranteed to be `,`.
public var trailingComma: TokenSyntax?
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, just one question
Node( | ||
kind: .lifetimeSpecifierArgument, | ||
base: .syntax, | ||
nameForDiagnostics: nil, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the lifetime specifier nodes be marked experimental and therefore SPI?
Yeah, that representation looks fine to me. |
9c33644
to
8da6dba
Compare
@swift-ci Please test |
Having multiple type specifiers on a type is valid in the C++ parser but not in the Swift parser. rdar://118125715
… generated `TypeSpecifierSyntax.SpecifierOptions` The two `TokenSpecSet`s had already diverged. Instead of manually maintaining the `TypeSpecifier` spec set, we should allow all keywors specified in the syntax tree definition.
…f as docc links Docc doesn’t like references to SPI types because they are not part of the public API.
8da6dba
to
3df63e8
Compare
@swift-ci Please test |
@swift-ci Please test Windows |
Having multiple type specifiers on a type is valid in the C++ parser but not in the Swift parser. Also add support for lifetime specifiers that can have arguments, like
borrow(data)
.rdar://118125715
While at it, replace the manually maintained
TokenSpecSet
TypeSpecifier
by the generatedTypeSpecifierSyntax.SpecifierOptions
The two
TokenSpecSet
s had already diverged. Instead of manually maintaining theTypeSpecifier
spec set, we should allow all keywors specified in the syntax tree definition.