-
Notifications
You must be signed in to change notification settings - Fork 108
Use @Test function parameters to explicitly type array literal argument expressions #808
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
base: main
Are you sure you want to change the base?
Use @Test function parameters to explicitly type array literal argument expressions #808
Conversation
…nt expressions
@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.
Discussing off-GitHub. It should be possible to implement this change without needing deep macro changes and, ideally, preserving the "good" diagnostics as much as possible.
|
||
return map { argument in | ||
// Only add explicit types below if this is an Array literal expression. | ||
guard argument.expression.is(ArrayExprSyntax.self) else { |
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.
You probably need to strip parentheses here.
.map { argument, parameter in | ||
// Only add explicit types below if this is an Array literal | ||
// expression. | ||
guard argument.expression.is(ArrayExprSyntax.self) else { |
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.
You probably need to strip parentheses here.
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.
Actually, does this branch even need to do anything interesting at all?
/// `as ...` cast. | ||
fileprivate func testArguments(typedUsingParameters parameters: FunctionParameterListSyntax) -> [Argument] { | ||
if count == 1 { | ||
let tupleTypes = parameters.lazy |
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.
This will fail to compile if any arguments have specifiers like borrowing
. (I'm not sure if that's correct in this position.) You should check the exact type of type node.
fileprivate func testArguments(typedUsingParameters parameters: FunctionParameterListSyntax) -> [Argument] { | ||
if count == 1 { | ||
let tupleTypes = parameters.lazy | ||
.map(\.type) |
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.
.trimmedDescription
?
I've extracted some of the general macro refactoring into a separate PR (#834) |
… macro (#834) This is a minor refactor of the logic and data structures in the `@Test` macro implementation responsible for parsing and handling test function argument expressions. ### Motivation: I discovered there was a way to simplify this logic while working on #808, and since this isn't strictly pertinent to that PR I wanted to extract it and land it separately here. ### Modifications: - Remove the need to hardcode the parameter label `arguments:` in three places. - Remove the need to iterate a Collection using raw indices. - Resolve one "TODO" comment. ### Checklist: - [x] Code and documentation should follow the style of the [Style Guide](https://github.com/apple/swift-testing/blob/main/Documentation/StyleGuide.md). - [x] If public symbols are renamed or modified, DocC references should be updated.
This solves a problem that users who pass array literals to
@Test(arguments: ...)
may encounter if the array's elements are heterogeneous. For example:Due to the use of heterogeneous elements
Int.self
andString.self
, the overall array's type is inferred as[Any]
. This leads to two problems:@Test(arguments:)
macro requires aCollection
which isSendable
, and[Any]
is notSendable
. This prevents passing the array to the macro at all, since arguments to a macro must typecheck successfully before the macro is expanded.Any.Type
andString
, respectively. For the macro expansion to produce valid code, the array literal needs to have type[(Any.Type, String)]
.This PR makes two changes to address those problems:
@Test
macro declarations without theirSendable
requirements. This solves problem 1 above. (See the considerations below for discussion about why I believe this is safe and reasonable.)as ...
cast to array literal expressions passed toarguments: ...
(unless they already have one) to provide an explicit type.Continuing the example above, this results in the expanded code behaving as though the array expression had
as [(Any.Type, String)]
at the end, and the original code now compiles successfully.Concurrency safety
The expanded code from the new
@Test
overloads is no less concurrency safe than before, because it still calls APIs from the testing library which requireSendable
. This means that passing a non-Sendable
collection will still result in a compiler diagnostic, just with a different source location than before:Documentation
The new
@Test
overloads are necessarilypublic
but are hidden from rendered DocC documentation using@_documentation(visibility: private)
. From an end user's perspective,@Test(arguments:)
did, and still does, requireSendable
; the only thing changing is where that enforcement occurs. So in terms of documentation, the only overloads we need to document are those that do requireSendable
. In fact, for similar reasons, we already hide many of our@Test
overloads from documentation so this has precedent.Checklist:
Fixes swiftlang/swift#76637