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

implement the ? operator #31954

Merged
merged 2 commits into from
Mar 8, 2016
Merged

implement the ? operator #31954

merged 2 commits into from
Mar 8, 2016

Conversation

japaric
Copy link
Member

@japaric japaric commented Feb 28, 2016

The ? postfix operator is sugar equivalent to the try! macro, but is more amenable to chaining:
File::open("foo")?.metadata()?.is_dir().

? is accepted on any expression that can return a Result, e.g. x()?, y!()?, {z}?,
(w)?, etc. And binds more tightly than unary operators, e.g. !x? is parsed as !(x?).

cc #31436


cc @aturon @eddyb

@rust-highfive
Copy link
Collaborator

r? @arielb1

(rust_highfive has picked a reviewer for you, use r? to override)

expr_call(lctx, e.span, err_ctor, hir_vec![from_expr], None)
};
let err_pat = pat_err(lctx, e.span, pat_ident(lctx, e.span, err_ident));
let ret_expr = expr(lctx, e.span, hir::Expr_::ExprRet(Some(err_expr)), None);
Copy link
Contributor

Choose a reason for hiding this comment

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

this line is too long for make tidy

@durka
Copy link
Contributor

durka commented Feb 29, 2016

Needs a feature gate, right?

@japaric
Copy link
Member Author

japaric commented Feb 29, 2016

? is now behind a feature gate.

@brson
Copy link
Contributor

brson commented Feb 29, 2016

🎉

@brson
Copy link
Contributor

brson commented Feb 29, 2016

It might be useful to have tests of what happens when the try expansion fails to resolve. Is it nice? Hideous?

@brson
Copy link
Contributor

brson commented Feb 29, 2016

Here's the try test case. I think it looks nice. The ? really gets out of the way so you don't notice the error handling.

@seanmonstar
Copy link
Contributor

The RFC claims this feature flag should be question_mark. https://github.com/rust-lang/rfcs/blob/master/text/0243-trait-based-exception-handling.md

@japaric
Copy link
Member Author

japaric commented Mar 1, 2016

It might be useful to have tests of what happens when the try expansion fails to resolve. Is it nice? Hideous?

I don't have a build at hand, but the error message should be similar to the one for unresolved for loops. The one for for loops looks like this:

#![feature(no_core)]
#![no_core]

fn main() {
    for x in xs {}
}
$ rustc for.rs
for.rs:5:14: 5:16 help: run `rustc --explain E0425` to see a detailed explanation
for.rs:5:5: 5:9 error: failed to resolve. Maybe a missing `extern crate iter`? [E0433]
for.rs:5     for x in xs {}
             ^~~~
for.rs:5:5: 5:9 help: run `rustc --explain E0433` to see a detailed explanation
for.rs:5:5: 5:19 error: unresolved name `iter::IntoIterator::into_iter` [E0425]
for.rs:5     for x in xs {}
             ^~~~~~~~~~~~~~
for.rs:5:5: 5:19 help: run `rustc --explain E0425` to see a detailed explanation
for.rs:5:5: 5:9 error: failed to resolve. Maybe a missing `extern crate iter`? [E0433]
for.rs:5     for x in xs {}
             ^~~~
for.rs:5:5: 5:9 help: run `rustc --explain E0433` to see a detailed explanation
for.rs:5:5: 5:19 error: unresolved name `iter::Iterator::next` [E0425]
for.rs:5     for x in xs {}
             ^~~~~~~~~~~~~~
for.rs:5:5: 5:19 help: run `rustc --explain E0425` to see a detailed explanation
for.rs:5:5: 5:19 error: unresolved enum variant, struct or const `Some` [E0419]
for.rs:5     for x in xs {}
             ^~~~~~~~~~~~~~
for.rs:5:5: 5:19 help: run `rustc --explain E0419` to see a detailed explanation
for.rs:5:5: 5:19 error: unresolved enum variant, struct or const `None` [E0419]
for.rs:5     for x in xs {}
             ^~~~~~~~~~~~~~

@seanmonstar will push a commit renaming the feature gate in a bit.

@nikomatsakis
Copy link
Contributor

r? @nikomatsakis

(stealing review)

@rust-highfive rust-highfive assigned nikomatsakis and unassigned arielb1 Mar 4, 2016
@nikomatsakis
Copy link
Contributor

So first review done, comments:

  • Move parsing code into parse_dot_or_call_expr_with_ instead
  • Move feature-gate code into PostExpansionVisitor
  • Feels like there could/should be some negative tests, but I'm not sure precisely what :) maybe not needed

(I'll take another look afterwards.)

@japaric
Copy link
Member Author

japaric commented Mar 6, 2016

Move parsing code into parse_dot_or_call_expr_with_ instead
Move feature-gate code into PostExpansionVisitor

Done. The impl looks simpler now. :-)

Feels like there could/should be some negative tests, but I'm not sure precisely what :) maybe not needed

You mean like checking that ExprKind::Try(ExprKind::Binary) is never created?

This seems to be roughly what we do elsewhere -- but do we need to do anything to make hygiene work out for us? Can we make a test where the context defines const val: u32 = 0 or something, just to make sure that the name val here is always a binding and does not conflict with this in-scope constant?

I've added a test for this.

@bors
Copy link
Contributor

bors commented Mar 6, 2016

☔ The latest upstream changes (presumably #30884) made this pull request unmergeable. Please resolve the merge conflicts.

@japaric
Copy link
Member Author

japaric commented Mar 6, 2016

☔ The latest upstream changes (presumably #30884) made this pull request unmergeable. Please resolve the merge conflicts.

Will rebase after @nikomatsakis takes a second look :-).

@nikomatsakis
Copy link
Contributor

@japaric

The changes look great. r=me, feel free to rebase. :)

You mean like checking that ExprKind::Try(ExprKind::Binary) is never created?

No, I meant some kind of test that a + b? parses as expected, but it doesn't seem necessary now with the newer code.

The `?` postfix operator is sugar equivalent to the try! macro, but is more amenable to chaining:
`File::open("foo")?.metadata()?.is_dir()`.

`?` is accepted on any *expression* that can return a `Result`, e.g. `x()?`, `y!()?`, `{z}?`,
`(w)?`, etc. And binds more tightly than unary operators, e.g. `!x?` is parsed as `!(x?)`.

cc rust-lang#31436
@japaric
Copy link
Member Author

japaric commented Mar 7, 2016

@bors: r=nikomatsakis

@bors
Copy link
Contributor

bors commented Mar 7, 2016

📌 Commit 210dd61 has been approved by nikomatsakis

@bors
Copy link
Contributor

bors commented Mar 7, 2016

⌛ Testing commit 210dd61 with merge fc751a0...

@bors
Copy link
Contributor

bors commented Mar 7, 2016

💔 Test failed - auto-linux-64-opt

@nikomatsakis
Copy link
Contributor

@japaric
Copy link
Member Author

japaric commented Mar 8, 2016

@bors: r=nikomatsakis

@bors
Copy link
Contributor

bors commented Mar 8, 2016

📌 Commit 2de4932 has been approved by nikomatsakis

@bors
Copy link
Contributor

bors commented Mar 8, 2016

⌛ Testing commit 2de4932 with merge 3af60f8...

bors added a commit that referenced this pull request Mar 8, 2016
implement the `?` operator

The `?` postfix operator is sugar equivalent to the try! macro, but is more amenable to chaining:
`File::open("foo")?.metadata()?.is_dir()`.

`?` is accepted on any *expression* that can return a `Result`, e.g. `x()?`, `y!()?`, `{z}?`,
`(w)?`, etc. And binds more tightly than unary operators, e.g. `!x?` is parsed as `!(x?)`.

cc #31436

---

cc @aturon @eddyb
@perlun
Copy link

perlun commented Aug 11, 2017

For the record, this was stabilized as part of 1.13.0, i.e no longer behind a feature gate. I hadn't seen it until now, when I happened to see it being referred to in the docs. 😉 Nice with some more syntactic sugar!

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.

10 participants