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

[region-isolation] Implement function sub typing rules #74129

Merged

Conversation

gottesmm
Copy link
Contributor

@gottesmm gottesmm commented Jun 4, 2024

Just taking care of this real quick.

rdar://127675288

@gottesmm
Copy link
Contributor Author

gottesmm commented Jun 4, 2024

@swift-ci smoke test

@gottesmm gottesmm enabled auto-merge June 4, 2024 23:18
@gottesmm gottesmm force-pushed the pr-d17a3faab1ceab8b831d7649c1005be9c49d771c branch from cbc5c12 to 684a33f Compare June 12, 2024 23:12
gottesmm added 5 commits June 12, 2024 16:13
…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
… 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
…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.
@gottesmm gottesmm force-pushed the pr-d17a3faab1ceab8b831d7649c1005be9c49d771c branch from 684a33f to 85a66d7 Compare June 12, 2024 23:13
The previous commit fixed things like:

```swift
let x: () -> sending String = { "" }
```

This commit fixes this test case:

```swift
let x = { () -> sending String in "" }
```
@gottesmm gottesmm force-pushed the pr-d17a3faab1ceab8b831d7649c1005be9c49d771c branch from 85a66d7 to 81100ad Compare June 13, 2024 00:00
@gottesmm
Copy link
Contributor Author

@swift-ci smoke test

@gottesmm gottesmm requested a review from adrian-prantl as a code owner June 13, 2024 06:07
@gottesmm
Copy link
Contributor Author

@swift-ci smoke test

@gottesmm gottesmm force-pushed the pr-d17a3faab1ceab8b831d7649c1005be9c49d771c branch from e8c14fb to 74fa96a Compare June 14, 2024 04:49
…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.
@gottesmm gottesmm force-pushed the pr-d17a3faab1ceab8b831d7649c1005be9c49d771c branch from 74fa96a to 16d0194 Compare June 14, 2024 05:27
@gottesmm gottesmm disabled auto-merge June 14, 2024 05:27
@gottesmm
Copy link
Contributor Author

@swift-ci smoke test

class NonSendableKlass {}

protocol ProtocolWithSendingReqs {
func sendingResult() -> sending NonSendableKlass // expected-note {{}}
Copy link
Contributor

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?

Copy link
Contributor Author

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor typo:

Suggested change
/// sending result, but is passed a function typeed parameter without a
/// sending result, but is passed a function typed parameter without a

Copy link
Contributor

@ktoso ktoso left a 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

@gottesmm
Copy link
Contributor Author

macOS failure is something unrelated in lldb.

@gottesmm
Copy link
Contributor Author

@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.
@gottesmm
Copy link
Contributor Author

@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 {
Copy link
Contributor

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);
Copy link
Contributor

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 {
Copy link
Contributor

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,
Copy link
Contributor

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: {
Copy link
Contributor

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.

@gottesmm gottesmm merged commit f995418 into swiftlang:main Jun 14, 2024
3 checks passed
Comment on lines +1558 to +1559
} else if (Tok.isContextualKeyword("sending")) {
consumeToken();
Copy link
Member

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) {}

Copy link
Contributor Author

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.

Copy link
Member

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.

gottesmm added a commit to gottesmm/swift that referenced this pull request Jun 20, 2024
Didn't need to modify any tests since this shouldn't have any functional
change. Just a slight cleanup.
@gottesmm gottesmm deleted the pr-d17a3faab1ceab8b831d7649c1005be9c49d771c branch June 20, 2024 03:19
gottesmm added a commit that referenced this pull request Jun 25, 2024
…7a86b82f9d282c

Follow up fixes with feedback from #74129
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.

4 participants