-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
Initial support for return type notation (RTN) #109010
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
r? compiler cc @rust-lang/wg-async I think @nikomatsakis is going to create a lang-team initiative for this (or perhaps expected me to? can't tell from the convo...), but for now, I can put this up for review for the compiler side. |
d2c2243
to
3699d11
Compare
tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs
Show resolved
Hide resolved
57191ac
to
496763d
Compare
Some changes occurred in src/tools/clippy cc @rust-lang/clippy |
Looks good to me. Feel free to add the doc comments I mentioned or not (up to you!) and then r=me afterwards. |
@bors r=eholk |
📌 Commit bc95b6ccd222ed4833f9a316d08b55ea5fccbc92 has been approved by It is now in the queue for this repository. |
I personally also somewhat strongly dislike this approach. Arguing mostly against the feature as presented in https://smallcultfollowing.com/babysteps/blog/2023/02/13/return-type-notation-send-bounds-part-2/. I agree with the premise of the "send bound" problem and believe this is something we have to fix. I do however see fairly strong negatives of the current approach and believe that most of them can be avoided by using a far smaller extension of the language. The negatives of RTN
I assume that most developers do not have a clear understanding of async functions as something that returns a state machine when called. I think that the intuitive understanding tends to end at "If I use an async function, I have to use Because of the above point, the design of RTN will always be suboptimal for ordinary functions. If we allow it and I also dislike the complexity necessary to deal with generic functions. The proposal requires yet another syntax extension, inferring the generic parameters for the function from by specifying the expected argument types. This again is unfamiliar and different from how generic parameters of methods are handled in any other context. Considering that the syntax for RTN is something between type and expression syntax, I think that both requiring the turbofish and not requiring it will end up feeling slightly weird. I also think that the restriction to only use RTN in A not yet mentioned alternative (as far as I know)As stated above, I think RTN has a very high cost which may however be justified if there is no sensible alternative. While I haven't worked out all the details or the final syntax, here's a general idea I would prefer. The problem statement is: we need the ability to somehow talk about the future returned by async functions in traits. As stated in Niko's post the reason to use RTN is that we do not want to expose details about this desugaring which we don't want to be stable. My proposal is that the authors of traits have to explicitly bind the returned future of an async function to an associated type of the trait. This can be done by using an attribute1. An example would be the following: trait HealthCheck {
// idk about `'anon`, need to provide some way to talk about the anonymous lifetimes
// in the return type of `check`.
type CheckFut<'anon>;
// The attribute name is a placeholder.
#[defined_by_returned_future(CheckFut)]
async fn check(&mut self, server: Server);
} Adding bounds on the return future returned by It does not have to deal with the difference between sync and async functions, as it is explicit opt-in for Let's end by going through the arguments for RTN in the post.
Solved by having the author explicitly define the associated type.
This is a valid advantage of RTN, but I believe the negatives still far outweigh that benefit. I think it's fine to start by not allowing APIT Footnotes
|
I suspect you are misunderstanding the problem space here and what RTN has been chalked up to solve. Your criticisms of the syntax are valid in my opinion, even though personally I quite like it, but your points on explicitly binding to the associated type defeat the point of what is trying to be solved here. The issue, as far as I understand it, is the variability of Regarding the syntax of Anyway, as I've mentioned, I do actually quite like the syntax of |
This seems like my explanation might not have been as clear as I had hoped. With the attribute provided in the trait definition, all bounds using The goal is to replace complexity at use sites - new syntax and imo inconsistent behavior - with complexity at the definition of the trait. By forcing the trait definition to provide a name for the return type of |
Thanks @lcnr for the feedback. I'll add some notes to the tracking issue and we can carry out further discussion going forward. As I noted above, I don't see these concerns as a reason to block this PR from landing per se, but I definitely think we should dig into them further before authoring any RFCs. (For now, I've linked to the comment from the tracking issue.) |
The final comment period, with a disposition to merge, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. This will be merged soon. |
@bors r=eholk |
☀️ Test successful - checks-actions |
Finished benchmarking commit (7402519): comparison URL. Overall result: ✅ improvements - no action needed@rustbot label: -perf-regression Instruction countThis is a highly reliable metric that was used to determine the overall result at the top of this comment.
Max RSS (memory usage)ResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesThis benchmark run did not return any relevant results for this metric. |
Initial support for return type notation (RTN) See: https://smallcultfollowing.com/babysteps/blog/2023/02/13/return-type-notation-send-bounds-part-2/ 1. Only supports `T: Trait<method(): Send>` style bounds, not `<T as Trait>::method(): Send`. Checking validity and injecting an implicit binder for all of the late-bound method generics is harder to do for the latter. * I'd add this in a follow-up. 3. ~Doesn't support RTN in general type position, i.e. no `let x: <T as Trait>::method() = ...`~ * I don't think we actually want this. 5. Doesn't add syntax for "eliding" the function args -- i.e. for now, we write `method(): Send` instead of `method(..): Send`. * May be a hazard if we try to add it in the future. I'll probably add it in a follow-up later, with a structured suggestion to change `method()` to `method(..)` once we add it. 7. ~I'm not in love with the feature gate name 😺~ * I renamed it to `return_type_notation` ✔️ Follow-up PRs will probably add support for `where T::method(): Send` bounds. I'm not sure if we ever want to support return-type-notation in arbitrary type positions. I may also make the bounds require `..` in the args list later. r? `@ghost`
I wonder if a more discoverable and comfortable syntax for this idea would be the An example then would be: trait SomeTrait {
async fn some_func()
}
impl<T> SomeStruct<T>
where
T: SomeTrait,
ReturnType<T::some_func>: SomeBound,
{
} I think it would be usable in all the same places as If we want to indicate these are not regular generic types, something like |
@maboesanman That's an interesting idea, and I can imagine that something like that might someday be "non-magically" implementable via generic type alias syntax. Also, I believe the right place for further discussion is the tracking issue. |
See: https://smallcultfollowing.com/babysteps/blog/2023/02/13/return-type-notation-send-bounds-part-2/
T: Trait<method(): Send>
style bounds, not<T as Trait>::method(): Send
. Checking validity and injecting an implicit binder for all of the late-bound method generics is harder to do for the latter.Doesn't support RTN in general type position, i.e. nolet x: <T as Trait>::method() = ...
method(): Send
instead ofmethod(..): Send
.method()
tomethod(..)
once we add it.I'm not in love with the feature gate name 😺return_type_notation
✔️Follow-up PRs will probably add support for
where T::method(): Send
bounds. I'm not sure if we ever want to support return-type-notation in arbitrary type positions. I may also make the bounds require..
in the args list later.r? @ghost