Skip to content

Emit error when move-only type is used as a generic type #62599

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

Merged
merged 12 commits into from
Feb 2, 2023

Conversation

kavon
Copy link
Member

@kavon kavon commented Dec 15, 2022

resolves rdar://101651405

Needed-before-merge TODOs:

  • Prevent conformances to Copyable from appearing in swiftinterface files (see Sema/missing-import-typealias.swift)
  • Fix any other issues with other tests.

Deferrable TODOs:

  • Diagnose expressions that explicitly cast a move-only value to some existential as an error, not warning. i.e., mo as! AnyHashable. Alternatively, make sure they truly do fail at runtime.
  • Improve diagnostics (specify the 2nd type it failed to match with in the message!)
  • Prevent move-only types from appearing in tuples.
  • Make pack types (repeat each T) conform to _Copyable (see Generics/tuple-conformances.swift)
  • Get _Copyable out of the stdlib and make it some sort of builtin that's pre-populated in the ASTContext, like Any. We can't bootstrap the stdlib if that protocol is defined in some part of the stdlib, because every generic parameter is implicitly constrained to it and we have to be able to typecheck with -parse-stdlib. (see Sema/stdlib_sugar_types.swift)
  • Determine whether changes to the diagnostics for unqualified member lookups are a significant concern and whether we can mitigate them. Example:
protocol MungedString {}

func format<T: MungedString>(_ t: T) {}
func takeGeneric<T>(_ t: T) {}

func caller() {
  // PREVIOUSLY error: type 'MungedString' has no member 'emptyString'
  // NOW error: reference to member 'emptyString' cannot be resolved without a contextual type
  format(.emptyString)

  // PREVIOUSLY error: cannot infer contextual base in reference to member 'somebody'
  // NOW error: type '_Copyable' has no member 'somebody'
  takeGeneric(.somebody)
}

@kavon kavon force-pushed the ban-moveonly-generic-subst branch from 35896a5 to 67e52e2 Compare January 6, 2023 22:30
@kavon kavon force-pushed the ban-moveonly-generic-subst branch 4 times, most recently from 0e8fca6 to e3a0ade Compare January 27, 2023 04:46
@kavon kavon force-pushed the ban-moveonly-generic-subst branch from e3a0ade to f68c14b Compare January 27, 2023 05:12
@kavon
Copy link
Member Author

kavon commented Jan 27, 2023

@swift-ci please test

@kavon kavon force-pushed the ban-moveonly-generic-subst branch from f68c14b to 30c728d Compare January 27, 2023 06:38
@kavon kavon changed the title Emit error when move-only type is substituted for a generic type Emit error when move-only type is used as a generic type Jan 27, 2023
@kavon kavon force-pushed the ban-moveonly-generic-subst branch from 30c728d to 6a9732c Compare January 28, 2023 03:14
@kavon
Copy link
Member Author

kavon commented Jan 30, 2023

@swift-ci please test

@kavon
Copy link
Member Author

kavon commented Jan 31, 2023

@swift-ci pls smoke test macOS platform

@kavon
Copy link
Member Author

kavon commented Jan 31, 2023

@swift-ci please smoke test macOS platform

@kavon kavon force-pushed the ban-moveonly-generic-subst branch 3 times, most recently from a0fb617 to 8b0ce29 Compare February 1, 2023 06:41
@kavon kavon marked this pull request as ready for review February 1, 2023 06:43
@kavon
Copy link
Member Author

kavon commented Feb 1, 2023

@swift-ci please test and merge

@kavon
Copy link
Member Author

kavon commented Feb 1, 2023

@swift-ci Please Test Source Compatibility

@kavon
Copy link
Member Author

kavon commented Feb 1, 2023

@swift-ci please test

@kavon kavon force-pushed the ban-moveonly-generic-subst branch from 8b0ce29 to 3cd43bf Compare February 2, 2023 04:05
@kavon
Copy link
Member Author

kavon commented Feb 2, 2023

@swift-ci please smoke test and merge

@kavon kavon force-pushed the ban-moveonly-generic-subst branch from 95ce272 to 82740a4 Compare February 2, 2023 07:24
kavon added 2 commits February 1, 2023 23:38
Since values of generic type are currently assumed to always
support copying, we need to prevent move-only types from
being substituted for generic type parameters.

This approach leans on a `_Copyable` marker protocol to which
all generic type parameters implicitly must conform.

A few other changes in this initial implementation:

- Now every concrete type that can conform to Copyable will do so. This fixes issues with conforming to a protocol that requires Copyable.
- Narrowly ban writing a concrete type `[T]` when `T` is move-only.
kavon added 10 commits February 1, 2023 23:38
`Any`, which is effectively `any _Copyable`, is obviously copyable.
`matchExistentialTypes` ends up getting called in most cases,
to ensure the conversion is legal.
Since structs and enums only participate in subtyping via protocols,
move-only types that are structs and enums effectively are only
subtypes of themselves.
Also, only generate those conformances when the move-only feature is on,
for now.
where `MO` is a move-only type.

turns out it was being allowed because the cast is represented as a
disjunction in the constraint solver:

- `MO conv AnyObject`
- `MO bridge conv AnyObject`

I caught the first one but missed the second, which was unconditionally
being allowed.
Previous implementation blindly took the first solution
and tried to diagnose, but that's not a safe assumption.

It's possible that among the solution-fix pairs, one
of `noncopyableTy`'s within the fix differs from the
others. Things probably can go wrong because the solution
doesn't correspond to that type.

Also, in that case we'd be emitting a diagnostic that
may not make any sense. In such cases, now we decline
to emit a diagnostic.

Thanks Pavel for catching this.
A number of our existing tests put move-only types in optionals and
used them as arguments to generic type parameters. It turns out that
many of these appearances in the tests were not crucial for the test's
functionality itself.

The little coverage for force-unwrapping an Optional<moveOnly>
that was lost will be regained once we make these types sound.

I also tried to tidy up some of the tests with consistent naming for
operations on values, i.e., `consumeVal` and `borrowVal` functions.
@kavon kavon force-pushed the ban-moveonly-generic-subst branch from 0ec9a08 to d2da71a Compare February 2, 2023 07:52
@kavon
Copy link
Member Author

kavon commented Feb 2, 2023

@swift-ci please smoke test and merge

@swift-ci swift-ci merged commit bf2816b into swiftlang:main Feb 2, 2023
@kavon kavon deleted the ban-moveonly-generic-subst branch February 2, 2023 19:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants