-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Tracking Issue for RFC 3137: let-else statements #87335
Comments
This comment has been minimized.
This comment has been minimized.
Is there already someone who wants to implement the RFC? Otherwise I could maybe take a stab at it |
I volunteered on Zulip to implement a while ago and I have a start on it. @Fishrock123 are you still okay with me taking it since you were also interested? |
I'm interested but I'm clueless and pretty busy. I'd say you should just take it. |
An interesting example which I didn't see come up in the RFC text/thread (quick search for let parents: HashMap<u32, u32> = dfs();
let mut curr: u32 = 0;
let mut path: Vec<u32> = Vec::new();
loop {
path.push(curr);
let Some(&curr) = parents.get(curr) else { break }
} Here, Just as an observation, Kotlin-style elvis operator would avoid this issue, as it doesn't require a pattern: let parents: HashMap<u32, u32> = dfs();
let mut curr: u32 = 0;
let mut path: Vec<u32> = Vec::new();
loop {
path.push(curr);
curr = *(parents.get(curr) ?: break);
} |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Hypothetically, we can allow the following (else without let): let parents: HashMap<u32, u32> = dfs();
let mut curr: u32 = 0;
let mut path: Vec<u32> = Vec::new();
loop {
path.push(curr);
Some(&curr) = parents.get(curr) else { break }
} This would be a natural combination of let-else and #71126. While #71126 is still unstable, it might be worth is to think about the interactions between the two. Will the above example just work, or are there any problems with it? |
I also mentioned this in the RFC. Probably no technical limitation but just readability concerns. I think we can safely wait until let-else and destructuring-assignment have matured before expecting them to procreate (forgive me). |
Ah, I seem to have missed that thing about |
Introduce `let...else` Tracking issue: rust-lang#87335 The trickiest part for me was enforcing the diverging else block with clear diagnostics. Perhaps the obvious solution is to expand to `let _: ! = ..`, but I decided against this because, when a "mismatched type" error is found in typeck, there is no way to trace where in the HIR the expected type originated, AFAICT. In order to pass down this information, I believe we should introduce `Expectation::LetElseNever(HirId)` or maybe add `HirId` to `Expectation::HasType`, but I left that as a future enhancement. For now, I simply assert that the block is `!` with a custom `ObligationCauseCode`, and I think this is clear enough, at least to start. The downside here is that the error points at the entire block rather than the specific expression with the wrong type. I left a todo to this effect. Overall, I believe this PR is feature-complete with regard to the RFC.
@joshtriplett #87688 has been merged, can you tick off "implement the RFC"? |
@camsteffen @cjgillot did the implementation answer the "Grammar clarity" question at all? |
See |
My understanding of the state of implementation is:
|
@Fishrock123 cool! Once you've had a chance to test, we should consider moving to feature complete status and writing a blog post as a way to get more feedback. =) |
#89688 is a blocker for a stabilization. Without this fixed, our implementation does not match the behaviour as prescribed by the RFC. |
scale-info v2.4.0 fails to compile with: error[E0658]: `let...else` statements are unstable --> /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/scale-info-2.4.0/src/portable.rs:124:17 | 124 | / let Some(ty) = param.ty() else { 125 | | continue 126 | | }; | |__________________^ | = note: see issue #87335 <rust-lang/rust#87335> for more information Signed-off-by: Sean Young <sean@mess.org>
Compiling with Debian GNU/Linux 12 (bookworm) packages: $ apt-cache madison cargo rustc cargo | 0.66.0+ds1-1 | http://deb.debian.org/debian bookworm/main ppc64el Packages cargo | 0.66.0+ds1-1 | http://deb.debian.org/debian bookworm/main Sources rustc | 1.63.0+dfsg1-2 | http://deb.debian.org/debian bookworm/main ppc64el Packages rustc | 1.63.0+dfsg1-2 | http://deb.debian.org/debian bookworm/main Sources ..., we run into: Compiling generic_format_parser v0.1.0 ([...]/source-gcc/libgrust/libformat_parser/generic_format_parser) error[E0658]: `let...else` statements are unstable --> generic_format_parser/src/lib.rs:994:5 | 994 | / let Some(unescaped) = unescape_string(snippet) else { 995 | | return InputStringKind::NotALiteral; 996 | | }; | |______^ | = note: see issue #87335 <rust-lang/rust#87335> for more information Rewrite backwards, per <https://rust-lang.github.io/rfcs/3137-let-else.html>. libgrust/ * libformat_parser/generic_format_parser/src/lib.rs: Work around 'error[E0658]: `let...else` statements are unstable'.
This is a tracking issue for RFC 3137: let-else statements.
The feature gate for the issue is
#![feature(let_else)]
.About tracking issues
Tracking issues are used to record the overall progress of implementation.
They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions.
A tracking issue is however not meant for large scale discussion, questions, or bug reports about a feature.
Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.
Steps
let...else
#87688)let else
#93628Unresolved Questions
let ... else { ... };
be clear enough to humans in practical code, or will some introducer syntax be desirable?Implementation history
let...else
#87688 implemented let-else.let x: Type = ... else { ... }
)The text was updated successfully, but these errors were encountered: