diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2015-02-03 15:36:07 -0800 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2015-02-03 20:11:20 -0800 |
| commit | 74f7e0693909a45f9159c6d2ef72b42fcb4f1bac (patch) | |
| tree | 4a275ef4606878200f7a1e7ee57cf9fa1bb75b16 /src/libsyntax/parse/parser.rs | |
| parent | 1d921f557d6d9e509ce0d696d7b2178628989935 (diff) | |
| parent | 8ddcb06b1d021560bfe641c0dbc452a04e80388e (diff) | |
| download | rust-74f7e0693909a45f9159c6d2ef72b42fcb4f1bac.tar.gz rust-74f7e0693909a45f9159c6d2ef72b42fcb4f1bac.zip | |
rollup merge of #21899: nikomatsakis/closure-unify-anyhow
This *almost* completes the job for #16440. The idea is that even if we do not know whether some closure type `C` implements `Fn` or `FnMut` (etc), we still know its argument and return types. So if we see an obligation `C : Fn(_0)`, we can unify `_0` with those argument types while still considering the obligation ambiguous and unsatisfied. This helps to make a lot of progress with type inference even before closure kind inference is done. As part of this PR, the explicit `:` syntax is removed from the AST and completely ignored. We still infer the closure kind based on the expected type if that is available. There are several reasons for this. First, deciding the closure kind earlier is always better, as it allows us to make more progress. Second, this retains a (admittedly obscure) way for users to manually specify the closure kind, which is useful for writing tests if nothing else. Finally, there are still some cases where inference can fail, so it may be useful to have this manual override. (The expectation is that we will eventually revisit an explicit syntax for specifying the closure kind, but it will not be `:` and may be some sort of generalization of the `||` syntax to handle other traits as well.) This commit does not *quite* fix #16640 because a snapshot is still needed to enable the obsolete syntax errors for explicit `&mut:` and friends. r? @eddyb as he reviewed the prior patch in this direction
Diffstat (limited to 'src/libsyntax/parse/parser.rs')
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 62 |
1 files changed, 33 insertions, 29 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index c3182602a4b..2cb265033c3 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -28,8 +28,6 @@ use ast::{ExprLit, ExprLoop, ExprMac, ExprRange}; use ast::{ExprMethodCall, ExprParen, ExprPath, ExprQPath}; use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary}; use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl}; -use ast::{FnClosureKind, FnMutClosureKind}; -use ast::{FnOnceClosureKind}; use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy}; use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic}; use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl, ItemConst}; @@ -57,7 +55,7 @@ use ast::{TyFixedLengthVec, TyBareFn}; use ast::{TyTypeof, TyInfer, TypeMethod}; use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath}; use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq}; -use ast::{TypeImplItem, TypeTraitItem, Typedef, ClosureKind}; +use ast::{TypeImplItem, TypeTraitItem, Typedef,}; use ast::{UnnamedField, UnsafeBlock}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; use ast::{Visibility, WhereClause}; @@ -1139,29 +1137,36 @@ impl<'a> Parser<'a> { TyInfer } - /// Parses an optional closure kind (`&:`, `&mut:`, or `:`). - pub fn parse_optional_closure_kind(&mut self) -> Option<ClosureKind> { - if self.check(&token::BinOp(token::And)) && - self.look_ahead(1, |t| t.is_keyword(keywords::Mut)) && - self.look_ahead(2, |t| *t == token::Colon) { + /// Parses an obsolete closure kind (`&:`, `&mut:`, or `:`). + pub fn parse_obsolete_closure_kind(&mut self) { + // let lo = self.span.lo; + if + self.check(&token::BinOp(token::And)) && + self.look_ahead(1, |t| t.is_keyword(keywords::Mut)) && + self.look_ahead(2, |t| *t == token::Colon) + { self.bump(); self.bump(); self.bump(); - return Some(FnMutClosureKind) - } - - if self.token == token::BinOp(token::And) && - self.look_ahead(1, |t| *t == token::Colon) { + } else if + self.token == token::BinOp(token::And) && + self.look_ahead(1, |t| *t == token::Colon) + { self.bump(); self.bump(); - return Some(FnClosureKind) - } - - if self.eat(&token::Colon) { - return Some(FnOnceClosureKind) + return; + } else if + self.eat(&token::Colon) + { + /* nothing */ + } else { + return; } - return None + // SNAP 474b324 + // Enable these obsolete errors after snapshot: + // let span = mk_sp(lo, self.span.hi); + // self.obsolete(span, ObsoleteSyntax::ClosureKind); } pub fn parse_ty_bare_fn_or_ty_closure(&mut self, lifetime_defs: Vec<LifetimeDef>) -> Ty_ { @@ -3047,7 +3052,7 @@ impl<'a> Parser<'a> { -> P<Expr> { let lo = self.span.lo; - let (decl, optional_closure_kind) = self.parse_fn_block_decl(); + let decl = self.parse_fn_block_decl(); let body = self.parse_expr(); let fakeblock = P(ast::Block { id: ast::DUMMY_NODE_ID, @@ -3060,7 +3065,7 @@ impl<'a> Parser<'a> { self.mk_expr( lo, fakeblock.span.hi, - ExprClosure(capture_clause, optional_closure_kind, decl, fakeblock)) + ExprClosure(capture_clause, decl, fakeblock)) } pub fn parse_else_expr(&mut self) -> P<Expr> { @@ -4529,30 +4534,29 @@ impl<'a> Parser<'a> { } // parse the |arg, arg| header on a lambda - fn parse_fn_block_decl(&mut self) -> (P<FnDecl>, Option<ClosureKind>) { - let (optional_closure_kind, inputs_captures) = { + fn parse_fn_block_decl(&mut self) -> P<FnDecl> { + let inputs_captures = { if self.eat(&token::OrOr) { - (None, Vec::new()) + Vec::new() } else { self.expect(&token::BinOp(token::Or)); - let optional_closure_kind = - self.parse_optional_closure_kind(); + self.parse_obsolete_closure_kind(); let args = self.parse_seq_to_before_end( &token::BinOp(token::Or), seq_sep_trailing_allowed(token::Comma), |p| p.parse_fn_block_arg() ); self.bump(); - (optional_closure_kind, args) + args } }; let output = self.parse_ret_ty(); - (P(FnDecl { + P(FnDecl { inputs: inputs_captures, output: output, variadic: false - }), optional_closure_kind) + }) } /// Parses the `(arg, arg) -> return_type` header on a procedure. |
