diff options
| author | bors <bors@rust-lang.org> | 2016-03-08 01:31:04 -0800 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2016-03-08 01:31:04 -0800 |
| commit | 3af60f831f75ae2632bbfd4c1aa66049ec2d486a (patch) | |
| tree | 211677e1c9a46740ec3fc9cba30c5f7346ad675d /src/libsyntax | |
| parent | a9ffe67f98366c58f13e89851d025e8e063f0bb2 (diff) | |
| parent | 2de4932453a99a19e9033edb47db7a66a612188c (diff) | |
| download | rust-3af60f831f75ae2632bbfd4c1aa66049ec2d486a.tar.gz rust-3af60f831f75ae2632bbfd4c1aa66049ec2d486a.zip | |
Auto merge of #31954 - japaric:rfc243, r=nikomatsakis
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
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 9 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 7 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 3 |
6 files changed, 27 insertions, 2 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 0dbfb2c7be6..342ba60e553 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1022,6 +1022,9 @@ pub enum ExprKind { /// No-op: used solely so we can pretty-print faithfully Paren(P<Expr>), + + /// `expr?` + Try(P<Expr>), } /// The explicit Self type in a "qualified path". The actual diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 23025489142..14a3f93738a 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -245,6 +245,9 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option<u32>, Status // a...b and ...b ("inclusive_range_syntax", "1.7.0", Some(28237), Active), + + // `expr?` + ("question_mark", "1.9.0", Some(31436), Active) ]; // (changing above list without updating src/doc/reference.md makes @cmr sad) @@ -570,6 +573,7 @@ pub struct Features { pub staged_api: bool, pub stmt_expr_attributes: bool, pub deprecated: bool, + pub question_mark: bool, } impl Features { @@ -603,6 +607,7 @@ impl Features { staged_api: false, stmt_expr_attributes: false, deprecated: false, + question_mark: false, } } } @@ -1001,6 +1006,9 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { e.span, "inclusive range syntax is experimental"); } + ast::ExprKind::Try(..) => { + self.gate_feature("question_mark", e.span, "the `?` operator is not stable"); + } _ => {} } visit::walk_expr(self, e); @@ -1203,6 +1211,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &Handler, staged_api: cx.has_feature("staged_api"), stmt_expr_attributes: cx.has_feature("stmt_expr_attributes"), deprecated: cx.has_feature("deprecated"), + question_mark: cx.has_feature("question_mark"), } } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 591c1295d66..9056103d300 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1332,7 +1332,8 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu fields.move_map(|x| folder.fold_field(x)), maybe_expr.map(|x| folder.fold_expr(x))) }, - ExprKind::Paren(ex) => ExprKind::Paren(folder.fold_expr(ex)) + ExprKind::Paren(ex) => ExprKind::Paren(folder.fold_expr(ex)), + ExprKind::Try(ex) => ExprKind::Try(folder.fold_expr(ex)), }, span: folder.new_span(span), attrs: attrs.map_thin_attrs(|v| fold_attrs(v, folder)), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d9714cc1e25..53b53415429 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2534,6 +2534,12 @@ impl<'a> Parser<'a> { let mut e = e0; let mut hi; loop { + // expr? + while self.eat(&token::Question) { + let hi = self.span.hi; + e = self.mk_expr(lo, hi, ExprKind::Try(e), None); + } + // expr.f if self.eat(&token::Dot) { match self.token { @@ -2907,7 +2913,6 @@ impl<'a> Parser<'a> { } }; - if self.expr_is_complete(&lhs) { // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071 return Ok(lhs); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 55c1af44cab..2cfed1f82f7 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2277,6 +2277,10 @@ impl<'a> State<'a> { try!(self.print_inner_attributes_inline(attrs)); try!(self.print_expr(&e)); try!(self.pclose()); + }, + ast::ExprKind::Try(ref e) => { + try!(self.print_expr(e)); + try!(word(&mut self.s, "?")) } } try!(self.ann.post(self, NodeExpr(expr))); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 73ad488e55c..25aee09e26c 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -793,6 +793,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_expr(&output.expr) } } + ExprKind::Try(ref subexpression) => { + visitor.visit_expr(subexpression) + } } visitor.visit_expr_post(expression) |
