-
Notifications
You must be signed in to change notification settings - Fork 10.5k
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
[region-isolation] Implement function sub typing rules #74129
[region-isolation] Implement function sub typing rules #74129
Conversation
@swift-ci smoke test |
cbc5c12
to
684a33f
Compare
…witnessed by a function without a sending result. This is important since the witness is not promising to return a disconnected value and the caller of the requirement is going to accept that. rdar://127675288
rdar://127675288
… computeFailureTypeWitness. The problem happens when a type conforms to AsyncIterator.next when next in the protocol returns its value as sending, but the witness does not have sending. This results in the function subtyping rules rejecting the witness... but we still leave in the witness as a nullptr... so we need to handle it here. rdar://129300953
…testing typecheck errors.
…rs and results. I found this while writing tests for the earlier part of this work. Since this is also type checking work, I am just folding this work into that work.
684a33f
to
85a66d7
Compare
The previous commit fixed things like: ```swift let x: () -> sending String = { "" } ``` This commit fixes this test case: ```swift let x = { () -> sending String in "" } ```
85a66d7
to
81100ad
Compare
@swift-ci smoke test |
@swift-ci smoke test |
e8c14fb
to
74fa96a
Compare
…when not in swift 6. This will ensure that we do not break anyone who has adopted APIs like CheckedContinuation.resume that now have sending parameters. An example of where this can come up is shown by the ProcessType in SwiftToolsCore: ```swift @available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) @discardableResult public func waitUntilExit() async throws -> ProcessResult { try await withCheckedThrowingContinuation { continuation in DispatchQueue.processConcurrent.async { self.waitUntilExit(continuation.resume(with:)) } } } ``` This fails to compile since self.waitUntilExit doesn't expect a function that takes a sending parameter. We want to give people time to fix such issues.
74fa96a
to
16d0194
Compare
@swift-ci smoke test |
class NonSendableKlass {} | ||
|
||
protocol ProtocolWithSendingReqs { | ||
func sendingResult() -> sending NonSendableKlass // expected-note {{}} |
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.
what is expected note {{}} -- "any note"? First time seeing this tbh; worth spelling it out?
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.
The reason I did this is that the message here isn't important to what I am testing but it is still a diagnostic.
/// parameter. | ||
/// | ||
/// 2. Where we have a function that expects a function typed parameter with a | ||
/// sending result, but is passed a function typeed parameter without a |
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.
minor typo:
/// sending result, but is passed a function typeed parameter without a | |
/// sending result, but is passed a function typed parameter without a |
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.
Looks OK, I'm not 100% sure about the rule but it sounds good from thinking about it for a while... LGTM
macOS failure is something unrelated in lldb. |
@swift-ci smoke test macOS platform |
For now, just turn off the error in swift 5 mode. I wanted to make this an error but right now I do not have all of the time to do it so this is good in the short term so that people can adopt sending on protocols without breaking people using their framework in executables still compiling in swift 5.
@swift-ci smoke test |
/// that this is being sent to does not enforce that invariants within its body. | ||
class AllowSendingMismatch final : public ContextualMismatch { | ||
public: | ||
enum class Kind { |
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 don't think this is necessary, it could be determined based on the locator associated wit the fix.
|
||
static AllowSendingMismatch *create(ConstraintSystem &cs, | ||
ConstraintLocator *locator, Type srcType, | ||
Type dstType, Kind kind); |
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.
Nit: Based on all other create
methods let's use - cs, src, dst, locator
ordering.
bool diagnoseAsError() override; | ||
}; | ||
|
||
class SendingOnFunctionResultMismatchFailure final : public ContextualFailure { |
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.
It looks like this split is not necessary, the diagnostic is anchored on a simplified locator so it would point to the right spot.
} | ||
|
||
bool SendingOnFunctionResultMismatchFailure::diagnoseAsError() { | ||
emitDiagnosticAt(getLoc(), diag::sending_function_wrong_sending, |
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.
Why not just emitDiagnostic
since you are using getLoc()
anyway?
solution, getFromType(), getToType(), getLocator(), fixBehavior); | ||
return failure.diagnose(asNote); | ||
} | ||
case Kind::Result: { |
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.
It doesn't look like this split brings much to the table, the difference could be handled internally to the diagnostic.
} else if (Tok.isContextualKeyword("sending")) { | ||
consumeToken(); |
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.
Is this correct? My impression is that only parameters can be annotated as sending
and not arbitrary types. Looking at this change, I think it might cause the following to stop compiling because sending
now gets consumed as a contextual keyword instead of as the type name.
struct sending {}
let a: sending = sending()
func test(x: sending) {}
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.
@ahoppen I just tested this locally and it isn't an issue.
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 just attached a debugger to it and understand why my example didn’t hit the issue that I was thinking about but this one does
struct sending {}
func test() {
_ = { () -> sending in
}
}
I think the proper solution here is to check if sending
is followed by something that satisfies canParseType
. If not, we probably need to backtrack and check if sending
itself can be used as the type name.
Didn't need to modify any tests since this shouldn't have any functional change. Just a slight cleanup.
…7a86b82f9d282c Follow up fixes with feedback from #74129
Just taking care of this real quick.
rdar://127675288