]> git.proxmox.com Git - rustc.git/blob - src/librustc_parse/parser/ty.rs
New upstream version 1.41.1+dfsg1
[rustc.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 rustc_errors::{PResult, Applicability, pluralize};
7 use rustc_error_codes::*;
8 use syntax::ptr::P;
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;
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 args = self.parse_mac_args()?;
179 let mac = Mac {
180 path,
181 args,
182 prior_type_ascription: self.last_type_ascription,
183 };
184 TyKind::Mac(mac)
185 } else {
186 // Just a type path or bound list (trait object type) starting with a trait.
187 // `Type`
188 // `Trait1 + Trait2 + 'a`
189 if allow_plus && self.check_plus() {
190 self.parse_remaining_bounds(Vec::new(), path, lo, true)?
191 } else {
192 TyKind::Path(None, path)
193 }
194 }
195 } else if self.check(&token::DotDotDot) {
196 if allow_c_variadic {
197 self.eat(&token::DotDotDot);
198 TyKind::CVarArgs
199 } else {
200 return Err(struct_span_fatal!(
201 self.sess.span_diagnostic,
202 self.token.span,
203 E0743,
204 "only foreign functions are allowed to be C-variadic",
205 ));
206 }
207 } else {
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);
212 return Err(err);
213 };
214
215 let span = lo.to(self.prev_span);
216 let ty = self.mk_ty(span, kind);
217
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)
222 }
223
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)];
228 if parse_plus {
229 self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
230 bounds.append(&mut self.parse_generic_bounds(Some(self.prev_span))?);
231 }
232 Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
233 }
234
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")
242 .emit();
243 Mutability::Immutable
244 });
245 let t = self.parse_ty_no_plus()?;
246 Ok(MutTy { ty: t, mutbl })
247 }
248
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()?))
252 } else {
253 Ok(None)
254 }
255 }
256
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 }));
262 }
263
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)
269 }
270
271 /// Parses a `TyKind::BareFn` type.
272 fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>) -> PResult<'a, TyKind> {
273 /*
274
275 [unsafe] [extern "ABI"] fn (S) -> T
276 ^~~~^ ^~~~^ ^~^ ^
277 | | | |
278 | | | Return type
279 | | Argument types
280 | |
281 | ABI
282 Function Style
283 */
284
285 let unsafety = self.parse_unsafety();
286 let ext = self.parse_extern()?;
287 self.expect_keyword(kw::Fn)?;
288 let cfg = ParamCfg {
289 is_self_allowed: false,
290 allow_c_variadic: true,
291 is_name_required: |_| false,
292 };
293 let decl = self.parse_fn_decl(cfg, false)?;
294 Ok(TyKind::BareFn(P(BareFnTy {
295 ext,
296 unsafety,
297 generic_params,
298 decl,
299 })))
300 }
301
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)
305 }
306
307 /// Parses bounds of a type parameter `BOUND + BOUND + ...`, possibly with trailing `+`.
308 ///
309 /// ```
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>`)
314 /// ```
315 fn parse_generic_bounds_common(&mut self,
316 allow_plus: bool,
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;
322 loop {
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));
329 if is_bound_start {
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");
339 }
340 bounds.push(GenericBound::Outlives(self.expect_lifetime()));
341 if has_parens {
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"
347 );
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",
352 snippet.to_owned(),
353 Applicability::MachineApplicable
354 );
355 }
356 err.emit();
357 }
358 } else {
359 let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
360 let path = self.parse_path(PathStyle::Type)?;
361 if has_parens {
362 self.expect(&token::CloseDelim(token::Paren))?;
363 }
364 let poly_span = lo.to(self.prev_span);
365 if is_negative {
366 was_negative = true;
367 if let Some(sp) = last_plus_span.or(colon_span) {
368 negative_bounds.push(sp.to(poly_span));
369 }
370 } else {
371 let poly_trait = PolyTraitRef::new(lifetime_defs, path, poly_span);
372 let modifier = if question.is_some() {
373 TraitBoundModifier::Maybe
374 } else {
375 TraitBoundModifier::None
376 };
377 bounds.push(GenericBound::Trait(poly_trait, modifier));
378 }
379 }
380 } else {
381 break
382 }
383
384 if !allow_plus || !self.eat_plus() {
385 break
386 } else {
387 last_plus_span = Some(self.prev_span);
388 }
389 }
390
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(
395 negative_bounds,
396 "negative trait bounds are not supported",
397 );
398 if let Some(sp) = last_span {
399 err.span_label(sp, "negative trait bounds are not supported");
400 }
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);
410 }
411 new_bound_list = new_bound_list.replacen(" +", ":", 1);
412 }
413 err.span_suggestion_hidden(
414 bound_list,
415 &format!("remove the trait bound{}", pluralize!(negative_bounds_len)),
416 new_bound_list,
417 Applicability::MachineApplicable,
418 );
419 }
420 err.emit();
421 }
422
423 return Ok(bounds);
424 }
425
426 pub(super) fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec<GenericParam>> {
427 if self.eat_keyword(kw::For) {
428 self.expect_lt()?;
429 let params = self.parse_generic_params()?;
430 self.expect_gt()?;
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.
433 Ok(params)
434 } else {
435 Ok(Vec::new())
436 }
437 }
438
439 pub fn check_lifetime(&mut self) -> bool {
440 self.expected_tokens.push(TokenType::Lifetime);
441 self.token.is_lifetime()
442 }
443
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;
448 self.bump();
449 Lifetime { ident: Ident::new(ident.name, span), id: ast::DUMMY_NODE_ID }
450 } else {
451 self.span_bug(self.token.span, "not a lifetime")
452 }
453 }
454
455 pub(super) fn mk_ty(&self, span: Span, kind: TyKind) -> P<Ty> {
456 P(Ty { kind, span, id: ast::DUMMY_NODE_ID })
457 }
458 }