Skip to content

Implement if let #16741

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

Closed
wants to merge 7 commits into from
Closed

Implement if let #16741

wants to merge 7 commits into from

Conversation

lilyball
Copy link
Contributor

Implement the new desugaring if let syntax.

Fixes #16779.

@lilyball
Copy link
Contributor Author

One thing to note is the error message for having a non-refutable pattern is kind of confusing:

fn main() {
    if let a = 1i {
        println!("irrefutable pattern");
    }
}
iflet.rs:2:5: 4:6 error: unreachable pattern [E0001] (pass `--explain E0001` to see a detailed explanation)
iflet.rs:2     if let a = 1i {
iflet.rs:3         println!("irrefutable pattern");
iflet.rs:4     }

This could perhaps be fixed by attaching an attribute to the desugared match that is used by the "unreachable pattern" to produce an error message tailored to if let. Of course, we didn't do anything like that for for, which also had the potential of being confusing (notably, if Some/None were not in scope), but it might be worth doing in this case.

@lilyball
Copy link
Contributor Author

Another option is to put an attribute on the generated _ => () match arm that says "don't throw an error if this is unrreachable", but I would prefer to keep irrefutable if lets as an error and make the message better instead.

@lilyball
Copy link
Contributor Author

I implemented the attribute approach, and then replaced it with an approach based on expn_info. I prefer the expn_info approach, but I left the attribute approach commit intact in case anyone wants to look at it.

Prior to merging, the discarded approach (currently the attribute approach) should be removed from the commit list.

@huonw
Copy link
Member

huonw commented Aug 26, 2014

If we do take this approach, I would mildly prefer that ExprMatch just has an extra field:

enum MatchSource {
    MatchNormal,
    MatchIfLetDesugar
}

@lilyball
Copy link
Contributor Author

@huonw At first glance, it looks like that would require updating at least 19 locations across librustc and libsyntax just to account for the new parameter, and that's without actually even using it.

It's certainly doable, but is it really appropriate? Do clients of ExprMatch really need to care that it was produced from a desugared if let? To me, the desugaring is basically equivalent to macro expansion, and expn_info seems like perhaps the correct place to record that information.

Using expn_info like this is also future-compatible with any other desugarings that we might add in the future, such as the while let that I suggested today.

@huonw
Copy link
Member

huonw commented Aug 26, 2014

I have a feeling that some/most of those could be changed to give error diagnostics specific to if let, rather than match (even if it's just changing the word match to if let in the output text).

@lilyball
Copy link
Contributor Author

Most of what? Those aren't errors I was talking about. Those were just uses of the token ExprMatch.

@huonw
Copy link
Member

huonw commented Aug 26, 2014

Those were just uses of the token ExprMatch.

They are 'just' uses that lead to compiler diagnostics, e.g.

They should not be talking about match when the problem was created with an if let. Furthermore, the majority of the uses of ExprMatch have (..), and I don't imagine if let will need special handling, so they can be left entirely unchanged.

@lilyball
Copy link
Contributor Author

@huonw Ok I pushed a commit that uses enum MatchSource.

@lilyball
Copy link
Contributor Author

As before, this commit obsoletes the two previous commits, but I haven't removed them, for comparison's sake. They will be removed if we go ahead with enum MatchSource.

@alexcrichton alexcrichton mentioned this pull request Aug 27, 2014
@lilyball
Copy link
Contributor Author

I've added the feature gate. At this point we just need to decide which approach to use for error reporting. Since it's already implemented, I'm in favor of @huonw's MatchSource approach, though I think the expr_info approach is fine as well (but the unnecessary parens lint would need to be updated for that).

@nikomatsakis Since you seemed to care strongly that if let be an AST rewrite, do you have any opinion on the error reporting approach? You can see all 3 approaches implemented in the commits on this PR.

@lilyball lilyball changed the title [PENDING RFC APPROVAL] Implement if let Implement if let Aug 27, 2014
@nikomatsakis
Copy link
Contributor

@huonw's suggestion is the same as what I had in mind.

Modify ast::ExprMatch to include a new value of type ast::MatchSource,
making it easy to tell whether the match was written literally or
produced via desugaring. This allows us to customize error messages
appropriately.
When an `if let` translates into a `match` with more than two arms, we
don't want to print multiple "irrefutable if-let pattern" errors.
@lilyball
Copy link
Contributor Author

Force-pushed to remove the rejected approaches from commit history.

r?

@@ -2457,6 +2457,8 @@ The currently implemented features of the reference compiler are:
whether this will continue as a feature or not. For these reasons,
the glob import statement has been hidden behind this feature flag.

* `if_let` - Allows use of the `if let` desugaring syntax.
Copy link
Member

Choose a reason for hiding this comment

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

replace 'desugaring syntax' with 'feature' or 'statement' - the fact that it is implemented with desugaring is not relevant to the user

if self.is_keyword(kw) {
self.bump();
true
} else { false }
Copy link
Member

Choose a reason for hiding this comment

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

} else {
    false
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We actually have no style guidelines here, and some minor precedence for making very short else expressions into one-liners, such as https://github.com/rust-lang/rust/blob/master/src/librustdoc/html/render.rs#L885

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That said, I will make the change, because this isn't something worth fighting for.

@nrc
Copy link
Member

nrc commented Aug 28, 2014

Looks good! r=me with the nits addressed

@lilyball
Copy link
Contributor Author

@nick29581 Thanks! I'll push the updated version as soon as I make sure it works locally

@lilyball
Copy link
Contributor Author

Same weird error three times in a row. It's looking less and less like a weird ephemeral error. But this PR has nothing to do with any of those run-pass-fulldeps issues, or with the plugin registry.

@nrc
Copy link
Member

nrc commented Sep 1, 2014

A belated review comment - we should add if let to the docs, at the very least to the reference manual.

@kballard If you are going to add stuff to this PR for the error, could you do that here. Otherwise, could you file an issue for it please?

@lilyball
Copy link
Contributor Author

lilyball commented Sep 2, 2014

@nick29581 Good point. I'm still trying to figure out what the heck is going on with the errors though.

@steveklabnik
Copy link
Member

This needs a rebase.

@lilyball
Copy link
Contributor Author

Yes it does. I've been really busy lately, but I'm going to try and get back to this soon. Even before the rebase it was still having weird issues though, which is what was giving me problems in the first place.

@ghost
Copy link

ghost commented Sep 29, 2014

I chatted with @kballard on IRC and we agreed I could pick this up. I'll open a new PR.

@ghost ghost mentioned this pull request Sep 29, 2014
@alexcrichton
Copy link
Member

Closing in favor of #17634, thanks @jakub-!

bors added a commit that referenced this pull request Sep 30, 2014
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.

Implement if-let
7 participants