]> git.lizzy.rs Git - rust.git/blob - src/librustc_parse/parser/ty.rs
move syntax::parse -> librustc_parse
[rust.git] / src / librustc_parse / parser / ty.rs
1 use super::{Parser, PathStyle, PrevTokenKind, TokenType};
2 use super::item::ParamCfg;
3
4 use crate::{maybe_whole, maybe_recover_from_interpolated_ty_qpath};
5
6 use syntax::ptr::P;
7 use syntax::ast::{self, Ty, TyKind, MutTy, BareFnTy, FunctionRetTy, GenericParam, Lifetime, Ident};
8 use syntax::ast::{TraitBoundModifier, TraitObjectSyntax, GenericBound, GenericBounds, PolyTraitRef};
9 use syntax::ast::{Mutability, AnonConst, Mac};
10 use syntax::token::{self, Token};
11 use syntax::source_map::Span;
12 use syntax::struct_span_fatal;
13 use syntax_pos::symbol::kw;
14
15 use errors::{PResult, Applicability, pluralize};
16
17 /// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT<u8, u8>`,
18 /// `IDENT<<u8 as Trait>::AssocTy>`.
19 ///
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)
25 }
26
27 impl<'a> Parser<'a> {
28     /// Parses a type.
29     pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
30         self.parse_ty_common(true, true, false)
31     }
32
33     /// Parses a type in restricted contexts where `+` is not permitted.
34     ///
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)
41     }
42
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)?))
47         } else {
48             Ok(FunctionRetTy::Default(self.token.span.shrink_to_lo()))
49         }
50     }
51
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);
56
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.
62             let mut ts = vec![];
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) {
67                     last_comma = true;
68                 } else {
69                     last_comma = false;
70                     break;
71                 }
72             }
73             let trailing_plus = self.prev_token_kind == PrevTokenKind::Plus;
74             self.expect(&token::CloseDelim(token::Paren))?;
75
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();
79                 match ty.kind {
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)?
83                     }
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"),
89                         };
90                         self.parse_remaining_bounds(Vec::new(), path, lo, true)?
91                     }
92                     // `(TYPE)`
93                     _ => TyKind::Paren(P(ty))
94                 }
95             } else {
96                 TyKind::Tup(ts)
97             }
98         } else if self.eat(&token::Not) {
99             // Never type `!`
100             TyKind::Never
101         } else if self.eat(&token::BinOp(token::Star)) {
102             // Raw pointer
103             TyKind::Ptr(self.parse_ptr()?)
104         } else if self.eat(&token::OpenDelim(token::Bracket)) {
105             // Array or slice
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,
112                     value: length,
113                 }),
114             };
115             self.expect(&token::CloseDelim(token::Bracket))?;
116             t
117         } else if self.check(&token::BinOp(token::And)) || self.check(&token::AndAnd) {
118             // Reference
119             self.expect_and()?;
120             self.parse_borrowed_pointee()?
121         } else if self.eat_keyword_noexpect(kw::Typeof) {
122             // `typeof(EXPR)`
123             // In order to not be ambiguous, the type must be surrounded by parens.
124             self.expect(&token::OpenDelim(token::Paren))?;
125             let e = AnonConst {
126                 id: ast::DUMMY_NODE_ID,
127                 value: self.parse_expr()?,
128             };
129             self.expect(&token::CloseDelim(token::Paren))?;
130             TyKind::Typeof(e)
131         } else if self.eat_keyword(kw::Underscore) {
132             // A type to be inferred `_`
133             TyKind::Infer
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)?
145             } else {
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)?
149             }
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() {
170             // Qualified path
171             let (qself, path) = self.parse_qpath(PathStyle::Type)?;
172             TyKind::Path(Some(qself), path)
173         } else if self.token.is_path_start() {
174             // Simple path
175             let path = self.parse_path(PathStyle::Type)?;
176             if self.eat(&token::Not) {
177                 // Macro invocation in type position
178                 let (delim, tts) = self.expect_delimited_token_tree()?;
179                 let mac = Mac {
180                     path,
181                     tts,
182                     delim,
183                     span: lo.to(self.prev_span),
184                     prior_type_ascription: self.last_type_ascription,
185                 };
186                 TyKind::Mac(mac)
187             } else {
188                 // Just a type path or bound list (trait object type) starting with a trait.
189                 //   `Type`
190                 //   `Trait1 + Trait2 + 'a`
191                 if allow_plus && self.check_plus() {
192                     self.parse_remaining_bounds(Vec::new(), path, lo, true)?
193                 } else {
194                     TyKind::Path(None, path)
195                 }
196             }
197         } else if self.check(&token::DotDotDot) {
198             if allow_c_variadic {
199                 self.eat(&token::DotDotDot);
200                 TyKind::CVarArgs
201             } else {
202                 return Err(struct_span_fatal!(
203                     self.sess.span_diagnostic,
204                     self.token.span,
205                     E0743,
206                     "only foreign functions are allowed to be C-variadic",
207                 ));
208             }
209         } else {
210             let msg = format!("expected type, found {}", self.this_token_descr());
211             let mut err = self.fatal(&msg);
212             err.span_label(self.token.span, "expected type");
213             self.maybe_annotate_with_ascription(&mut err, true);
214             return Err(err);
215         };
216
217         let span = lo.to(self.prev_span);
218         let ty = self.mk_ty(span, kind);
219
220         // Try to recover from use of `+` with incorrect priority.
221         self.maybe_report_ambiguous_plus(allow_plus, impl_dyn_multi, &ty);
222         self.maybe_recover_from_bad_type_plus(allow_plus, &ty)?;
223         self.maybe_recover_from_bad_qpath(ty, allow_qpath_recovery)
224     }
225
226     fn parse_remaining_bounds(&mut self, generic_params: Vec<GenericParam>, path: ast::Path,
227                               lo: Span, parse_plus: bool) -> PResult<'a, TyKind> {
228         let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_span));
229         let mut bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)];
230         if parse_plus {
231             self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
232             bounds.append(&mut self.parse_generic_bounds(Some(self.prev_span))?);
233         }
234         Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
235     }
236
237     fn parse_ptr(&mut self) -> PResult<'a, MutTy> {
238         let mutbl = self.parse_const_or_mut().unwrap_or_else(|| {
239             let span = self.prev_span;
240             let msg = "expected mut or const in raw pointer type";
241             self.struct_span_err(span, msg)
242                 .span_label(span, msg)
243                 .help("use `*mut T` or `*const T` as appropriate")
244                 .emit();
245             Mutability::Immutable
246         });
247         let t = self.parse_ty_no_plus()?;
248         Ok(MutTy { ty: t, mutbl })
249     }
250
251     fn maybe_parse_fixed_length_of_vec(&mut self) -> PResult<'a, Option<P<ast::Expr>>> {
252         if self.eat(&token::Semi) {
253             Ok(Some(self.parse_expr()?))
254         } else {
255             Ok(None)
256         }
257     }
258
259     fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
260         let opt_lifetime = if self.check_lifetime() { Some(self.expect_lifetime()) } else { None };
261         let mutbl = self.parse_mutability();
262         let ty = self.parse_ty_no_plus()?;
263         return Ok(TyKind::Rptr(opt_lifetime, MutTy { ty, mutbl }));
264     }
265
266     /// Is the current token one of the keywords that signals a bare function type?
267     fn token_is_bare_fn_keyword(&mut self) -> bool {
268         self.check_keyword(kw::Fn) ||
269             self.check_keyword(kw::Unsafe) ||
270             self.check_keyword(kw::Extern)
271     }
272
273     /// Parses a `TyKind::BareFn` type.
274     fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>) -> PResult<'a, TyKind> {
275         /*
276
277         [unsafe] [extern "ABI"] fn (S) -> T
278          ^~~~^           ^~~~^     ^~^    ^
279            |               |        |     |
280            |               |        |   Return type
281            |               |      Argument types
282            |               |
283            |              ABI
284         Function Style
285         */
286
287         let unsafety = self.parse_unsafety();
288         let abi = self.parse_extern_abi()?;
289         self.expect_keyword(kw::Fn)?;
290         let cfg = ParamCfg {
291             is_self_allowed: false,
292             allow_c_variadic: true,
293             is_name_required: |_| false,
294         };
295         let decl = self.parse_fn_decl(cfg, false)?;
296         Ok(TyKind::BareFn(P(BareFnTy {
297             abi,
298             unsafety,
299             generic_params,
300             decl,
301         })))
302     }
303
304     pub(super) fn parse_generic_bounds(&mut self,
305                                   colon_span: Option<Span>) -> PResult<'a, GenericBounds> {
306         self.parse_generic_bounds_common(true, colon_span)
307     }
308
309     /// Parses bounds of a type parameter `BOUND + BOUND + ...`, possibly with trailing `+`.
310     ///
311     /// ```
312     /// BOUND = TY_BOUND | LT_BOUND
313     /// LT_BOUND = LIFETIME (e.g., `'a`)
314     /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN)
315     /// TY_BOUND_NOPAREN = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g., `?for<'a: 'b> m::Trait<'a>`)
316     /// ```
317     fn parse_generic_bounds_common(&mut self,
318                                    allow_plus: bool,
319                                    colon_span: Option<Span>) -> PResult<'a, GenericBounds> {
320         let mut bounds = Vec::new();
321         let mut negative_bounds = Vec::new();
322         let mut last_plus_span = None;
323         let mut was_negative = false;
324         loop {
325             // This needs to be synchronized with `TokenKind::can_begin_bound`.
326             let is_bound_start = self.check_path() || self.check_lifetime() ||
327                                  self.check(&token::Not) || // used for error reporting only
328                                  self.check(&token::Question) ||
329                                  self.check_keyword(kw::For) ||
330                                  self.check(&token::OpenDelim(token::Paren));
331             if is_bound_start {
332                 let lo = self.token.span;
333                 let has_parens = self.eat(&token::OpenDelim(token::Paren));
334                 let inner_lo = self.token.span;
335                 let is_negative = self.eat(&token::Not);
336                 let question = if self.eat(&token::Question) { Some(self.prev_span) } else { None };
337                 if self.token.is_lifetime() {
338                     if let Some(question_span) = question {
339                         self.span_err(question_span,
340                                       "`?` may only modify trait bounds, not lifetime bounds");
341                     }
342                     bounds.push(GenericBound::Outlives(self.expect_lifetime()));
343                     if has_parens {
344                         let inner_span = inner_lo.to(self.prev_span);
345                         self.expect(&token::CloseDelim(token::Paren))?;
346                         let mut err = self.struct_span_err(
347                             lo.to(self.prev_span),
348                             "parenthesized lifetime bounds are not supported"
349                         );
350                         if let Ok(snippet) = self.span_to_snippet(inner_span) {
351                             err.span_suggestion_short(
352                                 lo.to(self.prev_span),
353                                 "remove the parentheses",
354                                 snippet.to_owned(),
355                                 Applicability::MachineApplicable
356                             );
357                         }
358                         err.emit();
359                     }
360                 } else {
361                     let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
362                     let path = self.parse_path(PathStyle::Type)?;
363                     if has_parens {
364                         self.expect(&token::CloseDelim(token::Paren))?;
365                     }
366                     let poly_span = lo.to(self.prev_span);
367                     if is_negative {
368                         was_negative = true;
369                         if let Some(sp) = last_plus_span.or(colon_span) {
370                             negative_bounds.push(sp.to(poly_span));
371                         }
372                     } else {
373                         let poly_trait = PolyTraitRef::new(lifetime_defs, path, poly_span);
374                         let modifier = if question.is_some() {
375                             TraitBoundModifier::Maybe
376                         } else {
377                             TraitBoundModifier::None
378                         };
379                         bounds.push(GenericBound::Trait(poly_trait, modifier));
380                     }
381                 }
382             } else {
383                 break
384             }
385
386             if !allow_plus || !self.eat_plus() {
387                 break
388             } else {
389                 last_plus_span = Some(self.prev_span);
390             }
391         }
392
393         if !negative_bounds.is_empty() || was_negative {
394             let negative_bounds_len = negative_bounds.len();
395             let last_span = negative_bounds.last().map(|sp| *sp);
396             let mut err = self.struct_span_err(
397                 negative_bounds,
398                 "negative trait bounds are not supported",
399             );
400             if let Some(sp) = last_span {
401                 err.span_label(sp, "negative trait bounds are not supported");
402             }
403             if let Some(bound_list) = colon_span {
404                 let bound_list = bound_list.to(self.prev_span);
405                 let mut new_bound_list = String::new();
406                 if !bounds.is_empty() {
407                     let mut snippets = bounds.iter().map(|bound| bound.span())
408                         .map(|span| self.span_to_snippet(span));
409                     while let Some(Ok(snippet)) = snippets.next() {
410                         new_bound_list.push_str(" + ");
411                         new_bound_list.push_str(&snippet);
412                     }
413                     new_bound_list = new_bound_list.replacen(" +", ":", 1);
414                 }
415                 err.span_suggestion_hidden(
416                     bound_list,
417                     &format!("remove the trait bound{}", pluralize!(negative_bounds_len)),
418                     new_bound_list,
419                     Applicability::MachineApplicable,
420                 );
421             }
422             err.emit();
423         }
424
425         return Ok(bounds);
426     }
427
428     pub(super) fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<GenericParam>> {
429         if self.eat_keyword(kw::For) {
430             self.expect_lt()?;
431             let params = self.parse_generic_params()?;
432             self.expect_gt()?;
433             // We rely on AST validation to rule out invalid cases: There must not be type
434             // parameters, and the lifetime parameters must not have bounds.
435             Ok(params)
436         } else {
437             Ok(Vec::new())
438         }
439     }
440
441     pub fn check_lifetime(&mut self) -> bool {
442         self.expected_tokens.push(TokenType::Lifetime);
443         self.token.is_lifetime()
444     }
445
446     /// Parses a single lifetime `'a` or panics.
447     pub fn expect_lifetime(&mut self) -> Lifetime {
448         if let Some(ident) = self.token.lifetime() {
449             let span = self.token.span;
450             self.bump();
451             Lifetime { ident: Ident::new(ident.name, span), id: ast::DUMMY_NODE_ID }
452         } else {
453             self.span_bug(self.token.span, "not a lifetime")
454         }
455     }
456
457     pub(super) fn mk_ty(&self, span: Span, kind: TyKind) -> P<Ty> {
458         P(Ty { kind, span, id: ast::DUMMY_NODE_ID })
459     }
460 }