]>
Commit | Line | Data |
---|---|---|
416331ca XL |
1 | use super::{Parser, PResult, TokenType}; |
2 | ||
3 | use crate::{maybe_whole, ThinVec}; | |
4 | use crate::ast::{self, QSelf, Path, PathSegment, Ident, ParenthesizedArgs, AngleBracketedArgs}; | |
5 | use crate::ast::{AnonConst, GenericArg, AssocTyConstraint, AssocTyConstraintKind, BlockCheckMode}; | |
6 | use crate::parse::token::{self, Token}; | |
7 | use crate::source_map::{Span, BytePos}; | |
8 | use crate::symbol::kw; | |
9 | ||
10 | use std::mem; | |
11 | use log::debug; | |
e1599b0c | 12 | use errors::{Applicability, pluralise}; |
416331ca XL |
13 | |
14 | /// Specifies how to parse a path. | |
15 | #[derive(Copy, Clone, PartialEq)] | |
16 | pub enum PathStyle { | |
17 | /// In some contexts, notably in expressions, paths with generic arguments are ambiguous | |
18 | /// with something else. For example, in expressions `segment < ....` can be interpreted | |
19 | /// as a comparison and `segment ( ....` can be interpreted as a function call. | |
20 | /// In all such contexts the non-path interpretation is preferred by default for practical | |
21 | /// reasons, but the path interpretation can be forced by the disambiguator `::`, e.g. | |
22 | /// `x<y>` - comparisons, `x::<y>` - unambiguously a path. | |
23 | Expr, | |
24 | /// In other contexts, notably in types, no ambiguity exists and paths can be written | |
25 | /// without the disambiguator, e.g., `x<y>` - unambiguously a path. | |
26 | /// Paths with disambiguators are still accepted, `x::<Y>` - unambiguously a path too. | |
27 | Type, | |
28 | /// A path with generic arguments disallowed, e.g., `foo::bar::Baz`, used in imports, | |
29 | /// visibilities or attributes. | |
30 | /// Technically, this variant is unnecessary and e.g., `Expr` can be used instead | |
31 | /// (paths in "mod" contexts have to be checked later for absence of generic arguments | |
32 | /// anyway, due to macros), but it is used to avoid weird suggestions about expected | |
33 | /// tokens when something goes wrong. | |
34 | Mod, | |
35 | } | |
36 | ||
37 | impl<'a> Parser<'a> { | |
38 | /// Parses a qualified path. | |
39 | /// Assumes that the leading `<` has been parsed already. | |
40 | /// | |
41 | /// `qualified_path = <type [as trait_ref]>::path` | |
42 | /// | |
43 | /// # Examples | |
44 | /// `<T>::default` | |
45 | /// `<T as U>::a` | |
46 | /// `<T as U>::F::a<S>` (without disambiguator) | |
47 | /// `<T as U>::F::a::<S>` (with disambiguator) | |
48 | pub(super) fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (QSelf, Path)> { | |
49 | let lo = self.prev_span; | |
50 | let ty = self.parse_ty()?; | |
51 | ||
52 | // `path` will contain the prefix of the path up to the `>`, | |
53 | // if any (e.g., `U` in the `<T as U>::*` examples | |
54 | // above). `path_span` has the span of that path, or an empty | |
55 | // span in the case of something like `<T>::Bar`. | |
56 | let (mut path, path_span); | |
57 | if self.eat_keyword(kw::As) { | |
58 | let path_lo = self.token.span; | |
59 | path = self.parse_path(PathStyle::Type)?; | |
60 | path_span = path_lo.to(self.prev_span); | |
61 | } else { | |
62 | path_span = self.token.span.to(self.token.span); | |
63 | path = ast::Path { segments: Vec::new(), span: path_span }; | |
64 | } | |
65 | ||
66 | // See doc comment for `unmatched_angle_bracket_count`. | |
67 | self.expect(&token::Gt)?; | |
68 | if self.unmatched_angle_bracket_count > 0 { | |
69 | self.unmatched_angle_bracket_count -= 1; | |
70 | debug!("parse_qpath: (decrement) count={:?}", self.unmatched_angle_bracket_count); | |
71 | } | |
72 | ||
73 | self.expect(&token::ModSep)?; | |
74 | ||
75 | let qself = QSelf { ty, path_span, position: path.segments.len() }; | |
76 | self.parse_path_segments(&mut path.segments, style)?; | |
77 | ||
78 | Ok((qself, Path { segments: path.segments, span: lo.to(self.prev_span) })) | |
79 | } | |
80 | ||
81 | /// Parses simple paths. | |
82 | /// | |
83 | /// `path = [::] segment+` | |
84 | /// `segment = ident | ident[::]<args> | ident[::](args) [-> type]` | |
85 | /// | |
86 | /// # Examples | |
87 | /// `a::b::C<D>` (without disambiguator) | |
88 | /// `a::b::C::<D>` (with disambiguator) | |
89 | /// `Fn(Args)` (without disambiguator) | |
90 | /// `Fn::(Args)` (with disambiguator) | |
91 | pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> { | |
92 | maybe_whole!(self, NtPath, |path| { | |
93 | if style == PathStyle::Mod && | |
94 | path.segments.iter().any(|segment| segment.args.is_some()) { | |
95 | self.diagnostic().span_err(path.span, "unexpected generic arguments in path"); | |
96 | } | |
97 | path | |
98 | }); | |
99 | ||
100 | let lo = self.meta_var_span.unwrap_or(self.token.span); | |
101 | let mut segments = Vec::new(); | |
102 | let mod_sep_ctxt = self.token.span.ctxt(); | |
103 | if self.eat(&token::ModSep) { | |
104 | segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt))); | |
105 | } | |
106 | self.parse_path_segments(&mut segments, style)?; | |
107 | ||
108 | Ok(Path { segments, span: lo.to(self.prev_span) }) | |
109 | } | |
110 | ||
111 | /// Like `parse_path`, but also supports parsing `Word` meta items into paths for | |
112 | /// backwards-compatibility. This is used when parsing derive macro paths in `#[derive]` | |
113 | /// attributes. | |
114 | pub fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, Path> { | |
115 | let meta_ident = match self.token.kind { | |
116 | token::Interpolated(ref nt) => match **nt { | |
117 | token::NtMeta(ref meta) => match meta.node { | |
118 | ast::MetaItemKind::Word => Some(meta.path.clone()), | |
119 | _ => None, | |
120 | }, | |
121 | _ => None, | |
122 | }, | |
123 | _ => None, | |
124 | }; | |
125 | if let Some(path) = meta_ident { | |
126 | self.bump(); | |
127 | return Ok(path); | |
128 | } | |
129 | self.parse_path(style) | |
130 | } | |
131 | ||
e1599b0c XL |
132 | crate fn parse_path_segments( |
133 | &mut self, | |
134 | segments: &mut Vec<PathSegment>, | |
135 | style: PathStyle, | |
136 | ) -> PResult<'a, ()> { | |
416331ca XL |
137 | loop { |
138 | let segment = self.parse_path_segment(style)?; | |
139 | if style == PathStyle::Expr { | |
140 | // In order to check for trailing angle brackets, we must have finished | |
141 | // recursing (`parse_path_segment` can indirectly call this function), | |
142 | // that is, the next token must be the highlighted part of the below example: | |
143 | // | |
144 | // `Foo::<Bar as Baz<T>>::Qux` | |
145 | // ^ here | |
146 | // | |
147 | // As opposed to the below highlight (if we had only finished the first | |
148 | // recursion): | |
149 | // | |
150 | // `Foo::<Bar as Baz<T>>::Qux` | |
151 | // ^ here | |
152 | // | |
153 | // `PathStyle::Expr` is only provided at the root invocation and never in | |
154 | // `parse_path_segment` to recurse and therefore can be checked to maintain | |
155 | // this invariant. | |
156 | self.check_trailing_angle_brackets(&segment, token::ModSep); | |
157 | } | |
158 | segments.push(segment); | |
159 | ||
160 | if self.is_import_coupler() || !self.eat(&token::ModSep) { | |
161 | return Ok(()); | |
162 | } | |
163 | } | |
164 | } | |
165 | ||
166 | pub(super) fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, PathSegment> { | |
167 | let ident = self.parse_path_segment_ident()?; | |
168 | ||
169 | let is_args_start = |token: &Token| match token.kind { | |
170 | token::Lt | token::BinOp(token::Shl) | token::OpenDelim(token::Paren) | |
171 | | token::LArrow => true, | |
172 | _ => false, | |
173 | }; | |
174 | let check_args_start = |this: &mut Self| { | |
175 | this.expected_tokens.extend_from_slice( | |
176 | &[TokenType::Token(token::Lt), TokenType::Token(token::OpenDelim(token::Paren))] | |
177 | ); | |
178 | is_args_start(&this.token) | |
179 | }; | |
180 | ||
181 | Ok(if style == PathStyle::Type && check_args_start(self) || | |
182 | style != PathStyle::Mod && self.check(&token::ModSep) | |
183 | && self.look_ahead(1, |t| is_args_start(t)) { | |
184 | // We use `style == PathStyle::Expr` to check if this is in a recursion or not. If | |
185 | // it isn't, then we reset the unmatched angle bracket count as we're about to start | |
186 | // parsing a new path. | |
187 | if style == PathStyle::Expr { | |
188 | self.unmatched_angle_bracket_count = 0; | |
189 | self.max_angle_bracket_count = 0; | |
190 | } | |
191 | ||
192 | // Generic arguments are found - `<`, `(`, `::<` or `::(`. | |
193 | self.eat(&token::ModSep); | |
194 | let lo = self.token.span; | |
195 | let args = if self.eat_lt() { | |
196 | // `<'a, T, A = U>` | |
197 | let (args, constraints) = | |
198 | self.parse_generic_args_with_leaning_angle_bracket_recovery(style, lo)?; | |
199 | self.expect_gt()?; | |
200 | let span = lo.to(self.prev_span); | |
201 | AngleBracketedArgs { args, constraints, span }.into() | |
202 | } else { | |
203 | // `(T, U) -> R` | |
204 | let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?; | |
e1599b0c | 205 | let span = ident.span.to(self.prev_span); |
416331ca XL |
206 | let output = if self.eat(&token::RArrow) { |
207 | Some(self.parse_ty_common(false, false, false)?) | |
208 | } else { | |
209 | None | |
210 | }; | |
211 | ParenthesizedArgs { inputs, output, span }.into() | |
212 | }; | |
213 | ||
214 | PathSegment { ident, args, id: ast::DUMMY_NODE_ID } | |
215 | } else { | |
216 | // Generic arguments are not found. | |
217 | PathSegment::from_ident(ident) | |
218 | }) | |
219 | } | |
220 | ||
221 | pub(super) fn parse_path_segment_ident(&mut self) -> PResult<'a, Ident> { | |
222 | match self.token.kind { | |
223 | token::Ident(name, _) if name.is_path_segment_keyword() => { | |
224 | let span = self.token.span; | |
225 | self.bump(); | |
226 | Ok(Ident::new(name, span)) | |
227 | } | |
228 | _ => self.parse_ident(), | |
229 | } | |
230 | } | |
231 | ||
232 | /// Parses generic args (within a path segment) with recovery for extra leading angle brackets. | |
233 | /// For the purposes of understanding the parsing logic of generic arguments, this function | |
234 | /// can be thought of being the same as just calling `self.parse_generic_args()` if the source | |
235 | /// had the correct amount of leading angle brackets. | |
236 | /// | |
237 | /// ```ignore (diagnostics) | |
238 | /// bar::<<<<T as Foo>::Output>(); | |
239 | /// ^^ help: remove extra angle brackets | |
240 | /// ``` | |
241 | fn parse_generic_args_with_leaning_angle_bracket_recovery( | |
242 | &mut self, | |
243 | style: PathStyle, | |
244 | lo: Span, | |
245 | ) -> PResult<'a, (Vec<GenericArg>, Vec<AssocTyConstraint>)> { | |
246 | // We need to detect whether there are extra leading left angle brackets and produce an | |
247 | // appropriate error and suggestion. This cannot be implemented by looking ahead at | |
248 | // upcoming tokens for a matching `>` character - if there are unmatched `<` tokens | |
249 | // then there won't be matching `>` tokens to find. | |
250 | // | |
251 | // To explain how this detection works, consider the following example: | |
252 | // | |
253 | // ```ignore (diagnostics) | |
254 | // bar::<<<<T as Foo>::Output>(); | |
255 | // ^^ help: remove extra angle brackets | |
256 | // ``` | |
257 | // | |
258 | // Parsing of the left angle brackets starts in this function. We start by parsing the | |
259 | // `<` token (incrementing the counter of unmatched angle brackets on `Parser` via | |
260 | // `eat_lt`): | |
261 | // | |
262 | // *Upcoming tokens:* `<<<<T as Foo>::Output>;` | |
263 | // *Unmatched count:* 1 | |
264 | // *`parse_path_segment` calls deep:* 0 | |
265 | // | |
266 | // This has the effect of recursing as this function is called if a `<` character | |
267 | // is found within the expected generic arguments: | |
268 | // | |
269 | // *Upcoming tokens:* `<<<T as Foo>::Output>;` | |
270 | // *Unmatched count:* 2 | |
271 | // *`parse_path_segment` calls deep:* 1 | |
272 | // | |
273 | // Eventually we will have recursed until having consumed all of the `<` tokens and | |
274 | // this will be reflected in the count: | |
275 | // | |
276 | // *Upcoming tokens:* `T as Foo>::Output>;` | |
277 | // *Unmatched count:* 4 | |
278 | // `parse_path_segment` calls deep:* 3 | |
279 | // | |
280 | // The parser will continue until reaching the first `>` - this will decrement the | |
281 | // unmatched angle bracket count and return to the parent invocation of this function | |
282 | // having succeeded in parsing: | |
283 | // | |
284 | // *Upcoming tokens:* `::Output>;` | |
285 | // *Unmatched count:* 3 | |
286 | // *`parse_path_segment` calls deep:* 2 | |
287 | // | |
288 | // This will continue until the next `>` character which will also return successfully | |
289 | // to the parent invocation of this function and decrement the count: | |
290 | // | |
291 | // *Upcoming tokens:* `;` | |
292 | // *Unmatched count:* 2 | |
293 | // *`parse_path_segment` calls deep:* 1 | |
294 | // | |
295 | // At this point, this function will expect to find another matching `>` character but | |
296 | // won't be able to and will return an error. This will continue all the way up the | |
297 | // call stack until the first invocation: | |
298 | // | |
299 | // *Upcoming tokens:* `;` | |
300 | // *Unmatched count:* 2 | |
301 | // *`parse_path_segment` calls deep:* 0 | |
302 | // | |
303 | // In doing this, we have managed to work out how many unmatched leading left angle | |
304 | // brackets there are, but we cannot recover as the unmatched angle brackets have | |
305 | // already been consumed. To remedy this, we keep a snapshot of the parser state | |
306 | // before we do the above. We can then inspect whether we ended up with a parsing error | |
307 | // and unmatched left angle brackets and if so, restore the parser state before we | |
308 | // consumed any `<` characters to emit an error and consume the erroneous tokens to | |
309 | // recover by attempting to parse again. | |
310 | // | |
311 | // In practice, the recursion of this function is indirect and there will be other | |
312 | // locations that consume some `<` characters - as long as we update the count when | |
313 | // this happens, it isn't an issue. | |
314 | ||
315 | let is_first_invocation = style == PathStyle::Expr; | |
316 | // Take a snapshot before attempting to parse - we can restore this later. | |
317 | let snapshot = if is_first_invocation { | |
318 | Some(self.clone()) | |
319 | } else { | |
320 | None | |
321 | }; | |
322 | ||
323 | debug!("parse_generic_args_with_leading_angle_bracket_recovery: (snapshotting)"); | |
324 | match self.parse_generic_args() { | |
325 | Ok(value) => Ok(value), | |
326 | Err(ref mut e) if is_first_invocation && self.unmatched_angle_bracket_count > 0 => { | |
327 | // Cancel error from being unable to find `>`. We know the error | |
328 | // must have been this due to a non-zero unmatched angle bracket | |
329 | // count. | |
330 | e.cancel(); | |
331 | ||
332 | // Swap `self` with our backup of the parser state before attempting to parse | |
333 | // generic arguments. | |
334 | let snapshot = mem::replace(self, snapshot.unwrap()); | |
335 | ||
336 | debug!( | |
337 | "parse_generic_args_with_leading_angle_bracket_recovery: (snapshot failure) \ | |
338 | snapshot.count={:?}", | |
339 | snapshot.unmatched_angle_bracket_count, | |
340 | ); | |
341 | ||
342 | // Eat the unmatched angle brackets. | |
343 | for _ in 0..snapshot.unmatched_angle_bracket_count { | |
344 | self.eat_lt(); | |
345 | } | |
346 | ||
347 | // Make a span over ${unmatched angle bracket count} characters. | |
348 | let span = lo.with_hi( | |
349 | lo.lo() + BytePos(snapshot.unmatched_angle_bracket_count) | |
350 | ); | |
416331ca XL |
351 | self.diagnostic() |
352 | .struct_span_err( | |
353 | span, | |
354 | &format!( | |
355 | "unmatched angle bracket{}", | |
e1599b0c | 356 | pluralise!(snapshot.unmatched_angle_bracket_count) |
416331ca XL |
357 | ), |
358 | ) | |
359 | .span_suggestion( | |
360 | span, | |
361 | &format!( | |
362 | "remove extra angle bracket{}", | |
e1599b0c | 363 | pluralise!(snapshot.unmatched_angle_bracket_count) |
416331ca XL |
364 | ), |
365 | String::new(), | |
366 | Applicability::MachineApplicable, | |
367 | ) | |
368 | .emit(); | |
369 | ||
370 | // Try again without unmatched angle bracket characters. | |
371 | self.parse_generic_args() | |
372 | }, | |
373 | Err(e) => Err(e), | |
374 | } | |
375 | } | |
376 | ||
377 | /// Parses (possibly empty) list of lifetime and type arguments and associated type bindings, | |
378 | /// possibly including trailing comma. | |
379 | fn parse_generic_args(&mut self) -> PResult<'a, (Vec<GenericArg>, Vec<AssocTyConstraint>)> { | |
380 | let mut args = Vec::new(); | |
381 | let mut constraints = Vec::new(); | |
382 | let mut misplaced_assoc_ty_constraints: Vec<Span> = Vec::new(); | |
383 | let mut assoc_ty_constraints: Vec<Span> = Vec::new(); | |
384 | ||
385 | let args_lo = self.token.span; | |
386 | ||
387 | loop { | |
388 | if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) { | |
389 | // Parse lifetime argument. | |
390 | args.push(GenericArg::Lifetime(self.expect_lifetime())); | |
391 | misplaced_assoc_ty_constraints.append(&mut assoc_ty_constraints); | |
392 | } else if self.check_ident() && self.look_ahead(1, | |
393 | |t| t == &token::Eq || t == &token::Colon) { | |
394 | // Parse associated type constraint. | |
395 | let lo = self.token.span; | |
396 | let ident = self.parse_ident()?; | |
397 | let kind = if self.eat(&token::Eq) { | |
398 | AssocTyConstraintKind::Equality { | |
399 | ty: self.parse_ty()?, | |
400 | } | |
401 | } else if self.eat(&token::Colon) { | |
402 | AssocTyConstraintKind::Bound { | |
403 | bounds: self.parse_generic_bounds(Some(self.prev_span))?, | |
404 | } | |
405 | } else { | |
406 | unreachable!(); | |
407 | }; | |
408 | let span = lo.to(self.prev_span); | |
409 | constraints.push(AssocTyConstraint { | |
410 | id: ast::DUMMY_NODE_ID, | |
411 | ident, | |
412 | kind, | |
413 | span, | |
414 | }); | |
415 | assoc_ty_constraints.push(span); | |
416 | } else if self.check_const_arg() { | |
417 | // Parse const argument. | |
418 | let expr = if let token::OpenDelim(token::Brace) = self.token.kind { | |
419 | self.parse_block_expr( | |
420 | None, self.token.span, BlockCheckMode::Default, ThinVec::new() | |
421 | )? | |
422 | } else if self.token.is_ident() { | |
423 | // FIXME(const_generics): to distinguish between idents for types and consts, | |
424 | // we should introduce a GenericArg::Ident in the AST and distinguish when | |
425 | // lowering to the HIR. For now, idents for const args are not permitted. | |
e1599b0c | 426 | if self.token.is_bool_lit() { |
416331ca XL |
427 | self.parse_literal_maybe_minus()? |
428 | } else { | |
429 | return Err( | |
430 | self.fatal("identifiers may currently not be used for const generics") | |
431 | ); | |
432 | } | |
433 | } else { | |
434 | self.parse_literal_maybe_minus()? | |
435 | }; | |
436 | let value = AnonConst { | |
437 | id: ast::DUMMY_NODE_ID, | |
438 | value: expr, | |
439 | }; | |
440 | args.push(GenericArg::Const(value)); | |
441 | misplaced_assoc_ty_constraints.append(&mut assoc_ty_constraints); | |
442 | } else if self.check_type() { | |
443 | // Parse type argument. | |
444 | args.push(GenericArg::Type(self.parse_ty()?)); | |
445 | misplaced_assoc_ty_constraints.append(&mut assoc_ty_constraints); | |
446 | } else { | |
447 | break | |
448 | } | |
449 | ||
450 | if !self.eat(&token::Comma) { | |
451 | break | |
452 | } | |
453 | } | |
454 | ||
455 | // FIXME: we would like to report this in ast_validation instead, but we currently do not | |
456 | // preserve ordering of generic parameters with respect to associated type binding, so we | |
457 | // lose that information after parsing. | |
458 | if misplaced_assoc_ty_constraints.len() > 0 { | |
459 | let mut err = self.struct_span_err( | |
460 | args_lo.to(self.prev_span), | |
461 | "associated type bindings must be declared after generic parameters", | |
462 | ); | |
463 | for span in misplaced_assoc_ty_constraints { | |
464 | err.span_label( | |
465 | span, | |
466 | "this associated type binding should be moved after the generic parameters", | |
467 | ); | |
468 | } | |
469 | err.emit(); | |
470 | } | |
471 | ||
472 | Ok((args, constraints)) | |
473 | } | |
474 | } |