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

Tracking Issue for RFC 3137: let-else statements #87335

Closed
6 of 7 tasks
joshtriplett opened this issue Jul 21, 2021 · 79 comments · Fixed by #93628
Closed
6 of 7 tasks

Tracking Issue for RFC 3137: let-else statements #87335

joshtriplett opened this issue Jul 21, 2021 · 79 comments · Fixed by #93628
Assignees
Labels
C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC F-let_else Issues related to let-else statements (RFC 3137) S-tracking-impl-incomplete Status: The implementation is incomplete. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@joshtriplett
Copy link
Member

joshtriplett commented Jul 21, 2021

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

Unresolved Questions

  • Readability in practice: Will let ... else { ... }; be clear enough to humans in practical code, or will some introducer syntax be desirable?
  • Conflicts with if-let-chains: Does this conflict too much with the if-let-chains RFC or vice-versa? Neither this feature nor that feature should be stabilized without considering the other.
  • Amount of special cases: Are there too many special-case interactions with other features?
  • Grammar clarity: Does the grammar need to be clarified? This RFC has some slightly unusual grammar requirements.

Implementation history

@joshtriplett joshtriplett added T-lang Relevant to the language team, which will review and decide on the PR/issue. C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC F-let_else Issues related to let-else statements (RFC 3137) labels Jul 21, 2021
@inquisitivecrystal

This comment has been minimized.

@LeSeulArtichaut
Copy link
Contributor

Is there already someone who wants to implement the RFC? Otherwise I could maybe take a stab at it

@camsteffen
Copy link
Contributor

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?

@Fishrock123
Copy link
Contributor

I'm interested but I'm clueless and pretty busy. I'd say you should just take it.

@matklad
Copy link
Member

matklad commented Aug 18, 2021

An interesting example which I didn't see come up in the RFC text/thread (quick search for mut). In today's Rust, let-else won't work for a case of updating variables. An example here is computing a path in a graph after DFS returns a map of parents:

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, let won't re-bind curr, it'll shadow it instead.

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

@joshtriplett

This comment has been minimized.

@matklad

This comment has been minimized.

@matklad
Copy link
Member

matklad commented Aug 18, 2021

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?

@camsteffen
Copy link
Contributor

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).

@Fishrock123
Copy link
Contributor

Fishrock123 commented Aug 18, 2021

Ah, I seem to have missed that thing about destructuring_assignment, yes that seems like a future possibility, with the above mentioned caveats.

bors added a commit to rust-lang-ci/rust that referenced this issue Sep 1, 2021
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.
@Fishrock123
Copy link
Contributor

@joshtriplett #87688 has been merged, can you tick off "implement the RFC"?

@Fishrock123
Copy link
Contributor

@camsteffen @cjgillot did the implementation answer the "Grammar clarity" question at all?

@camsteffen
Copy link
Contributor

camsteffen commented Sep 1, 2021

did the implementation answer the "Grammar clarity" question at all?

See expr_trailing_brace - I think the "slightly unusual grammar requirements" are contained there.

@Fishrock123
Copy link
Contributor

My understanding of the state of implementation is:

@nikomatsakis
Copy link
Contributor

@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. =)

@nagisa
Copy link
Member

nagisa commented Oct 9, 2021

#89688 is a blocker for a stabilization. Without this fixed, our implementation does not match the behaviour as prescribed by the RFC.

@bors bors closed this as completed in 3ad81e0 Sep 17, 2022
seanyoung added a commit to seanyoung/solang that referenced this issue Mar 24, 2023
scale-info v2.4.0 fails to compile with:

 error[E0658]: `let...else` statements are unstable
   --> /Users/runner/.cargo/registry/src/git.luolix.top-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>
hubot pushed a commit to gcc-mirror/gcc that referenced this issue Dec 9, 2024
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'.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC F-let_else Issues related to let-else statements (RFC 3137) S-tracking-impl-incomplete Status: The implementation is incomplete. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
Status: Feature Complete
Development

Successfully merging a pull request may close this issue.