-
Notifications
You must be signed in to change notification settings - Fork 441
Add Sendable annotations to swift-syntax #2425
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 Sendable annotations to swift-syntax #2425
Conversation
4fb95c4
to
aa91cfc
Compare
@swift-ci Please test |
…` across actor boundaries
aa91cfc
to
485f166
Compare
We are getting a new warning in CI: ``` .../swift-testing/Sources/TestingMacros/ConditionMacro.swift:46:13: warning: let '_sourceLocationLabel' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6 private let _sourceLocationLabel = TokenSyntax.identifier("sourceLocation") ^ ``` Work around it by using `private var ... {}` instead of `private let`. I'm assuming that creating a `TokenSyntax` is not prohibitively expensive, so the change should be safe. @ahoppen confirms that this operation is reasonably cheap and that syntax nodes are not safely sendable in the 5.9 tag of swift-syntax, so the warning is technically valid. Although our code does not access these constants across concurrency domains, the compiler is (in theory) free to invoke our macro expansion code on multiple tasks concurrently. Concurrency safety in swift-syntax is tracked with swiftlang/swift-syntax#2425.
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.
Other than the silly nitpick, LGTM. Would be good to have @rintaro take a look too though.
485f166
to
1388b09
Compare
@swift-ci Please test |
@swift-ci Please test Windows |
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.
I didn't check what types should be Sendable
, but other than that, SyntaxArena
/RawSyntax
related changes looks good to me.
payload.presence = newValue | ||
return RawSyntax(arena: arena, payload: .parsedToken(payload)) | ||
if arena == self.raw.arenaReference { | ||
payload.presence = newValue | ||
return RawSyntax(arena: arena, payload: .parsedToken(payload)) | ||
} | ||
// If the modified token is allocated in a different arena, it might have | ||
// a different or no `parseTrivia` function. We thus cannot use a | ||
// `parsedToken` anymore. | ||
return .makeMaterializedToken( | ||
kind: formKind(), | ||
leadingTrivia: formLeadingTrivia(), | ||
trailingTrivia: formTrailingTrivia(), | ||
presence: newValue, | ||
tokenDiagnostic: tokenDiagnostic, | ||
arena: arena | ||
) |
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.
Just to make sure I understand correctly, this should be reverted when SwiftParser
is merged, right?
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.
I’d prefer to keep it even if/when we merge SwiftSyntax + SwiftParser. Technically, the old implementation is not correct because the new arena could have a different parseTriviaFunction
than the arena the node is allocated in and thus the trivia pieces could change here if we don’t materialize them.
…ances Revert "Merge pull request #2425 from ahoppen/ahoppen/sendable-conformances"
Audit all modules in swift-syntax, add
Sendable
annotations to the types that are sendable.The audit uncovered that
SyntaxArena
was sent across actor boundaries even thoughSyntaxArena
is not thread safe. I fixed these issues by:ParsingSyntaxArena
slightly: If you modify a parsed token and the new arena is a different one than the old arena (and thus might not be aParsingSyntaxArena
), we materialize it and its trivia. That way we no longer need to search through all child arenas to find aParsingSyntaxArena
and theirparseTrivia
function. It also fixes a potential correctness issue if the modified node is allocated in aParsingSyntaxArena
that has a differentparseTrivia
function than the originalParsingSyntaxArena
.RetainedSyntaxArena
: In many cases where we were passing around aSyntaxArena
, we just needed to ensure that the syntax arena stayed alive but never accessed any properties of it.RetainedSyntaxArena
is an opaque wrapper aroundSyntaxArena
and even thoughSyntaxArena
is not sendable, we can send this type across actor boundaries because it doesn’t allow access to the internal state ofSyntaxArena
.SyntaxArenaAllocated(Buffer)Pointer
: This is a wrapper aroundUnsafe(Buffer)Pointer
that indicates that the buffer is allocated in a syntax arena. Because the syntax arena will always outlive any syntax nodes that reference its contents, we know that the buffer's contents won't get deallocated while being accessed and thus we can add an uncheckedSendable
conformance to it.Unsafe(Buffer)Pointer
is not sendable by default.SyntaxArena.hasParent
, which already had aFIXME
associated with it. This PR won’t make the situation any worse than it is today, so I just moved theFIXME
but we should fix it in a follow-up PR.rdar://117813694