You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Syntax for precise capturing: impl Trait + use<..> #125836
For precise capturing (#123432), we need to decide which syntax to adopt.
The original two, left as an open question in the RFC, were:
impl use<..> Trait
This syntax is used throughout the RFC.
use<..> impl Trait
This syntax is the worthy challenger.
(See the alternatives section in the RFC for a detailed comparative analysis of these options. In particular, so as to reduce duplication, please read that section carefully before commenting here.)
However, in the design meeting on 2024-06-05, as described below, we settled on placing use<..> within the list of bounds, e.g.:
fnfoo<'a>() -> implSized + use<'a> {}
This issue is to track the resolution of the open question on syntax left in the RFC.
The conclusion of the team is that we'll make use<..> a bound. That is, we'll support impl use<..> + Trait, impl Trait + use<..>, etc.
For now, we will support at most one such bound in a list of bounds, and semantically we'll only support these bounds in the item bounds of RPIT-like impl Trait opaque types (i.e., in the places discussed in the RFC).
We were interested in later extending this so that it could be used in the bounds on associated types and with dyn. This syntactic choice is the most scalable in that way.
For RPITIT (i.e. within trait definitions), we defer to implementation work and to stabilization whether to support it or to leave this work to later, e.g. to the point at which we support use<..> in the bounds on associated types.
Note, if we were later to support multiple use<..> items in a list of bounds, that use<T> + use<U> would represent a union, and so use<T> + use<U> would not be equivalent to use<T, U>.
If the bounds of the opaque type reference generics that are not present in the use<..>, that's an error of course, and a machine-applicable fix seems possible and desirable here.
We found the idea of this being a bound surprisingly appealing, and people liked that this choice allows for putting + use<..> at the end of a list of bounds. Doing it this way also means we don't need to migrate the ty macro matcher fragment specifier.
Thanks to @joshtriplett for proposing this appealing option. We resolved a difficult choice between two good options by finding an even better one. That's Rust at its best.
Reacted by Xingcan LAN, Tamme Schichler, Liigo Zhuang, Josh Triplett and George Moschovitis
Reacted by Josh Triplett, George Moschovitis and Michael Färber
changed the title [-]Decide for precise capturing: `impl use<..> Trait` vs `use<..> impl Trait`[/-][+]Syntax for precise capturing: `impl Trait + use<..>`[/+]on Jun 19, 2024
Reopening to formally propose FCP on the above change. I think it is a significant enough delta from the RFC that we would be better off doing an FCP and documenting the rationale now, instead of at stabilization time.
This FCP resolves the unresolved question in the RFC about syntax.
Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!
cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns.
See this document for info about what commands tagged team members can give me.
I don't know what our official policy is, but @traviscross , would you mind updating the description to reflect the new proposal from #125836 (comment) ?
(Or I guess even just making the line of the description be a link to that comment...)
However, in Edition 2021 and lower, the default is to capture only some things. How does use<> work with this? There's a few options:
use<> overrides the default capture list. Therefore it can either remove or add variables to the capture list. Then, it's no longer true that use<> always restricts the hidden type, so it doesn't make sense to add a bound.
use<> only further restricts the default capture list. I find this a bit unfortunate because it means you'll still need the + Captures<'a> hack to add a lifetime capture.
use<> is entirely disallowed in Edition 2021 and lower. This is also unfortunate, and IIUC the aim is to add new features to all editions if possible, and it feels like in this case it should be.
Neither is particularly great
I think this is possibly the strongest argument against use<> as a bound, but I'm personally okay with saying that use<> overrides the default capture list in all editions, therefore it makes slightly less sense to conceptualize it as a bound in earlier editions. This is based on the ideas of joint behavior across editions and that editions are meant to be adopted, so while we prefer to have language features work the same across all editions where possible, we're also okay with only delivering the best possible experience in later editions.
Reacted by Travis Cross, Xingcan LAN, Michael Goulet and João Marcos
For unions of use<>, as per the example given: use<T> + use<U>, could we not take inspiration from other languages by using the pipe operator? I feel use<T | U> makes more sense.
A flavor of bound that loosens restrictions and cannot be mentioned more than once is not unprecedented. ?Trait bounds do exactly that.
// Compiles (no warning)fnexample0<'a>() -> &'a(implDebug + ?Sized){""}// Compiles (warning: relaxing a default bound only does something for `?Sized`)fnexample1<'a>() -> &'a(implDebug + ?Display){&0}// Fails: error[E0203]: type parameter has more than one relaxed default bound,// only one is supportedfnexample2<'a>() -> &'a(implDebug + ?Display + ?Sized){""}
I'm not sure if anyone has raised this, but maybe this error reporting could be improved to also say "consider adding + use<> rather than just complaining about an immutable borrow?
error[E0502]: cannot borrow `data` as mutable because it is also borrowedasimmutable
--> src/main.rs:6:5
|
5 | let mut i = indices(&data);
| ----- immutable borrow occurs here
6 | data.push(4);
| ^^^^^^^^^^^^ mutable borrow occurs here
7 | i.next();
| - immutable borrow later used here
Instead,
error[E0502]: cannot borrow `data` as mutable because it is also borrowedasimmutable
--> src/main.rs:6:5
|
5 | let mut i = indices(&data);
| ----- immutable borrow occurs here
6 | data.push(4);
| ^^^^^^^^^^^^ mutable borrow occurs here
7 | i.next();
| - immutable borrow later used here
10 | fn indices<T>(11 | slice:&[T],12 | ) -> implIterator<Item = usize> + use<> {
| ----- `implTrait` must mention all type parameters in scope in `use<...>`
Activity
traviscross commentedon Jun 6, 2024
We discussed this in the lang design meeting today:
impl use<..> Traitvsuse<..> impl Traitlang-team#269The conclusion of the team is that we'll make
use<..>a bound. That is, we'll supportimpl use<..> + Trait,impl Trait + use<..>, etc.For now, we will support at most one such bound in a list of bounds, and semantically we'll only support these bounds in the item bounds of RPIT-like
impl Traitopaque types (i.e., in the places discussed in the RFC).We were interested in later extending this so that it could be used in the bounds on associated types and with
dyn. This syntactic choice is the most scalable in that way.For RPITIT (i.e. within trait definitions), we defer to implementation work and to stabilization whether to support it or to leave this work to later, e.g. to the point at which we support
use<..>in the bounds on associated types.Note, if we were later to support multiple
use<..>items in a list of bounds, thatuse<T> + use<U>would represent a union, and souse<T> + use<U>would not be equivalent touse<T, U>.If the bounds of the opaque type reference generics that are not present in the
use<..>, that's an error of course, and a machine-applicable fix seems possible and desirable here.We found the idea of this being a bound surprisingly appealing, and people liked that this choice allows for putting
+ use<..>at the end of a list of bounds. Doing it this way also means we don't need to migrate thetymacro matcher fragment specifier.Thanks to @joshtriplett for proposing this appealing option. We resolved a difficult choice between two good options by finding an even better one. That's Rust at its best.
Auto merge of rust-lang#126049 - compiler-errors:rework-use, r=oli-obk
[-]Decide for precise capturing: `impl use<..> Trait` vs `use<..> impl Trait`[/-][+]Syntax for precise capturing: `impl Trait + use<..>`[/+]tmandry commentedon Jun 19, 2024
Reopening to formally propose FCP on the above change. I think it is a significant enough delta from the RFC that we would be better off doing an FCP and documenting the rationale now, instead of at stabilization time.
This FCP resolves the unresolved question in the RFC about syntax.
@rfcbot fcp merge
rfcbot commentedon Jun 19, 2024
Team member @tmandry has proposed to merge this. The next step is review by the rest of the tagged team members:
No concerns currently listed.
Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!
cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns.
See this document for info about what commands tagged team members can give me.
pnkfelix commentedon Jun 19, 2024
I don't know what our official policy is, but @traviscross , would you mind updating the description to reflect the new proposal from #125836 (comment) ?
(Or I guess even just making the line of the description be a link to that comment...)
8 remaining items
tmandry commentedon Jun 20, 2024
I think this is possibly the strongest argument against
use<>as a bound, but I'm personally okay with saying thatuse<>overrides the default capture list in all editions, therefore it makes slightly less sense to conceptualize it as a bound in earlier editions. This is based on the ideas of joint behavior across editions and that editions are meant to be adopted, so while we prefer to have language features work the same across all editions where possible, we're also okay with only delivering the best possible experience in later editions.Auto merge of #126049 - compiler-errors:rework-use, r=oli-obk
marziply commentedon Jun 29, 2024
For unions of
use<>, as per the example given:use<T> + use<U>, could we not take inspiration from other languages by using the pipe operator? I feeluse<T | U>makes more sense.rfcbot commentedon Jun 29, 2024
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.
Auto merge of rust-lang#127672 - compiler-errors:precise-capturing, r…
Auto merge of rust-lang#127672 - compiler-errors:precise-capturing, r…
Auto merge of #127672 - compiler-errors:precise-capturing, r=spastorino
QuineDot commentedon Aug 26, 2024
A flavor of bound that loosens restrictions and cannot be mentioned more than once is not unprecedented.
?Traitbounds do exactly that.Playground.
bsodmike commentedon Sep 8, 2024
I'm not sure if anyone has raised this, but maybe this error reporting could be improved to also say "consider adding
+ use<>rather than just complaining about an immutable borrow?Instead,