diff options
Diffstat (limited to 'compiler/rustc_parse/src/parser/ty.rs')
| -rw-r--r-- | compiler/rustc_parse/src/parser/ty.rs | 55 |
1 files changed, 49 insertions, 6 deletions
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 1eeb11a09fe..7096b201f84 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -1,4 +1,4 @@ -use super::{Parser, PathStyle, TokenType, Trailing}; +use super::{Parser, PathStyle, SeqSep, TokenType, Trailing}; use crate::errors::{ self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType, @@ -14,7 +14,7 @@ use rustc_ast::util::case::Case; use rustc_ast::{ self as ast, BareFnTy, BoundAsyncness, BoundConstness, BoundPolarity, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef, - TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, DUMMY_NODE_ID, + PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, DUMMY_NODE_ID, }; use rustc_errors::{Applicability, PResult}; use rustc_span::symbol::{kw, sym, Ident}; @@ -316,7 +316,7 @@ impl<'a> Parser<'a> { TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn) } (TyKind::TraitObject(bounds, _), kw::Impl) => { - TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds) + TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds, None) } _ => return Err(err), }; @@ -655,7 +655,6 @@ impl<'a> Parser<'a> { /// Parses an `impl B0 + ... + Bn` type. fn parse_impl_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> { - // Always parse bounds greedily for better error recovery. if self.token.is_lifetime() { self.look_ahead(1, |t| { if let token::Ident(sym, _) = t.kind { @@ -669,9 +668,53 @@ impl<'a> Parser<'a> { } }) } + + // parse precise captures, if any. This is `use<'lt, 'lt, P, P>`; a list of + // lifetimes and ident params (including SelfUpper). These are validated later + // for order, duplication, and whether they actually reference params. + let precise_capturing = if self.eat_keyword(kw::Use) { + let use_span = self.prev_token.span; + self.psess.gated_spans.gate(sym::precise_capturing, use_span); + let args = self.parse_precise_capturing_args()?; + Some(P((args, use_span))) + } else { + None + }; + + // Always parse bounds greedily for better error recovery. let bounds = self.parse_generic_bounds()?; + *impl_dyn_multi = bounds.len() > 1 || self.prev_token.kind == TokenKind::BinOp(token::Plus); - Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds)) + + Ok(TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds, precise_capturing)) + } + + fn parse_precise_capturing_args(&mut self) -> PResult<'a, ThinVec<PreciseCapturingArg>> { + Ok(self + .parse_unspanned_seq( + &TokenKind::Lt, + &TokenKind::Gt, + SeqSep::trailing_allowed(token::Comma), + |self_| { + if self_.check_keyword(kw::SelfUpper) { + self_.bump(); + Ok(PreciseCapturingArg::Arg( + ast::Path::from_ident(self_.prev_token.ident().unwrap().0), + DUMMY_NODE_ID, + )) + } else if self_.check_ident() { + Ok(PreciseCapturingArg::Arg( + ast::Path::from_ident(self_.parse_ident()?), + DUMMY_NODE_ID, + )) + } else if self_.check_lifetime() { + Ok(PreciseCapturingArg::Lifetime(self_.expect_lifetime())) + } else { + self_.unexpected_any() + } + }, + )? + .0) } /// Is a `dyn B0 + ... + Bn` type allowed here? @@ -957,7 +1000,7 @@ impl<'a> Parser<'a> { Applicability::MaybeIncorrect, ) } - TyKind::ImplTrait(_, bounds) + TyKind::ImplTrait(_, bounds, None) if let [GenericBound::Trait(tr, ..), ..] = bounds.as_slice() => { ( |
