diff options
| author | bors <bors@rust-lang.org> | 2019-05-02 02:01:31 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-05-02 02:01:31 +0000 |
| commit | 767f59462663fbc55a69d39fc5e1f7f83b6fb37d (patch) | |
| tree | 895cfb402b31011b55559d0acf4cdc5d34326eec /src/libsyntax/parse/parser.rs | |
| parent | ea68bee369c9ebc0de35abcd39211fa0d4f9c84f (diff) | |
| parent | 4ff12347d994d5c85cab250cedf223d9d0db8973 (diff) | |
| download | rust-767f59462663fbc55a69d39fc5e1f7f83b6fb37d.tar.gz rust-767f59462663fbc55a69d39fc5e1f7f83b6fb37d.zip | |
Auto merge of #60460 - Centril:rollup-gz5bc8i, r=Centril
Rollup of 7 pull requests Successful merges: - #59634 (Added an explanation for the E0704 error.) - #60348 (move some functions from parser.rs to diagostics.rs) - #60385 (Emit metadata files earlier) - #60428 (Refactor `eval_body_using_ecx` so that it doesn't need to query for MIR) - #60437 (Ensure that drop order of `async fn` matches `fn` and that users cannot refer to generated arguments.) - #60439 (doc: Warn about possible zombie apocalypse) - #60452 (Remove Context and ContextKind) Failed merges: r? @ghost
Diffstat (limited to 'src/libsyntax/parse/parser.rs')
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 230 |
1 files changed, 53 insertions, 177 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 8efe84cdf01..f70acb3e7da 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -189,41 +189,6 @@ enum PrevTokenKind { Other, } -trait RecoverQPath: Sized + 'static { - const PATH_STYLE: PathStyle = PathStyle::Expr; - fn to_ty(&self) -> Option<P<Ty>>; - fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self; -} - -impl RecoverQPath for Ty { - const PATH_STYLE: PathStyle = PathStyle::Type; - fn to_ty(&self) -> Option<P<Ty>> { - Some(P(self.clone())) - } - fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self { - Self { span: path.span, node: TyKind::Path(qself, path), id: ast::DUMMY_NODE_ID } - } -} - -impl RecoverQPath for Pat { - fn to_ty(&self) -> Option<P<Ty>> { - self.to_ty() - } - fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self { - Self { span: path.span, node: PatKind::Path(qself, path), id: ast::DUMMY_NODE_ID } - } -} - -impl RecoverQPath for Expr { - fn to_ty(&self) -> Option<P<Ty>> { - self.to_ty() - } - fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self { - Self { span: path.span, node: ExprKind::Path(qself, path), - attrs: ThinVec::new(), id: ast::DUMMY_NODE_ID } - } -} - /* ident is handled by common.rs */ #[derive(Clone)] @@ -1479,7 +1444,7 @@ impl<'a> Parser<'a> { fn span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) { self.sess.span_diagnostic.span_err(sp, m) } - fn struct_span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> { + crate fn struct_span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> { self.sess.span_diagnostic.struct_span_err(sp, m) } fn struct_span_warn<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> { @@ -1882,99 +1847,6 @@ impl<'a> Parser<'a> { Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None)) } - fn maybe_report_ambiguous_plus(&mut self, allow_plus: bool, impl_dyn_multi: bool, ty: &Ty) { - if !allow_plus && impl_dyn_multi { - let sum_with_parens = format!("({})", pprust::ty_to_string(&ty)); - self.struct_span_err(ty.span, "ambiguous `+` in a type") - .span_suggestion( - ty.span, - "use parentheses to disambiguate", - sum_with_parens, - Applicability::MachineApplicable - ).emit(); - } - } - - fn maybe_recover_from_bad_type_plus(&mut self, allow_plus: bool, ty: &Ty) -> PResult<'a, ()> { - // Do not add `+` to expected tokens. - if !allow_plus || !self.token.is_like_plus() { - return Ok(()) - } - - self.bump(); // `+` - let bounds = self.parse_generic_bounds(None)?; - let sum_span = ty.span.to(self.prev_span); - - let mut err = struct_span_err!(self.sess.span_diagnostic, sum_span, E0178, - "expected a path on the left-hand side of `+`, not `{}`", pprust::ty_to_string(ty)); - - match ty.node { - TyKind::Rptr(ref lifetime, ref mut_ty) => { - let sum_with_parens = pprust::to_string(|s| { - use crate::print::pprust::PrintState; - - s.s.word("&")?; - s.print_opt_lifetime(lifetime)?; - s.print_mutability(mut_ty.mutbl)?; - s.popen()?; - s.print_type(&mut_ty.ty)?; - s.print_type_bounds(" +", &bounds)?; - s.pclose() - }); - err.span_suggestion( - sum_span, - "try adding parentheses", - sum_with_parens, - Applicability::MachineApplicable - ); - } - TyKind::Ptr(..) | TyKind::BareFn(..) => { - err.span_label(sum_span, "perhaps you forgot parentheses?"); - } - _ => { - err.span_label(sum_span, "expected a path"); - }, - } - err.emit(); - Ok(()) - } - - /// Try to recover from associated item paths like `[T]::AssocItem`/`(T, U)::AssocItem`. - /// Attempt to convert the base expression/pattern/type into a type, parse the `::AssocItem` - /// tail, and combine them into a `<Ty>::AssocItem` expression/pattern/type. - fn maybe_recover_from_bad_qpath<T: RecoverQPath>(&mut self, base: P<T>, allow_recovery: bool) - -> PResult<'a, P<T>> { - // Do not add `::` to expected tokens. - if allow_recovery && self.token == token::ModSep { - if let Some(ty) = base.to_ty() { - return self.maybe_recover_from_bad_qpath_stage_2(ty.span, ty); - } - } - Ok(base) - } - - /// Given an already parsed `Ty` parse the `::AssocItem` tail and - /// combine them into a `<Ty>::AssocItem` expression/pattern/type. - fn maybe_recover_from_bad_qpath_stage_2<T: RecoverQPath>(&mut self, ty_span: Span, ty: P<Ty>) - -> PResult<'a, P<T>> { - self.expect(&token::ModSep)?; - - let mut path = ast::Path { segments: Vec::new(), span: syntax_pos::DUMMY_SP }; - self.parse_path_segments(&mut path.segments, T::PATH_STYLE)?; - path.span = ty_span.to(self.prev_span); - - let ty_str = self.sess.source_map().span_to_snippet(ty_span) - .unwrap_or_else(|_| pprust::ty_to_string(&ty)); - self.diagnostic() - .struct_span_err(path.span, "missing angle brackets in associated item path") - .span_suggestion( // this is a best-effort recovery - path.span, "try", format!("<{}>::{}", ty_str, path), Applicability::MaybeIncorrect - ).emit(); - - let path_span = ty_span.shrink_to_hi(); // use an empty path since `position` == 0 - Ok(P(T::recovered(Some(QSelf { ty, path_span, position: 0 }), path))) - } - fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> { let opt_lifetime = if self.check_lifetime() { Some(self.expect_lifetime()) } else { None }; let mutbl = self.parse_mutability(); @@ -2410,7 +2282,7 @@ impl<'a> Parser<'a> { self.parse_path(style) } - fn parse_path_segments(&mut self, + crate fn parse_path_segments(&mut self, segments: &mut Vec<PathSegment>, style: PathStyle) -> PResult<'a, ()> { @@ -5815,7 +5687,8 @@ impl<'a> Parser<'a> { return Ok(bounds); } - fn parse_generic_bounds(&mut self, colon_span: Option<Span>) -> PResult<'a, GenericBounds> { + crate fn parse_generic_bounds(&mut self, + colon_span: Option<Span>) -> PResult<'a, GenericBounds> { self.parse_generic_bounds_common(true, colon_span) } @@ -7352,37 +7225,6 @@ impl<'a> Parser<'a> { } } - fn maybe_consume_incorrect_semicolon(&mut self, items: &[P<Item>]) -> bool { - if self.eat(&token::Semi) { - let mut err = self.struct_span_err(self.prev_span, "expected item, found `;`"); - err.span_suggestion_short( - self.prev_span, - "remove this semicolon", - String::new(), - Applicability::MachineApplicable, - ); - if !items.is_empty() { - let previous_item = &items[items.len()-1]; - let previous_item_kind_name = match previous_item.node { - // say "braced struct" because tuple-structs and - // braceless-empty-struct declarations do take a semicolon - ItemKind::Struct(..) => Some("braced struct"), - ItemKind::Enum(..) => Some("enum"), - ItemKind::Trait(..) => Some("trait"), - ItemKind::Union(..) => Some("union"), - _ => None, - }; - if let Some(name) = previous_item_kind_name { - err.help(&format!("{} declarations are not followed by a semicolon", name)); - } - } - err.emit(); - true - } else { - false - } - } - /// Given a termination token, parses all of the items in a module. fn parse_mod_items(&mut self, term: &token::Token, inner_lo: Span) -> PResult<'a, Mod> { let mut items = vec![]; @@ -8878,13 +8720,39 @@ impl<'a> Parser<'a> { // Construct a name for our temporary argument. let name = format!("__arg{}", index); - let ident = Ident::from_str(&name); + let ident = Ident::from_str(&name).gensym(); + + // Check if this is a ident pattern, if so, we can optimize and avoid adding a + // `let <pat> = __argN;` statement, instead just adding a `let <pat> = <pat>;` + // statement. + let (ident, is_simple_pattern) = match input.pat.node { + PatKind::Ident(_, ident, _) => (ident, true), + _ => (ident, false), + }; // Construct an argument representing `__argN: <ty>` to replace the argument of the - // async function. - let arg = Arg { - ty: input.ty.clone(), - id, + // async function if it isn't a simple pattern. + let arg = if is_simple_pattern { + None + } else { + Some(Arg { + ty: input.ty.clone(), + id, + pat: P(Pat { + id, + node: PatKind::Ident( + BindingMode::ByValue(Mutability::Immutable), ident, None, + ), + span, + }), + source: ArgSource::AsyncFn(input.pat.clone()), + }) + }; + + // Construct a `let __argN = __argN;` statement to insert at the top of the + // async closure. This makes sure that the argument is captured by the closure and + // that the drop order is correct. + let move_local = Local { pat: P(Pat { id, node: PatKind::Ident( @@ -8892,13 +8760,6 @@ impl<'a> Parser<'a> { ), span, }), - source: ArgSource::AsyncFn(input.pat.clone()), - }; - - // Construct a `let <pat> = __argN;` statement to insert at the top of the - // async closure. - let local = P(Local { - pat: input.pat.clone(), // We explicitly do not specify the type for this statement. When the user's // argument type is `impl Trait` then this would require the // `impl_trait_in_bindings` feature to also be present for that same type to @@ -8918,10 +8779,25 @@ impl<'a> Parser<'a> { span, attrs: ThinVec::new(), source: LocalSource::AsyncFn, - }); - let stmt = Stmt { id, node: StmtKind::Local(local), span, }; + }; + + // Construct a `let <pat> = __argN;` statement to insert at the top of the + // async closure if this isn't a simple pattern. + let pat_stmt = if is_simple_pattern { + None + } else { + Some(Stmt { + id, + node: StmtKind::Local(P(Local { + pat: input.pat.clone(), + ..move_local.clone() + })), + span, + }) + }; - arguments.push(AsyncArgument { ident, arg, stmt }); + let move_stmt = Stmt { id, node: StmtKind::Local(P(move_local)), span }; + arguments.push(AsyncArgument { ident, arg, pat_stmt, move_stmt }); } } } |
