Skip to content
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 non-copyable types as expectation arguments #543

Open
grynspan opened this issue Jul 16, 2024 · 7 comments
Open

Add support for non-copyable types as expectation arguments #543

grynspan opened this issue Jul 16, 2024 · 7 comments
Labels
enhancement New feature or request public-api Affects public API
Milestone

Comments

@grynspan
Copy link
Contributor

Add support for non-copyable types as expectation arguments, e.g.:

struct S: ~Copyable, ... {}

let a: S = ...
let b: S = ...
#expect(a != b)
#expect(a.foo())
#expect(a.isBar)
// etc.
@grynspan grynspan added enhancement New feature or request public-api Affects public API swift-6.1 labels Jul 16, 2024
@grynspan
Copy link
Contributor Author

grynspan commented Jul 16, 2024

Known issues:

  • String(describing:) does not take move-only values, so it cannot be used to describe a value that's part of a failed expectation expression
  • type(of:) does not take move-only values, so we can't get the runtime type of a value
  • String(reflecting:) does not take move-only metatypes, so we cannot capture the FQN of a move-only type
  • Variadic generics don't support move-only types (or at least, I can't get the compiler to accept them) which precludes the expansion of function calls that take any move-only arguments
  • We cannot syntactically distinguish consuming from borrowing arguments at call sites, so we may not be able to correctly expand expressions with move-only parts (and we don't have enough information during macro expansion to know to suppress these expansions, unlike with try and await.)
  • @autoclosure () -> U is treated as escaping, which means syntactically we can't borrow the right-hand argument of a binary operator.
  • Result needs to support non-copyable Success values (although we could build our own monad type if needed)
    • Attempting to implement my own Result analogue with the signature:
    enum __Result<Success, Failure>: ~Copyable where Success: ~Copyable, Failure: Error
    Seems to confuse the compiler, which still complains:

    🛑 Noncopyable type 'S' cannot be substituted for copyable generic parameter 'Success' in '__Result'

  • For our current implementation of binary operator expansion, we need non-copyable tuples.
  • Conditional casts to/from move-only types and existentials are needed for us to be able to implement String(describingForTest:). Even if we don't support the full gamut of possible stringification techniques, we need to be able to write something like if let value = value as? Copyable { ... } so we can opt into the full set for types that allow it.

@Azoy
Copy link

Azoy commented Jul 17, 2024

Result needs to support non-copyable Success values (although we could build our own monad type if needed)

FWIW Result will support non-copyable Success values in Swift 6.0

@grynspan
Copy link
Contributor Author

Good to know—that knocks one point off the list, at least!

@stmontgomery
Copy link
Contributor

stmontgomery commented Jul 17, 2024

  • @autoclosure () -> U is treated as escaping, which means syntactically we can't borrow the right-hand argument of a binary operator.

To avoid this problem, could we change our macro expansion code, and the associated __check.... functions it calls, to use an explicit closure and then stop using @autoclosure?

@grynspan
Copy link
Contributor Author

That causes other compilation issues (I'd have to dig into the pre-OSS commit history to determine what, exactly, the problems were—maybe they're no longer relevant?)

@grynspan
Copy link
Contributor Author

Thinking about it, I think it was that it forced evaluation of the RHS argument at capture time, defeating the purpose of a short-circuiting operator like &&.

@grynspan
Copy link
Contributor Author

String(reflecting:) does not take move-only metatypes, so we cannot capture the FQN of a move-only type

This appears to be resolved in the latest toolchains.

@grynspan grynspan added this to the Swift 6.1 milestone Sep 10, 2024
@grynspan grynspan mentioned this issue Sep 16, 2024
2 tasks
@grynspan grynspan modified the milestones: Swift 6.1, Swift 6.x Nov 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request public-api Affects public API
Projects
None yet
Development

No branches or pull requests

3 participants