1 use super::{Parser, PathStyle, PrevTokenKind, TokenType}
;
2 use super::item
::ParamCfg
;
4 use crate::{maybe_whole, maybe_recover_from_interpolated_ty_qpath}
;
6 use rustc_errors
::{PResult, Applicability, pluralize}
;
7 use rustc_error_codes
::*;
9 use syntax
::ast
::{self, Ty, TyKind, MutTy, BareFnTy, FunctionRetTy, GenericParam, Lifetime, Ident}
;
10 use syntax
::ast
::{TraitBoundModifier, TraitObjectSyntax, GenericBound, GenericBounds, PolyTraitRef}
;
11 use syntax
::ast
::{Mutability, AnonConst, Mac}
;
12 use syntax
::token
::{self, Token}
;
13 use syntax
::struct_span_fatal
;
14 use syntax_pos
::source_map
::Span
;
15 use syntax_pos
::symbol
::kw
;
17 /// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT<u8, u8>`,
18 /// `IDENT<<u8 as Trait>::AssocTy>`.
20 /// Types can also be of the form `IDENT(u8, u8) -> u8`, however this assumes
21 /// that `IDENT` is not the ident of a fn trait.
22 fn can_continue_type_after_non_fn_ident(t
: &Token
) -> bool
{
23 t
== &token
::ModSep
|| t
== &token
::Lt
||
24 t
== &token
::BinOp(token
::Shl
)
29 pub fn parse_ty(&mut self) -> PResult
<'a
, P
<Ty
>> {
30 self.parse_ty_common(true, true, false)
33 /// Parses a type in restricted contexts where `+` is not permitted.
35 /// Example 1: `&'a TYPE`
36 /// `+` is prohibited to maintain operator priority (P(+) < P(&)).
37 /// Example 2: `value1 as TYPE + value2`
38 /// `+` is prohibited to avoid interactions with expression grammar.
39 pub(super) fn parse_ty_no_plus(&mut self) -> PResult
<'a
, P
<Ty
>> {
40 self.parse_ty_common(false, true, false)
43 /// Parses an optional return type `[ -> TY ]` in a function declaration.
44 pub(super) fn parse_ret_ty(&mut self, allow_plus
: bool
) -> PResult
<'a
, FunctionRetTy
> {
45 if self.eat(&token
::RArrow
) {
46 Ok(FunctionRetTy
::Ty(self.parse_ty_common(allow_plus
, true, false)?
))
48 Ok(FunctionRetTy
::Default(self.token
.span
.shrink_to_lo()))
52 pub(super) fn parse_ty_common(&mut self, allow_plus
: bool
, allow_qpath_recovery
: bool
,
53 allow_c_variadic
: bool
) -> PResult
<'a
, P
<Ty
>> {
54 maybe_recover_from_interpolated_ty_qpath
!(self, allow_qpath_recovery
);
55 maybe_whole
!(self, NtTy
, |x
| x
);
57 let lo
= self.token
.span
;
58 let mut impl_dyn_multi
= false;
59 let kind
= if self.eat(&token
::OpenDelim(token
::Paren
)) {
60 // `(TYPE)` is a parenthesized type.
61 // `(TYPE,)` is a tuple with a single field of type TYPE.
63 let mut last_comma
= false;
64 while self.token
!= token
::CloseDelim(token
::Paren
) {
65 ts
.push(self.parse_ty()?
);
66 if self.eat(&token
::Comma
) {
73 let trailing_plus
= self.prev_token_kind
== PrevTokenKind
::Plus
;
74 self.expect(&token
::CloseDelim(token
::Paren
))?
;
76 if ts
.len() == 1 && !last_comma
{
77 let ty
= ts
.into_iter().nth(0).unwrap().into_inner();
78 let maybe_bounds
= allow_plus
&& self.token
.is_like_plus();
80 // `(TY_BOUND_NOPAREN) + BOUND + ...`.
81 TyKind
::Path(None
, ref path
) if maybe_bounds
=> {
82 self.parse_remaining_bounds(Vec
::new(), path
.clone(), lo
, true)?
84 TyKind
::TraitObject(ref bounds
, TraitObjectSyntax
::None
)
85 if maybe_bounds
&& bounds
.len() == 1 && !trailing_plus
=> {
86 let path
= match bounds
[0] {
87 GenericBound
::Trait(ref pt
, ..) => pt
.trait_ref
.path
.clone(),
88 GenericBound
::Outlives(..) => self.bug("unexpected lifetime bound"),
90 self.parse_remaining_bounds(Vec
::new(), path
, lo
, true)?
93 _
=> TyKind
::Paren(P(ty
))
98 } else if self.eat(&token
::Not
) {
101 } else if self.eat(&token
::BinOp(token
::Star
)) {
103 TyKind
::Ptr(self.parse_ptr()?
)
104 } else if self.eat(&token
::OpenDelim(token
::Bracket
)) {
106 let t
= self.parse_ty()?
;
107 // Parse optional `; EXPR` in `[TYPE; EXPR]`
108 let t
= match self.maybe_parse_fixed_length_of_vec()?
{
109 None
=> TyKind
::Slice(t
),
110 Some(length
) => TyKind
::Array(t
, AnonConst
{
111 id
: ast
::DUMMY_NODE_ID
,
115 self.expect(&token
::CloseDelim(token
::Bracket
))?
;
117 } else if self.check(&token
::BinOp(token
::And
)) || self.check(&token
::AndAnd
) {
120 self.parse_borrowed_pointee()?
121 } else if self.eat_keyword_noexpect(kw
::Typeof
) {
123 // In order to not be ambiguous, the type must be surrounded by parens.
124 self.expect(&token
::OpenDelim(token
::Paren
))?
;
126 id
: ast
::DUMMY_NODE_ID
,
127 value
: self.parse_expr()?
,
129 self.expect(&token
::CloseDelim(token
::Paren
))?
;
131 } else if self.eat_keyword(kw
::Underscore
) {
132 // A type to be inferred `_`
134 } else if self.token_is_bare_fn_keyword() {
135 // Function pointer type
136 self.parse_ty_bare_fn(Vec
::new())?
137 } else if self.check_keyword(kw
::For
) {
138 // Function pointer type or bound list (trait object type) starting with a poly-trait.
139 // `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
140 // `for<'lt> Trait1<'lt> + Trait2 + 'a`
141 let lo
= self.token
.span
;
142 let lifetime_defs
= self.parse_late_bound_lifetime_defs()?
;
143 if self.token_is_bare_fn_keyword() {
144 self.parse_ty_bare_fn(lifetime_defs
)?
146 let path
= self.parse_path(PathStyle
::Type
)?
;
147 let parse_plus
= allow_plus
&& self.check_plus();
148 self.parse_remaining_bounds(lifetime_defs
, path
, lo
, parse_plus
)?
150 } else if self.eat_keyword(kw
::Impl
) {
151 // Always parse bounds greedily for better error recovery.
152 let bounds
= self.parse_generic_bounds(None
)?
;
153 impl_dyn_multi
= bounds
.len() > 1 || self.prev_token_kind
== PrevTokenKind
::Plus
;
154 TyKind
::ImplTrait(ast
::DUMMY_NODE_ID
, bounds
)
155 } else if self.check_keyword(kw
::Dyn
) &&
156 (self.token
.span
.rust_2018() ||
157 self.look_ahead(1, |t
| t
.can_begin_bound() &&
158 !can_continue_type_after_non_fn_ident(t
))) {
159 self.bump(); // `dyn`
160 // Always parse bounds greedily for better error recovery.
161 let bounds
= self.parse_generic_bounds(None
)?
;
162 impl_dyn_multi
= bounds
.len() > 1 || self.prev_token_kind
== PrevTokenKind
::Plus
;
163 TyKind
::TraitObject(bounds
, TraitObjectSyntax
::Dyn
)
164 } else if self.check(&token
::Question
) ||
165 self.check_lifetime() && self.look_ahead(1, |t
| t
.is_like_plus()) {
166 // Bound list (trait object type)
167 TyKind
::TraitObject(self.parse_generic_bounds_common(allow_plus
, None
)?
,
168 TraitObjectSyntax
::None
)
169 } else if self.eat_lt() {
171 let (qself
, path
) = self.parse_qpath(PathStyle
::Type
)?
;
172 TyKind
::Path(Some(qself
), path
)
173 } else if self.token
.is_path_start() {
175 let path
= self.parse_path(PathStyle
::Type
)?
;
176 if self.eat(&token
::Not
) {
177 // Macro invocation in type position
178 let args
= self.parse_mac_args()?
;
182 prior_type_ascription
: self.last_type_ascription
,
186 // Just a type path or bound list (trait object type) starting with a trait.
188 // `Trait1 + Trait2 + 'a`
189 if allow_plus
&& self.check_plus() {
190 self.parse_remaining_bounds(Vec
::new(), path
, lo
, true)?
192 TyKind
::Path(None
, path
)
195 } else if self.check(&token
::DotDotDot
) {
196 if allow_c_variadic
{
197 self.eat(&token
::DotDotDot
);
200 return Err(struct_span_fatal
!(
201 self.sess
.span_diagnostic
,
204 "only foreign functions are allowed to be C-variadic",
208 let msg
= format
!("expected type, found {}", self.this_token_descr());
209 let mut err
= self.fatal(&msg
);
210 err
.span_label(self.token
.span
, "expected type");
211 self.maybe_annotate_with_ascription(&mut err
, true);
215 let span
= lo
.to(self.prev_span
);
216 let ty
= self.mk_ty(span
, kind
);
218 // Try to recover from use of `+` with incorrect priority.
219 self.maybe_report_ambiguous_plus(allow_plus
, impl_dyn_multi
, &ty
);
220 self.maybe_recover_from_bad_type_plus(allow_plus
, &ty
)?
;
221 self.maybe_recover_from_bad_qpath(ty
, allow_qpath_recovery
)
224 fn parse_remaining_bounds(&mut self, generic_params
: Vec
<GenericParam
>, path
: ast
::Path
,
225 lo
: Span
, parse_plus
: bool
) -> PResult
<'a
, TyKind
> {
226 let poly_trait_ref
= PolyTraitRef
::new(generic_params
, path
, lo
.to(self.prev_span
));
227 let mut bounds
= vec
![GenericBound
::Trait(poly_trait_ref
, TraitBoundModifier
::None
)];
229 self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
230 bounds
.append(&mut self.parse_generic_bounds(Some(self.prev_span
))?
);
232 Ok(TyKind
::TraitObject(bounds
, TraitObjectSyntax
::None
))
235 fn parse_ptr(&mut self) -> PResult
<'a
, MutTy
> {
236 let mutbl
= self.parse_const_or_mut().unwrap_or_else(|| {
237 let span
= self.prev_span
;
238 let msg
= "expected mut or const in raw pointer type";
239 self.struct_span_err(span
, msg
)
240 .span_label(span
, msg
)
241 .help("use `*mut T` or `*const T` as appropriate")
243 Mutability
::Immutable
245 let t
= self.parse_ty_no_plus()?
;
246 Ok(MutTy { ty: t, mutbl }
)
249 fn maybe_parse_fixed_length_of_vec(&mut self) -> PResult
<'a
, Option
<P
<ast
::Expr
>>> {
250 if self.eat(&token
::Semi
) {
251 Ok(Some(self.parse_expr()?
))
257 fn parse_borrowed_pointee(&mut self) -> PResult
<'a
, TyKind
> {
258 let opt_lifetime
= if self.check_lifetime() { Some(self.expect_lifetime()) }
else { None }
;
259 let mutbl
= self.parse_mutability();
260 let ty
= self.parse_ty_no_plus()?
;
261 return Ok(TyKind
::Rptr(opt_lifetime
, MutTy { ty, mutbl }
));
264 /// Is the current token one of the keywords that signals a bare function type?
265 fn token_is_bare_fn_keyword(&mut self) -> bool
{
266 self.check_keyword(kw
::Fn
) ||
267 self.check_keyword(kw
::Unsafe
) ||
268 self.check_keyword(kw
::Extern
)
271 /// Parses a `TyKind::BareFn` type.
272 fn parse_ty_bare_fn(&mut self, generic_params
: Vec
<GenericParam
>) -> PResult
<'a
, TyKind
> {
275 [unsafe] [extern "ABI"] fn (S) -> T
285 let unsafety
= self.parse_unsafety();
286 let ext
= self.parse_extern()?
;
287 self.expect_keyword(kw
::Fn
)?
;
289 is_self_allowed
: false,
290 allow_c_variadic
: true,
291 is_name_required
: |_
| false,
293 let decl
= self.parse_fn_decl(cfg
, false)?
;
294 Ok(TyKind
::BareFn(P(BareFnTy
{
302 pub(super) fn parse_generic_bounds(&mut self,
303 colon_span
: Option
<Span
>) -> PResult
<'a
, GenericBounds
> {
304 self.parse_generic_bounds_common(true, colon_span
)
307 /// Parses bounds of a type parameter `BOUND + BOUND + ...`, possibly with trailing `+`.
310 /// BOUND = TY_BOUND | LT_BOUND
311 /// LT_BOUND = LIFETIME (e.g., `'a`)
312 /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN)
313 /// TY_BOUND_NOPAREN = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g., `?for<'a: 'b> m::Trait<'a>`)
315 fn parse_generic_bounds_common(&mut self,
317 colon_span
: Option
<Span
>) -> PResult
<'a
, GenericBounds
> {
318 let mut bounds
= Vec
::new();
319 let mut negative_bounds
= Vec
::new();
320 let mut last_plus_span
= None
;
321 let mut was_negative
= false;
323 // This needs to be synchronized with `TokenKind::can_begin_bound`.
324 let is_bound_start
= self.check_path() || self.check_lifetime() ||
325 self.check(&token
::Not
) || // used for error reporting only
326 self.check(&token
::Question
) ||
327 self.check_keyword(kw
::For
) ||
328 self.check(&token
::OpenDelim(token
::Paren
));
330 let lo
= self.token
.span
;
331 let has_parens
= self.eat(&token
::OpenDelim(token
::Paren
));
332 let inner_lo
= self.token
.span
;
333 let is_negative
= self.eat(&token
::Not
);
334 let question
= if self.eat(&token
::Question
) { Some(self.prev_span) }
else { None }
;
335 if self.token
.is_lifetime() {
336 if let Some(question_span
) = question
{
337 self.span_err(question_span
,
338 "`?` may only modify trait bounds, not lifetime bounds");
340 bounds
.push(GenericBound
::Outlives(self.expect_lifetime()));
342 let inner_span
= inner_lo
.to(self.prev_span
);
343 self.expect(&token
::CloseDelim(token
::Paren
))?
;
344 let mut err
= self.struct_span_err(
345 lo
.to(self.prev_span
),
346 "parenthesized lifetime bounds are not supported"
348 if let Ok(snippet
) = self.span_to_snippet(inner_span
) {
349 err
.span_suggestion_short(
350 lo
.to(self.prev_span
),
351 "remove the parentheses",
353 Applicability
::MachineApplicable
359 let lifetime_defs
= self.parse_late_bound_lifetime_defs()?
;
360 let path
= self.parse_path(PathStyle
::Type
)?
;
362 self.expect(&token
::CloseDelim(token
::Paren
))?
;
364 let poly_span
= lo
.to(self.prev_span
);
367 if let Some(sp
) = last_plus_span
.or(colon_span
) {
368 negative_bounds
.push(sp
.to(poly_span
));
371 let poly_trait
= PolyTraitRef
::new(lifetime_defs
, path
, poly_span
);
372 let modifier
= if question
.is_some() {
373 TraitBoundModifier
::Maybe
375 TraitBoundModifier
::None
377 bounds
.push(GenericBound
::Trait(poly_trait
, modifier
));
384 if !allow_plus
|| !self.eat_plus() {
387 last_plus_span
= Some(self.prev_span
);
391 if !negative_bounds
.is_empty() || was_negative
{
392 let negative_bounds_len
= negative_bounds
.len();
393 let last_span
= negative_bounds
.last().map(|sp
| *sp
);
394 let mut err
= self.struct_span_err(
396 "negative trait bounds are not supported",
398 if let Some(sp
) = last_span
{
399 err
.span_label(sp
, "negative trait bounds are not supported");
401 if let Some(bound_list
) = colon_span
{
402 let bound_list
= bound_list
.to(self.prev_span
);
403 let mut new_bound_list
= String
::new();
404 if !bounds
.is_empty() {
405 let mut snippets
= bounds
.iter().map(|bound
| bound
.span())
406 .map(|span
| self.span_to_snippet(span
));
407 while let Some(Ok(snippet
)) = snippets
.next() {
408 new_bound_list
.push_str(" + ");
409 new_bound_list
.push_str(&snippet
);
411 new_bound_list
= new_bound_list
.replacen(" +", ":", 1);
413 err
.span_suggestion_hidden(
415 &format
!("remove the trait bound{}", pluralize
!(negative_bounds_len
)),
417 Applicability
::MachineApplicable
,
426 pub(super) fn parse_late_bound_lifetime_defs(&mut self) -> PResult
<'a
, Vec
<GenericParam
>> {
427 if self.eat_keyword(kw
::For
) {
429 let params
= self.parse_generic_params()?
;
431 // We rely on AST validation to rule out invalid cases: There must not be type
432 // parameters, and the lifetime parameters must not have bounds.
439 pub fn check_lifetime(&mut self) -> bool
{
440 self.expected_tokens
.push(TokenType
::Lifetime
);
441 self.token
.is_lifetime()
444 /// Parses a single lifetime `'a` or panics.
445 pub fn expect_lifetime(&mut self) -> Lifetime
{
446 if let Some(ident
) = self.token
.lifetime() {
447 let span
= self.token
.span
;
449 Lifetime { ident: Ident::new(ident.name, span), id: ast::DUMMY_NODE_ID }
451 self.span_bug(self.token
.span
, "not a lifetime")
455 pub(super) fn mk_ty(&self, span
: Span
, kind
: TyKind
) -> P
<Ty
> {
456 P(Ty { kind, span, id: ast::DUMMY_NODE_ID }
)