]> git.proxmox.com Git - rustc.git/blob - src/libsyntax/parse/parser/diagnostics.rs
New upstream version 1.40.0+dfsg1
[rustc.git] / src / libsyntax / parse / parser / diagnostics.rs
1 use super::{
2 BlockMode, PathStyle, SemiColonMode, TokenType, TokenExpectType,
3 SeqSep, PResult, Parser
4 };
5 use crate::ast::{
6 self, Param, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Ident, Item, ItemKind,
7 Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind,
8 };
9 use crate::parse::token::{self, TokenKind, token_can_begin_expr};
10 use crate::print::pprust;
11 use crate::ptr::P;
12 use crate::symbol::{kw, sym};
13 use crate::ThinVec;
14 use crate::util::parser::AssocOp;
15 use errors::{Applicability, DiagnosticBuilder, DiagnosticId, pluralise};
16 use rustc_data_structures::fx::FxHashSet;
17 use syntax_pos::{Span, DUMMY_SP, MultiSpan, SpanSnippetError};
18 use log::{debug, trace};
19 use std::mem;
20
21 const TURBOFISH: &'static str = "use `::<...>` instead of `<...>` to specify type arguments";
22
23 /// Creates a placeholder argument.
24 pub(super) fn dummy_arg(ident: Ident) -> Param {
25 let pat = P(Pat {
26 id: ast::DUMMY_NODE_ID,
27 kind: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None),
28 span: ident.span,
29 });
30 let ty = Ty {
31 kind: TyKind::Err,
32 span: ident.span,
33 id: ast::DUMMY_NODE_ID
34 };
35 Param {
36 attrs: ThinVec::default(),
37 id: ast::DUMMY_NODE_ID,
38 pat,
39 span: ident.span,
40 ty: P(ty),
41 is_placeholder: false,
42 }
43 }
44
45 pub enum Error {
46 FileNotFoundForModule {
47 mod_name: String,
48 default_path: String,
49 secondary_path: String,
50 dir_path: String,
51 },
52 DuplicatePaths {
53 mod_name: String,
54 default_path: String,
55 secondary_path: String,
56 },
57 UselessDocComment,
58 InclusiveRangeWithNoEnd,
59 }
60
61 impl Error {
62 fn span_err<S: Into<MultiSpan>>(
63 self,
64 sp: S,
65 handler: &errors::Handler,
66 ) -> DiagnosticBuilder<'_> {
67 match self {
68 Error::FileNotFoundForModule {
69 ref mod_name,
70 ref default_path,
71 ref secondary_path,
72 ref dir_path,
73 } => {
74 let mut err = struct_span_err!(
75 handler,
76 sp,
77 E0583,
78 "file not found for module `{}`",
79 mod_name,
80 );
81 err.help(&format!(
82 "name the file either {} or {} inside the directory \"{}\"",
83 default_path,
84 secondary_path,
85 dir_path,
86 ));
87 err
88 }
89 Error::DuplicatePaths { ref mod_name, ref default_path, ref secondary_path } => {
90 let mut err = struct_span_err!(
91 handler,
92 sp,
93 E0584,
94 "file for module `{}` found at both {} and {}",
95 mod_name,
96 default_path,
97 secondary_path,
98 );
99 err.help("delete or rename one of them to remove the ambiguity");
100 err
101 }
102 Error::UselessDocComment => {
103 let mut err = struct_span_err!(
104 handler,
105 sp,
106 E0585,
107 "found a documentation comment that doesn't document anything",
108 );
109 err.help("doc comments must come before what they document, maybe a comment was \
110 intended with `//`?");
111 err
112 }
113 Error::InclusiveRangeWithNoEnd => {
114 let mut err = struct_span_err!(
115 handler,
116 sp,
117 E0586,
118 "inclusive range with no end",
119 );
120 err.help("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)");
121 err
122 }
123 }
124 }
125 }
126
127 pub(super) trait RecoverQPath: Sized + 'static {
128 const PATH_STYLE: PathStyle = PathStyle::Expr;
129 fn to_ty(&self) -> Option<P<Ty>>;
130 fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self;
131 }
132
133 impl RecoverQPath for Ty {
134 const PATH_STYLE: PathStyle = PathStyle::Type;
135 fn to_ty(&self) -> Option<P<Ty>> {
136 Some(P(self.clone()))
137 }
138 fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self {
139 Self {
140 span: path.span,
141 kind: TyKind::Path(qself, path),
142 id: ast::DUMMY_NODE_ID,
143 }
144 }
145 }
146
147 impl RecoverQPath for Pat {
148 fn to_ty(&self) -> Option<P<Ty>> {
149 self.to_ty()
150 }
151 fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self {
152 Self {
153 span: path.span,
154 kind: PatKind::Path(qself, path),
155 id: ast::DUMMY_NODE_ID,
156 }
157 }
158 }
159
160 impl RecoverQPath for Expr {
161 fn to_ty(&self) -> Option<P<Ty>> {
162 self.to_ty()
163 }
164 fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self {
165 Self {
166 span: path.span,
167 kind: ExprKind::Path(qself, path),
168 attrs: ThinVec::new(),
169 id: ast::DUMMY_NODE_ID,
170 }
171 }
172 }
173
174 /// Control whether the closing delimiter should be consumed when calling `Parser::consume_block`.
175 crate enum ConsumeClosingDelim {
176 Yes,
177 No,
178 }
179
180 impl<'a> Parser<'a> {
181 pub fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> {
182 self.span_fatal(self.token.span, m)
183 }
184
185 crate fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
186 self.sess.span_diagnostic.struct_span_fatal(sp, m)
187 }
188
189 pub(super) fn span_fatal_err<S: Into<MultiSpan>>(
190 &self,
191 sp: S,
192 err: Error,
193 ) -> DiagnosticBuilder<'a> {
194 err.span_err(sp, self.diagnostic())
195 }
196
197 pub(super) fn bug(&self, m: &str) -> ! {
198 self.sess.span_diagnostic.span_bug(self.token.span, m)
199 }
200
201 pub(super) fn span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) {
202 self.sess.span_diagnostic.span_err(sp, m)
203 }
204
205 pub fn struct_span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
206 self.sess.span_diagnostic.struct_span_err(sp, m)
207 }
208
209 pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> ! {
210 self.sess.span_diagnostic.span_bug(sp, m)
211 }
212
213 pub(super) fn diagnostic(&self) -> &'a errors::Handler {
214 &self.sess.span_diagnostic
215 }
216
217 pub(super) fn span_to_snippet(&self, span: Span) -> Result<String, SpanSnippetError> {
218 self.sess.source_map().span_to_snippet(span)
219 }
220
221 pub(super) fn expected_ident_found(&self) -> DiagnosticBuilder<'a> {
222 let mut err = self.struct_span_err(
223 self.token.span,
224 &format!("expected identifier, found {}", self.this_token_descr()),
225 );
226 if let token::Ident(name, false) = self.token.kind {
227 if Ident::new(name, self.token.span).is_raw_guess() {
228 err.span_suggestion(
229 self.token.span,
230 "you can escape reserved keywords to use them as identifiers",
231 format!("r#{}", name),
232 Applicability::MaybeIncorrect,
233 );
234 }
235 }
236 if let Some(token_descr) = self.token_descr() {
237 err.span_label(self.token.span, format!("expected identifier, found {}", token_descr));
238 } else {
239 err.span_label(self.token.span, "expected identifier");
240 if self.token == token::Comma && self.look_ahead(1, |t| t.is_ident()) {
241 err.span_suggestion(
242 self.token.span,
243 "remove this comma",
244 String::new(),
245 Applicability::MachineApplicable,
246 );
247 }
248 }
249 err
250 }
251
252 pub(super) fn expected_one_of_not_found(
253 &mut self,
254 edible: &[TokenKind],
255 inedible: &[TokenKind],
256 ) -> PResult<'a, bool /* recovered */> {
257 fn tokens_to_string(tokens: &[TokenType]) -> String {
258 let mut i = tokens.iter();
259 // This might be a sign we need a connect method on `Iterator`.
260 let b = i.next()
261 .map_or(String::new(), |t| t.to_string());
262 i.enumerate().fold(b, |mut b, (i, a)| {
263 if tokens.len() > 2 && i == tokens.len() - 2 {
264 b.push_str(", or ");
265 } else if tokens.len() == 2 && i == tokens.len() - 2 {
266 b.push_str(" or ");
267 } else {
268 b.push_str(", ");
269 }
270 b.push_str(&a.to_string());
271 b
272 })
273 }
274
275 let mut expected = edible.iter()
276 .map(|x| TokenType::Token(x.clone()))
277 .chain(inedible.iter().map(|x| TokenType::Token(x.clone())))
278 .chain(self.expected_tokens.iter().cloned())
279 .collect::<Vec<_>>();
280 expected.sort_by_cached_key(|x| x.to_string());
281 expected.dedup();
282 let expect = tokens_to_string(&expected[..]);
283 let actual = self.this_token_descr();
284 let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 {
285 let short_expect = if expected.len() > 6 {
286 format!("{} possible tokens", expected.len())
287 } else {
288 expect.clone()
289 };
290 (format!("expected one of {}, found {}", expect, actual),
291 (self.sess.source_map().next_point(self.prev_span),
292 format!("expected one of {} here", short_expect)))
293 } else if expected.is_empty() {
294 (format!("unexpected token: {}", actual),
295 (self.prev_span, "unexpected token after this".to_string()))
296 } else {
297 (format!("expected {}, found {}", expect, actual),
298 (self.sess.source_map().next_point(self.prev_span),
299 format!("expected {}", expect)))
300 };
301 self.last_unexpected_token_span = Some(self.token.span);
302 let mut err = self.fatal(&msg_exp);
303 if self.token.is_ident_named(sym::and) {
304 err.span_suggestion_short(
305 self.token.span,
306 "use `&&` instead of `and` for the boolean operator",
307 "&&".to_string(),
308 Applicability::MaybeIncorrect,
309 );
310 }
311 if self.token.is_ident_named(sym::or) {
312 err.span_suggestion_short(
313 self.token.span,
314 "use `||` instead of `or` for the boolean operator",
315 "||".to_string(),
316 Applicability::MaybeIncorrect,
317 );
318 }
319 let sp = if self.token == token::Eof {
320 // This is EOF; don't want to point at the following char, but rather the last token.
321 self.prev_span
322 } else {
323 label_sp
324 };
325 match self.recover_closing_delimiter(&expected.iter().filter_map(|tt| match tt {
326 TokenType::Token(t) => Some(t.clone()),
327 _ => None,
328 }).collect::<Vec<_>>(), err) {
329 Err(e) => err = e,
330 Ok(recovered) => {
331 return Ok(recovered);
332 }
333 }
334
335 let sm = self.sess.source_map();
336 if self.prev_span == DUMMY_SP {
337 // Account for macro context where the previous span might not be
338 // available to avoid incorrect output (#54841).
339 err.span_label(self.token.span, label_exp);
340 } else if !sm.is_multiline(self.token.span.shrink_to_hi().until(sp.shrink_to_lo())) {
341 // When the spans are in the same line, it means that the only content between
342 // them is whitespace, point at the found token in that case:
343 //
344 // X | () => { syntax error };
345 // | ^^^^^ expected one of 8 possible tokens here
346 //
347 // instead of having:
348 //
349 // X | () => { syntax error };
350 // | -^^^^^ unexpected token
351 // | |
352 // | expected one of 8 possible tokens here
353 err.span_label(self.token.span, label_exp);
354 } else {
355 err.span_label(sp, label_exp);
356 err.span_label(self.token.span, "unexpected token");
357 }
358 self.maybe_annotate_with_ascription(&mut err, false);
359 Err(err)
360 }
361
362 pub fn maybe_annotate_with_ascription(
363 &self,
364 err: &mut DiagnosticBuilder<'_>,
365 maybe_expected_semicolon: bool,
366 ) {
367 if let Some((sp, likely_path)) = self.last_type_ascription {
368 let sm = self.sess.source_map();
369 let next_pos = sm.lookup_char_pos(self.token.span.lo());
370 let op_pos = sm.lookup_char_pos(sp.hi());
371
372 let allow_unstable = self.sess.unstable_features.is_nightly_build();
373
374 if likely_path {
375 err.span_suggestion(
376 sp,
377 "maybe write a path separator here",
378 "::".to_string(),
379 if allow_unstable {
380 Applicability::MaybeIncorrect
381 } else {
382 Applicability::MachineApplicable
383 },
384 );
385 } else if op_pos.line != next_pos.line && maybe_expected_semicolon {
386 err.span_suggestion(
387 sp,
388 "try using a semicolon",
389 ";".to_string(),
390 Applicability::MaybeIncorrect,
391 );
392 } else if allow_unstable {
393 err.span_label(sp, "tried to parse a type due to this type ascription");
394 } else {
395 err.span_label(sp, "tried to parse a type due to this");
396 }
397 if allow_unstable {
398 // Give extra information about type ascription only if it's a nightly compiler.
399 err.note("`#![feature(type_ascription)]` lets you annotate an expression with a \
400 type: `<expr>: <type>`");
401 err.note("for more information, see \
402 https://github.com/rust-lang/rust/issues/23416");
403 }
404 }
405 }
406
407 /// Eats and discards tokens until one of `kets` is encountered. Respects token trees,
408 /// passes through any errors encountered. Used for error recovery.
409 pub(super) fn eat_to_tokens(&mut self, kets: &[&TokenKind]) {
410 if let Err(ref mut err) = self.parse_seq_to_before_tokens(
411 kets,
412 SeqSep::none(),
413 TokenExpectType::Expect,
414 |p| Ok(p.parse_token_tree()),
415 ) {
416 err.cancel();
417 }
418 }
419
420 /// This function checks if there are trailing angle brackets and produces
421 /// a diagnostic to suggest removing them.
422 ///
423 /// ```ignore (diagnostic)
424 /// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
425 /// ^^ help: remove extra angle brackets
426 /// ```
427 pub(super) fn check_trailing_angle_brackets(&mut self, segment: &PathSegment, end: TokenKind) {
428 // This function is intended to be invoked after parsing a path segment where there are two
429 // cases:
430 //
431 // 1. A specific token is expected after the path segment.
432 // eg. `x.foo(`, `x.foo::<u32>(` (parenthesis - method call),
433 // `Foo::`, or `Foo::<Bar>::` (mod sep - continued path).
434 // 2. No specific token is expected after the path segment.
435 // eg. `x.foo` (field access)
436 //
437 // This function is called after parsing `.foo` and before parsing the token `end` (if
438 // present). This includes any angle bracket arguments, such as `.foo::<u32>` or
439 // `Foo::<Bar>`.
440
441 // We only care about trailing angle brackets if we previously parsed angle bracket
442 // arguments. This helps stop us incorrectly suggesting that extra angle brackets be
443 // removed in this case:
444 //
445 // `x.foo >> (3)` (where `x.foo` is a `u32` for example)
446 //
447 // This case is particularly tricky as we won't notice it just looking at the tokens -
448 // it will appear the same (in terms of upcoming tokens) as below (since the `::<u32>` will
449 // have already been parsed):
450 //
451 // `x.foo::<u32>>>(3)`
452 let parsed_angle_bracket_args = segment.args
453 .as_ref()
454 .map(|args| args.is_angle_bracketed())
455 .unwrap_or(false);
456
457 debug!(
458 "check_trailing_angle_brackets: parsed_angle_bracket_args={:?}",
459 parsed_angle_bracket_args,
460 );
461 if !parsed_angle_bracket_args {
462 return;
463 }
464
465 // Keep the span at the start so we can highlight the sequence of `>` characters to be
466 // removed.
467 let lo = self.token.span;
468
469 // We need to look-ahead to see if we have `>` characters without moving the cursor forward
470 // (since we might have the field access case and the characters we're eating are
471 // actual operators and not trailing characters - ie `x.foo >> 3`).
472 let mut position = 0;
473
474 // We can encounter `>` or `>>` tokens in any order, so we need to keep track of how
475 // many of each (so we can correctly pluralize our error messages) and continue to
476 // advance.
477 let mut number_of_shr = 0;
478 let mut number_of_gt = 0;
479 while self.look_ahead(position, |t| {
480 trace!("check_trailing_angle_brackets: t={:?}", t);
481 if *t == token::BinOp(token::BinOpToken::Shr) {
482 number_of_shr += 1;
483 true
484 } else if *t == token::Gt {
485 number_of_gt += 1;
486 true
487 } else {
488 false
489 }
490 }) {
491 position += 1;
492 }
493
494 // If we didn't find any trailing `>` characters, then we have nothing to error about.
495 debug!(
496 "check_trailing_angle_brackets: number_of_gt={:?} number_of_shr={:?}",
497 number_of_gt, number_of_shr,
498 );
499 if number_of_gt < 1 && number_of_shr < 1 {
500 return;
501 }
502
503 // Finally, double check that we have our end token as otherwise this is the
504 // second case.
505 if self.look_ahead(position, |t| {
506 trace!("check_trailing_angle_brackets: t={:?}", t);
507 *t == end
508 }) {
509 // Eat from where we started until the end token so that parsing can continue
510 // as if we didn't have those extra angle brackets.
511 self.eat_to_tokens(&[&end]);
512 let span = lo.until(self.token.span);
513
514 let total_num_of_gt = number_of_gt + number_of_shr * 2;
515 self.diagnostic()
516 .struct_span_err(
517 span,
518 &format!("unmatched angle bracket{}", pluralise!(total_num_of_gt)),
519 )
520 .span_suggestion(
521 span,
522 &format!("remove extra angle bracket{}", pluralise!(total_num_of_gt)),
523 String::new(),
524 Applicability::MachineApplicable,
525 )
526 .emit();
527 }
528 }
529
530 /// Produces an error if comparison operators are chained (RFC #558).
531 /// We only need to check the LHS, not the RHS, because all comparison ops have same
532 /// precedence (see `fn precedence`) and are left-associative (see `fn fixity`).
533 ///
534 /// This can also be hit if someone incorrectly writes `foo<bar>()` when they should have used
535 /// the turbofish (`foo::<bar>()`) syntax. We attempt some heuristic recovery if that is the
536 /// case.
537 ///
538 /// Keep in mind that given that `outer_op.is_comparison()` holds and comparison ops are left
539 /// associative we can infer that we have:
540 ///
541 /// outer_op
542 /// / \
543 /// inner_op r2
544 /// / \
545 /// l1 r1
546 pub(super) fn check_no_chained_comparison(
547 &mut self,
548 lhs: &Expr,
549 outer_op: &AssocOp,
550 ) -> PResult<'a, Option<P<Expr>>> {
551 debug_assert!(
552 outer_op.is_comparison(),
553 "check_no_chained_comparison: {:?} is not comparison",
554 outer_op,
555 );
556
557 let mk_err_expr = |this: &Self, span| {
558 Ok(Some(this.mk_expr(span, ExprKind::Err, ThinVec::new())))
559 };
560
561 match lhs.kind {
562 ExprKind::Binary(op, _, _) if op.node.is_comparison() => {
563 // Respan to include both operators.
564 let op_span = op.span.to(self.prev_span);
565 let mut err = self.struct_span_err(
566 op_span,
567 "chained comparison operators require parentheses",
568 );
569
570 let suggest = |err: &mut DiagnosticBuilder<'_>| {
571 err.span_suggestion_verbose(
572 op_span.shrink_to_lo(),
573 TURBOFISH,
574 "::".to_string(),
575 Applicability::MaybeIncorrect,
576 );
577 };
578
579 if op.node == BinOpKind::Lt &&
580 *outer_op == AssocOp::Less || // Include `<` to provide this recommendation
581 *outer_op == AssocOp::Greater // even in a case like the following:
582 { // Foo<Bar<Baz<Qux, ()>>>
583 if *outer_op == AssocOp::Less {
584 let snapshot = self.clone();
585 self.bump();
586 // So far we have parsed `foo<bar<`, consume the rest of the type args.
587 let modifiers = [
588 (token::Lt, 1),
589 (token::Gt, -1),
590 (token::BinOp(token::Shr), -2),
591 ];
592 self.consume_tts(1, &modifiers[..]);
593
594 if !&[
595 token::OpenDelim(token::Paren),
596 token::ModSep,
597 ].contains(&self.token.kind) {
598 // We don't have `foo< bar >(` or `foo< bar >::`, so we rewind the
599 // parser and bail out.
600 mem::replace(self, snapshot.clone());
601 }
602 }
603 return if token::ModSep == self.token.kind {
604 // We have some certainty that this was a bad turbofish at this point.
605 // `foo< bar >::`
606 suggest(&mut err);
607
608 let snapshot = self.clone();
609 self.bump(); // `::`
610
611 // Consume the rest of the likely `foo<bar>::new()` or return at `foo<bar>`.
612 match self.parse_expr() {
613 Ok(_) => {
614 // 99% certain that the suggestion is correct, continue parsing.
615 err.emit();
616 // FIXME: actually check that the two expressions in the binop are
617 // paths and resynthesize new fn call expression instead of using
618 // `ExprKind::Err` placeholder.
619 mk_err_expr(self, lhs.span.to(self.prev_span))
620 }
621 Err(mut expr_err) => {
622 expr_err.cancel();
623 // Not entirely sure now, but we bubble the error up with the
624 // suggestion.
625 mem::replace(self, snapshot);
626 Err(err)
627 }
628 }
629 } else if token::OpenDelim(token::Paren) == self.token.kind {
630 // We have high certainty that this was a bad turbofish at this point.
631 // `foo< bar >(`
632 suggest(&mut err);
633 // Consume the fn call arguments.
634 match self.consume_fn_args() {
635 Err(()) => Err(err),
636 Ok(()) => {
637 err.emit();
638 // FIXME: actually check that the two expressions in the binop are
639 // paths and resynthesize new fn call expression instead of using
640 // `ExprKind::Err` placeholder.
641 mk_err_expr(self, lhs.span.to(self.prev_span))
642 }
643 }
644 } else {
645 // All we know is that this is `foo < bar >` and *nothing* else. Try to
646 // be helpful, but don't attempt to recover.
647 err.help(TURBOFISH);
648 err.help("or use `(...)` if you meant to specify fn arguments");
649 // These cases cause too many knock-down errors, bail out (#61329).
650 Err(err)
651 };
652 }
653 err.emit();
654 }
655 _ => {}
656 }
657 Ok(None)
658 }
659
660 fn consume_fn_args(&mut self) -> Result<(), ()> {
661 let snapshot = self.clone();
662 self.bump(); // `(`
663
664 // Consume the fn call arguments.
665 let modifiers = [
666 (token::OpenDelim(token::Paren), 1),
667 (token::CloseDelim(token::Paren), -1),
668 ];
669 self.consume_tts(1, &modifiers[..]);
670
671 if self.token.kind == token::Eof {
672 // Not entirely sure that what we consumed were fn arguments, rollback.
673 mem::replace(self, snapshot);
674 Err(())
675 } else {
676 // 99% certain that the suggestion is correct, continue parsing.
677 Ok(())
678 }
679 }
680
681 pub(super) fn maybe_report_ambiguous_plus(
682 &mut self,
683 allow_plus: bool,
684 impl_dyn_multi: bool,
685 ty: &Ty,
686 ) {
687 if !allow_plus && impl_dyn_multi {
688 let sum_with_parens = format!("({})", pprust::ty_to_string(&ty));
689 self.struct_span_err(ty.span, "ambiguous `+` in a type")
690 .span_suggestion(
691 ty.span,
692 "use parentheses to disambiguate",
693 sum_with_parens,
694 Applicability::MachineApplicable,
695 )
696 .emit();
697 }
698 }
699
700 pub(super) fn maybe_recover_from_bad_type_plus(
701 &mut self,
702 allow_plus: bool,
703 ty: &Ty,
704 ) -> PResult<'a, ()> {
705 // Do not add `+` to expected tokens.
706 if !allow_plus || !self.token.is_like_plus() {
707 return Ok(());
708 }
709
710 self.bump(); // `+`
711 let bounds = self.parse_generic_bounds(None)?;
712 let sum_span = ty.span.to(self.prev_span);
713
714 let mut err = struct_span_err!(
715 self.sess.span_diagnostic,
716 sum_span,
717 E0178,
718 "expected a path on the left-hand side of `+`, not `{}`",
719 pprust::ty_to_string(ty)
720 );
721
722 match ty.kind {
723 TyKind::Rptr(ref lifetime, ref mut_ty) => {
724 let sum_with_parens = pprust::to_string(|s| {
725 s.s.word("&");
726 s.print_opt_lifetime(lifetime);
727 s.print_mutability(mut_ty.mutbl);
728 s.popen();
729 s.print_type(&mut_ty.ty);
730 s.print_type_bounds(" +", &bounds);
731 s.pclose()
732 });
733 err.span_suggestion(
734 sum_span,
735 "try adding parentheses",
736 sum_with_parens,
737 Applicability::MachineApplicable,
738 );
739 }
740 TyKind::Ptr(..) | TyKind::BareFn(..) => {
741 err.span_label(sum_span, "perhaps you forgot parentheses?");
742 }
743 _ => {
744 err.span_label(sum_span, "expected a path");
745 }
746 }
747 err.emit();
748 Ok(())
749 }
750
751 /// Tries to recover from associated item paths like `[T]::AssocItem` / `(T, U)::AssocItem`.
752 /// Attempts to convert the base expression/pattern/type into a type, parses the `::AssocItem`
753 /// tail, and combines them into a `<Ty>::AssocItem` expression/pattern/type.
754 pub(super) fn maybe_recover_from_bad_qpath<T: RecoverQPath>(
755 &mut self,
756 base: P<T>,
757 allow_recovery: bool,
758 ) -> PResult<'a, P<T>> {
759 // Do not add `::` to expected tokens.
760 if allow_recovery && self.token == token::ModSep {
761 if let Some(ty) = base.to_ty() {
762 return self.maybe_recover_from_bad_qpath_stage_2(ty.span, ty);
763 }
764 }
765 Ok(base)
766 }
767
768 /// Given an already parsed `Ty`, parses the `::AssocItem` tail and
769 /// combines them into a `<Ty>::AssocItem` expression/pattern/type.
770 pub(super) fn maybe_recover_from_bad_qpath_stage_2<T: RecoverQPath>(
771 &mut self,
772 ty_span: Span,
773 ty: P<Ty>,
774 ) -> PResult<'a, P<T>> {
775 self.expect(&token::ModSep)?;
776
777 let mut path = ast::Path {
778 segments: Vec::new(),
779 span: DUMMY_SP,
780 };
781 self.parse_path_segments(&mut path.segments, T::PATH_STYLE)?;
782 path.span = ty_span.to(self.prev_span);
783
784 let ty_str = self
785 .span_to_snippet(ty_span)
786 .unwrap_or_else(|_| pprust::ty_to_string(&ty));
787 self.diagnostic()
788 .struct_span_err(path.span, "missing angle brackets in associated item path")
789 .span_suggestion(
790 // This is a best-effort recovery.
791 path.span,
792 "try",
793 format!("<{}>::{}", ty_str, pprust::path_to_string(&path)),
794 Applicability::MaybeIncorrect,
795 )
796 .emit();
797
798 let path_span = ty_span.shrink_to_hi(); // Use an empty path since `position == 0`.
799 Ok(P(T::recovered(
800 Some(QSelf {
801 ty,
802 path_span,
803 position: 0,
804 }),
805 path,
806 )))
807 }
808
809 pub(super) fn maybe_consume_incorrect_semicolon(&mut self, items: &[P<Item>]) -> bool {
810 if self.eat(&token::Semi) {
811 let mut err = self.struct_span_err(self.prev_span, "expected item, found `;`");
812 err.span_suggestion_short(
813 self.prev_span,
814 "remove this semicolon",
815 String::new(),
816 Applicability::MachineApplicable,
817 );
818 if !items.is_empty() {
819 let previous_item = &items[items.len() - 1];
820 let previous_item_kind_name = match previous_item.kind {
821 // Say "braced struct" because tuple-structs and
822 // braceless-empty-struct declarations do take a semicolon.
823 ItemKind::Struct(..) => Some("braced struct"),
824 ItemKind::Enum(..) => Some("enum"),
825 ItemKind::Trait(..) => Some("trait"),
826 ItemKind::Union(..) => Some("union"),
827 _ => None,
828 };
829 if let Some(name) = previous_item_kind_name {
830 err.help(&format!(
831 "{} declarations are not followed by a semicolon",
832 name
833 ));
834 }
835 }
836 err.emit();
837 true
838 } else {
839 false
840 }
841 }
842
843 /// Creates a `DiagnosticBuilder` for an unexpected token `t` and tries to recover if it is a
844 /// closing delimiter.
845 pub(super) fn unexpected_try_recover(
846 &mut self,
847 t: &TokenKind,
848 ) -> PResult<'a, bool /* recovered */> {
849 let token_str = pprust::token_kind_to_string(t);
850 let this_token_str = self.this_token_descr();
851 let (prev_sp, sp) = match (&self.token.kind, self.subparser_name) {
852 // Point at the end of the macro call when reaching end of macro arguments.
853 (token::Eof, Some(_)) => {
854 let sp = self.sess.source_map().next_point(self.token.span);
855 (sp, sp)
856 }
857 // We don't want to point at the following span after DUMMY_SP.
858 // This happens when the parser finds an empty TokenStream.
859 _ if self.prev_span == DUMMY_SP => (self.token.span, self.token.span),
860 // EOF, don't want to point at the following char, but rather the last token.
861 (token::Eof, None) => (self.prev_span, self.token.span),
862 _ => (self.sess.source_map().next_point(self.prev_span), self.token.span),
863 };
864 let msg = format!(
865 "expected `{}`, found {}",
866 token_str,
867 match (&self.token.kind, self.subparser_name) {
868 (token::Eof, Some(origin)) => format!("end of {}", origin),
869 _ => this_token_str,
870 },
871 );
872 let mut err = self.struct_span_err(sp, &msg);
873 let label_exp = format!("expected `{}`", token_str);
874 match self.recover_closing_delimiter(&[t.clone()], err) {
875 Err(e) => err = e,
876 Ok(recovered) => {
877 return Ok(recovered);
878 }
879 }
880 let sm = self.sess.source_map();
881 if !sm.is_multiline(prev_sp.until(sp)) {
882 // When the spans are in the same line, it means that the only content
883 // between them is whitespace, point only at the found token.
884 err.span_label(sp, label_exp);
885 } else {
886 err.span_label(prev_sp, label_exp);
887 err.span_label(sp, "unexpected token");
888 }
889 Err(err)
890 }
891
892 pub(super) fn expect_semi(&mut self) -> PResult<'a, ()> {
893 if self.eat(&token::Semi) {
894 return Ok(());
895 }
896 let sm = self.sess.source_map();
897 let msg = format!("expected `;`, found `{}`", self.this_token_descr());
898 let appl = Applicability::MachineApplicable;
899 if self.token.span == DUMMY_SP || self.prev_span == DUMMY_SP {
900 // Likely inside a macro, can't provide meaninful suggestions.
901 return self.expect(&token::Semi).map(|_| ());
902 } else if !sm.is_multiline(self.prev_span.until(self.token.span)) {
903 // The current token is in the same line as the prior token, not recoverable.
904 } else if self.look_ahead(1, |t| t == &token::CloseDelim(token::Brace)
905 || token_can_begin_expr(t) && t.kind != token::Colon
906 ) && [token::Comma, token::Colon].contains(&self.token.kind) {
907 // Likely typo: `,` → `;` or `:` → `;`. This is triggered if the current token is
908 // either `,` or `:`, and the next token could either start a new statement or is a
909 // block close. For example:
910 //
911 // let x = 32:
912 // let y = 42;
913 self.bump();
914 let sp = self.prev_span;
915 self.struct_span_err(sp, &msg)
916 .span_suggestion(sp, "change this to `;`", ";".to_string(), appl)
917 .emit();
918 return Ok(())
919 } else if self.look_ahead(0, |t| t == &token::CloseDelim(token::Brace) || (
920 token_can_begin_expr(t)
921 && t != &token::Semi
922 && t != &token::Pound // Avoid triggering with too many trailing `#` in raw string.
923 )) {
924 // Missing semicolon typo. This is triggered if the next token could either start a
925 // new statement or is a block close. For example:
926 //
927 // let x = 32
928 // let y = 42;
929 let sp = self.prev_span.shrink_to_hi();
930 self.struct_span_err(sp, &msg)
931 .span_label(self.token.span, "unexpected token")
932 .span_suggestion_short(sp, "add `;` here", ";".to_string(), appl)
933 .emit();
934 return Ok(())
935 }
936 self.expect(&token::Semi).map(|_| ()) // Error unconditionally
937 }
938
939 pub(super) fn parse_semi_or_incorrect_foreign_fn_body(
940 &mut self,
941 ident: &Ident,
942 extern_sp: Span,
943 ) -> PResult<'a, ()> {
944 if self.token != token::Semi {
945 // This might be an incorrect fn definition (#62109).
946 let parser_snapshot = self.clone();
947 match self.parse_inner_attrs_and_block() {
948 Ok((_, body)) => {
949 self.struct_span_err(ident.span, "incorrect `fn` inside `extern` block")
950 .span_label(ident.span, "can't have a body")
951 .span_label(body.span, "this body is invalid here")
952 .span_label(
953 extern_sp,
954 "`extern` blocks define existing foreign functions and `fn`s \
955 inside of them cannot have a body")
956 .help("you might have meant to write a function accessible through ffi, \
957 which can be done by writing `extern fn` outside of the \
958 `extern` block")
959 .note("for more information, visit \
960 https://doc.rust-lang.org/std/keyword.extern.html")
961 .emit();
962 }
963 Err(mut err) => {
964 err.cancel();
965 mem::replace(self, parser_snapshot);
966 self.expect_semi()?;
967 }
968 }
969 } else {
970 self.bump();
971 }
972 Ok(())
973 }
974
975 /// Consumes alternative await syntaxes like `await!(<expr>)`, `await <expr>`,
976 /// `await? <expr>`, `await(<expr>)`, and `await { <expr> }`.
977 pub(super) fn parse_incorrect_await_syntax(
978 &mut self,
979 lo: Span,
980 await_sp: Span,
981 ) -> PResult<'a, (Span, ExprKind)> {
982 if self.token == token::Not {
983 // Handle `await!(<expr>)`.
984 self.expect(&token::Not)?;
985 self.expect(&token::OpenDelim(token::Paren))?;
986 let expr = self.parse_expr()?;
987 self.expect(&token::CloseDelim(token::Paren))?;
988 let sp = self.error_on_incorrect_await(lo, self.prev_span, &expr, false);
989 return Ok((sp, ExprKind::Await(expr)))
990 }
991
992 let is_question = self.eat(&token::Question); // Handle `await? <expr>`.
993 let expr = if self.token == token::OpenDelim(token::Brace) {
994 // Handle `await { <expr> }`.
995 // This needs to be handled separatedly from the next arm to avoid
996 // interpreting `await { <expr> }?` as `<expr>?.await`.
997 self.parse_block_expr(
998 None,
999 self.token.span,
1000 BlockCheckMode::Default,
1001 ThinVec::new(),
1002 )
1003 } else {
1004 self.parse_expr()
1005 }.map_err(|mut err| {
1006 err.span_label(await_sp, "while parsing this incorrect await expression");
1007 err
1008 })?;
1009 let sp = self.error_on_incorrect_await(lo, expr.span, &expr, is_question);
1010 Ok((sp, ExprKind::Await(expr)))
1011 }
1012
1013 fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: bool) -> Span {
1014 let expr_str = self.span_to_snippet(expr.span)
1015 .unwrap_or_else(|_| pprust::expr_to_string(&expr));
1016 let suggestion = format!("{}.await{}", expr_str, if is_question { "?" } else { "" });
1017 let sp = lo.to(hi);
1018 let app = match expr.kind {
1019 ExprKind::Try(_) => Applicability::MaybeIncorrect, // `await <expr>?`
1020 _ => Applicability::MachineApplicable,
1021 };
1022 self.struct_span_err(sp, "incorrect use of `await`")
1023 .span_suggestion(sp, "`await` is a postfix operation", suggestion, app)
1024 .emit();
1025 sp
1026 }
1027
1028 /// If encountering `future.await()`, consumes and emits an error.
1029 pub(super) fn recover_from_await_method_call(&mut self) {
1030 if self.token == token::OpenDelim(token::Paren) &&
1031 self.look_ahead(1, |t| t == &token::CloseDelim(token::Paren))
1032 {
1033 // future.await()
1034 let lo = self.token.span;
1035 self.bump(); // (
1036 let sp = lo.to(self.token.span);
1037 self.bump(); // )
1038 self.struct_span_err(sp, "incorrect use of `await`")
1039 .span_suggestion(
1040 sp,
1041 "`await` is not a method call, remove the parentheses",
1042 String::new(),
1043 Applicability::MachineApplicable,
1044 ).emit()
1045 }
1046 }
1047
1048 /// Recovers a situation like `for ( $pat in $expr )`
1049 /// and suggest writing `for $pat in $expr` instead.
1050 ///
1051 /// This should be called before parsing the `$block`.
1052 pub(super) fn recover_parens_around_for_head(
1053 &mut self,
1054 pat: P<Pat>,
1055 expr: &Expr,
1056 begin_paren: Option<Span>,
1057 ) -> P<Pat> {
1058 match (&self.token.kind, begin_paren) {
1059 (token::CloseDelim(token::Paren), Some(begin_par_sp)) => {
1060 self.bump();
1061
1062 let pat_str = self
1063 // Remove the `(` from the span of the pattern:
1064 .span_to_snippet(pat.span.trim_start(begin_par_sp).unwrap())
1065 .unwrap_or_else(|_| pprust::pat_to_string(&pat));
1066
1067 self.struct_span_err(self.prev_span, "unexpected closing `)`")
1068 .span_label(begin_par_sp, "opening `(`")
1069 .span_suggestion(
1070 begin_par_sp.to(self.prev_span),
1071 "remove parenthesis in `for` loop",
1072 format!("{} in {}", pat_str, pprust::expr_to_string(&expr)),
1073 // With e.g. `for (x) in y)` this would replace `(x) in y)`
1074 // with `x) in y)` which is syntactically invalid.
1075 // However, this is prevented before we get here.
1076 Applicability::MachineApplicable,
1077 )
1078 .emit();
1079
1080 // Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint.
1081 pat.and_then(|pat| match pat.kind {
1082 PatKind::Paren(pat) => pat,
1083 _ => P(pat),
1084 })
1085 }
1086 _ => pat,
1087 }
1088 }
1089
1090 pub(super) fn could_ascription_be_path(&self, node: &ast::ExprKind) -> bool {
1091 self.token.is_ident() &&
1092 if let ast::ExprKind::Path(..) = node { true } else { false } &&
1093 !self.token.is_reserved_ident() && // v `foo:bar(baz)`
1094 self.look_ahead(1, |t| t == &token::OpenDelim(token::Paren)) ||
1095 self.look_ahead(1, |t| t == &token::Lt) && // `foo:bar<baz`
1096 self.look_ahead(2, |t| t.is_ident()) ||
1097 self.look_ahead(1, |t| t == &token::Colon) && // `foo:bar:baz`
1098 self.look_ahead(2, |t| t.is_ident()) ||
1099 self.look_ahead(1, |t| t == &token::ModSep) &&
1100 (self.look_ahead(2, |t| t.is_ident()) || // `foo:bar::baz`
1101 self.look_ahead(2, |t| t == &token::Lt)) // `foo:bar::<baz>`
1102 }
1103
1104 pub(super) fn recover_seq_parse_error(
1105 &mut self,
1106 delim: token::DelimToken,
1107 lo: Span,
1108 result: PResult<'a, P<Expr>>,
1109 ) -> P<Expr> {
1110 match result {
1111 Ok(x) => x,
1112 Err(mut err) => {
1113 err.emit();
1114 // Recover from parse error, callers expect the closing delim to be consumed.
1115 self.consume_block(delim, ConsumeClosingDelim::Yes);
1116 self.mk_expr(lo.to(self.prev_span), ExprKind::Err, ThinVec::new())
1117 }
1118 }
1119 }
1120
1121 pub(super) fn recover_closing_delimiter(
1122 &mut self,
1123 tokens: &[TokenKind],
1124 mut err: DiagnosticBuilder<'a>,
1125 ) -> PResult<'a, bool> {
1126 let mut pos = None;
1127 // We want to use the last closing delim that would apply.
1128 for (i, unmatched) in self.unclosed_delims.iter().enumerate().rev() {
1129 if tokens.contains(&token::CloseDelim(unmatched.expected_delim))
1130 && Some(self.token.span) > unmatched.unclosed_span
1131 {
1132 pos = Some(i);
1133 }
1134 }
1135 match pos {
1136 Some(pos) => {
1137 // Recover and assume that the detected unclosed delimiter was meant for
1138 // this location. Emit the diagnostic and act as if the delimiter was
1139 // present for the parser's sake.
1140
1141 // Don't attempt to recover from this unclosed delimiter more than once.
1142 let unmatched = self.unclosed_delims.remove(pos);
1143 let delim = TokenType::Token(token::CloseDelim(unmatched.expected_delim));
1144 if unmatched.found_delim.is_none() {
1145 // We encountered `Eof`, set this fact here to avoid complaining about missing
1146 // `fn main()` when we found place to suggest the closing brace.
1147 *self.sess.reached_eof.borrow_mut() = true;
1148 }
1149
1150 // We want to suggest the inclusion of the closing delimiter where it makes
1151 // the most sense, which is immediately after the last token:
1152 //
1153 // {foo(bar {}}
1154 // - ^
1155 // | |
1156 // | help: `)` may belong here
1157 // |
1158 // unclosed delimiter
1159 if let Some(sp) = unmatched.unclosed_span {
1160 err.span_label(sp, "unclosed delimiter");
1161 }
1162 err.span_suggestion_short(
1163 self.sess.source_map().next_point(self.prev_span),
1164 &format!("{} may belong here", delim.to_string()),
1165 delim.to_string(),
1166 Applicability::MaybeIncorrect,
1167 );
1168 if unmatched.found_delim.is_none() {
1169 // Encountered `Eof` when lexing blocks. Do not recover here to avoid knockdown
1170 // errors which would be emitted elsewhere in the parser and let other error
1171 // recovery consume the rest of the file.
1172 Err(err)
1173 } else {
1174 err.emit();
1175 self.expected_tokens.clear(); // Reduce the number of errors.
1176 Ok(true)
1177 }
1178 }
1179 _ => Err(err),
1180 }
1181 }
1182
1183 /// Recovers from `pub` keyword in places where it seems _reasonable_ but isn't valid.
1184 pub(super) fn eat_bad_pub(&mut self) {
1185 // When `unclosed_delims` is populated, it means that the code being parsed is already
1186 // quite malformed, which might mean that, for example, a pub struct definition could be
1187 // parsed as being a trait item, which is invalid and this error would trigger
1188 // unconditionally, resulting in misleading diagnostics. Because of this, we only attempt
1189 // this nice to have recovery for code that is otherwise well formed.
1190 if self.token.is_keyword(kw::Pub) && self.unclosed_delims.is_empty() {
1191 match self.parse_visibility(false) {
1192 Ok(vis) => {
1193 self.diagnostic()
1194 .struct_span_err(vis.span, "unnecessary visibility qualifier")
1195 .span_label(vis.span, "`pub` not permitted here")
1196 .emit();
1197 }
1198 Err(mut err) => err.emit(),
1199 }
1200 }
1201 }
1202
1203 /// Eats tokens until we can be relatively sure we reached the end of the
1204 /// statement. This is something of a best-effort heuristic.
1205 ///
1206 /// We terminate when we find an unmatched `}` (without consuming it).
1207 pub(super) fn recover_stmt(&mut self) {
1208 self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore)
1209 }
1210
1211 /// If `break_on_semi` is `Break`, then we will stop consuming tokens after
1212 /// finding (and consuming) a `;` outside of `{}` or `[]` (note that this is
1213 /// approximate -- it can mean we break too early due to macros, but that
1214 /// should only lead to sub-optimal recovery, not inaccurate parsing).
1215 ///
1216 /// If `break_on_block` is `Break`, then we will stop consuming tokens
1217 /// after finding (and consuming) a brace-delimited block.
1218 pub(super) fn recover_stmt_(
1219 &mut self,
1220 break_on_semi: SemiColonMode,
1221 break_on_block: BlockMode,
1222 ) {
1223 let mut brace_depth = 0;
1224 let mut bracket_depth = 0;
1225 let mut in_block = false;
1226 debug!("recover_stmt_ enter loop (semi={:?}, block={:?})",
1227 break_on_semi, break_on_block);
1228 loop {
1229 debug!("recover_stmt_ loop {:?}", self.token);
1230 match self.token.kind {
1231 token::OpenDelim(token::DelimToken::Brace) => {
1232 brace_depth += 1;
1233 self.bump();
1234 if break_on_block == BlockMode::Break &&
1235 brace_depth == 1 &&
1236 bracket_depth == 0 {
1237 in_block = true;
1238 }
1239 }
1240 token::OpenDelim(token::DelimToken::Bracket) => {
1241 bracket_depth += 1;
1242 self.bump();
1243 }
1244 token::CloseDelim(token::DelimToken::Brace) => {
1245 if brace_depth == 0 {
1246 debug!("recover_stmt_ return - close delim {:?}", self.token);
1247 break;
1248 }
1249 brace_depth -= 1;
1250 self.bump();
1251 if in_block && bracket_depth == 0 && brace_depth == 0 {
1252 debug!("recover_stmt_ return - block end {:?}", self.token);
1253 break;
1254 }
1255 }
1256 token::CloseDelim(token::DelimToken::Bracket) => {
1257 bracket_depth -= 1;
1258 if bracket_depth < 0 {
1259 bracket_depth = 0;
1260 }
1261 self.bump();
1262 }
1263 token::Eof => {
1264 debug!("recover_stmt_ return - Eof");
1265 break;
1266 }
1267 token::Semi => {
1268 self.bump();
1269 if break_on_semi == SemiColonMode::Break &&
1270 brace_depth == 0 &&
1271 bracket_depth == 0 {
1272 debug!("recover_stmt_ return - Semi");
1273 break;
1274 }
1275 }
1276 token::Comma if break_on_semi == SemiColonMode::Comma &&
1277 brace_depth == 0 &&
1278 bracket_depth == 0 =>
1279 {
1280 debug!("recover_stmt_ return - Semi");
1281 break;
1282 }
1283 _ => {
1284 self.bump()
1285 }
1286 }
1287 }
1288 }
1289
1290 pub(super) fn check_for_for_in_in_typo(&mut self, in_span: Span) {
1291 if self.eat_keyword(kw::In) {
1292 // a common typo: `for _ in in bar {}`
1293 self.struct_span_err(self.prev_span, "expected iterable, found keyword `in`")
1294 .span_suggestion_short(
1295 in_span.until(self.prev_span),
1296 "remove the duplicated `in`",
1297 String::new(),
1298 Applicability::MachineApplicable,
1299 )
1300 .emit();
1301 }
1302 }
1303
1304 pub(super) fn expected_semi_or_open_brace<T>(&mut self) -> PResult<'a, T> {
1305 let token_str = self.this_token_descr();
1306 let mut err = self.fatal(&format!("expected `;` or `{{`, found {}", token_str));
1307 err.span_label(self.token.span, "expected `;` or `{`");
1308 Err(err)
1309 }
1310
1311 pub(super) fn eat_incorrect_doc_comment_for_param_type(&mut self) {
1312 if let token::DocComment(_) = self.token.kind {
1313 self.struct_span_err(
1314 self.token.span,
1315 "documentation comments cannot be applied to a function parameter's type",
1316 )
1317 .span_label(self.token.span, "doc comments are not allowed here")
1318 .emit();
1319 self.bump();
1320 } else if self.token == token::Pound && self.look_ahead(1, |t| {
1321 *t == token::OpenDelim(token::Bracket)
1322 }) {
1323 let lo = self.token.span;
1324 // Skip every token until next possible arg.
1325 while self.token != token::CloseDelim(token::Bracket) {
1326 self.bump();
1327 }
1328 let sp = lo.to(self.token.span);
1329 self.bump();
1330 self.struct_span_err(
1331 sp,
1332 "attributes cannot be applied to a function parameter's type",
1333 )
1334 .span_label(sp, "attributes are not allowed here")
1335 .emit();
1336 }
1337 }
1338
1339 pub(super) fn parameter_without_type(
1340 &mut self,
1341 err: &mut DiagnosticBuilder<'_>,
1342 pat: P<ast::Pat>,
1343 require_name: bool,
1344 is_self_allowed: bool,
1345 is_trait_item: bool,
1346 ) -> Option<Ident> {
1347 // If we find a pattern followed by an identifier, it could be an (incorrect)
1348 // C-style parameter declaration.
1349 if self.check_ident() && self.look_ahead(1, |t| {
1350 *t == token::Comma || *t == token::CloseDelim(token::Paren)
1351 }) { // `fn foo(String s) {}`
1352 let ident = self.parse_ident().unwrap();
1353 let span = pat.span.with_hi(ident.span.hi());
1354
1355 err.span_suggestion(
1356 span,
1357 "declare the type after the parameter binding",
1358 String::from("<identifier>: <type>"),
1359 Applicability::HasPlaceholders,
1360 );
1361 return Some(ident);
1362 } else if let PatKind::Ident(_, ident, _) = pat.kind {
1363 if require_name && (
1364 is_trait_item ||
1365 self.token == token::Comma ||
1366 self.token == token::Lt ||
1367 self.token == token::CloseDelim(token::Paren)
1368 ) { // `fn foo(a, b) {}`, `fn foo(a<x>, b<y>) {}` or `fn foo(usize, usize) {}`
1369 if is_self_allowed {
1370 err.span_suggestion(
1371 pat.span,
1372 "if this is a `self` type, give it a parameter name",
1373 format!("self: {}", ident),
1374 Applicability::MaybeIncorrect,
1375 );
1376 }
1377 // Avoid suggesting that `fn foo(HashMap<u32>)` is fixed with a change to
1378 // `fn foo(HashMap: TypeName<u32>)`.
1379 if self.token != token::Lt {
1380 err.span_suggestion(
1381 pat.span,
1382 "if this was a parameter name, give it a type",
1383 format!("{}: TypeName", ident),
1384 Applicability::HasPlaceholders,
1385 );
1386 }
1387 err.span_suggestion(
1388 pat.span,
1389 "if this is a type, explicitly ignore the parameter name",
1390 format!("_: {}", ident),
1391 Applicability::MachineApplicable,
1392 );
1393 err.note("anonymous parameters are removed in the 2018 edition (see RFC 1685)");
1394
1395 // Don't attempt to recover by using the `X` in `X<Y>` as the parameter name.
1396 return if self.token == token::Lt { None } else { Some(ident) };
1397 }
1398 }
1399 None
1400 }
1401
1402 pub(super) fn recover_arg_parse(&mut self) -> PResult<'a, (P<ast::Pat>, P<ast::Ty>)> {
1403 let pat = self.parse_pat(Some("argument name"))?;
1404 self.expect(&token::Colon)?;
1405 let ty = self.parse_ty()?;
1406
1407 self.diagnostic()
1408 .struct_span_err_with_code(
1409 pat.span,
1410 "patterns aren't allowed in methods without bodies",
1411 DiagnosticId::Error("E0642".into()),
1412 )
1413 .span_suggestion_short(
1414 pat.span,
1415 "give this argument a name or use an underscore to ignore it",
1416 "_".to_owned(),
1417 Applicability::MachineApplicable,
1418 )
1419 .emit();
1420
1421 // Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
1422 let pat = P(Pat {
1423 kind: PatKind::Wild,
1424 span: pat.span,
1425 id: ast::DUMMY_NODE_ID
1426 });
1427 Ok((pat, ty))
1428 }
1429
1430 pub(super) fn recover_bad_self_param(
1431 &mut self,
1432 mut param: ast::Param,
1433 is_trait_item: bool,
1434 ) -> PResult<'a, ast::Param> {
1435 let sp = param.pat.span;
1436 param.ty.kind = TyKind::Err;
1437 let mut err = self.struct_span_err(sp, "unexpected `self` parameter in function");
1438 if is_trait_item {
1439 err.span_label(sp, "must be the first associated function parameter");
1440 } else {
1441 err.span_label(sp, "not valid as function parameter");
1442 err.note("`self` is only valid as the first parameter of an associated function");
1443 }
1444 err.emit();
1445 Ok(param)
1446 }
1447
1448 pub(super) fn consume_block(
1449 &mut self,
1450 delim: token::DelimToken,
1451 consume_close: ConsumeClosingDelim,
1452 ) {
1453 let mut brace_depth = 0;
1454 loop {
1455 if self.eat(&token::OpenDelim(delim)) {
1456 brace_depth += 1;
1457 } else if self.check(&token::CloseDelim(delim)) {
1458 if brace_depth == 0 {
1459 if let ConsumeClosingDelim::Yes = consume_close {
1460 // Some of the callers of this method expect to be able to parse the
1461 // closing delimiter themselves, so we leave it alone. Otherwise we advance
1462 // the parser.
1463 self.bump();
1464 }
1465 return;
1466 } else {
1467 self.bump();
1468 brace_depth -= 1;
1469 continue;
1470 }
1471 } else if self.token == token::Eof || self.eat(&token::CloseDelim(token::NoDelim)) {
1472 return;
1473 } else {
1474 self.bump();
1475 }
1476 }
1477 }
1478
1479 pub(super) fn expected_expression_found(&self) -> DiagnosticBuilder<'a> {
1480 let (span, msg) = match (&self.token.kind, self.subparser_name) {
1481 (&token::Eof, Some(origin)) => {
1482 let sp = self.sess.source_map().next_point(self.token.span);
1483 (sp, format!("expected expression, found end of {}", origin))
1484 }
1485 _ => (self.token.span, format!(
1486 "expected expression, found {}",
1487 self.this_token_descr(),
1488 )),
1489 };
1490 let mut err = self.struct_span_err(span, &msg);
1491 let sp = self.sess.source_map().start_point(self.token.span);
1492 if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) {
1493 self.sess.expr_parentheses_needed(&mut err, *sp, None);
1494 }
1495 err.span_label(span, "expected expression");
1496 err
1497 }
1498
1499 fn consume_tts(
1500 &mut self,
1501 mut acc: i64, // `i64` because malformed code can have more closing delims than opening.
1502 // Not using `FxHashMap` due to `token::TokenKind: !Eq + !Hash`.
1503 modifier: &[(token::TokenKind, i64)],
1504 ) {
1505 while acc > 0 {
1506 if let Some((_, val)) = modifier.iter().find(|(t, _)| *t == self.token.kind) {
1507 acc += *val;
1508 }
1509 if self.token.kind == token::Eof {
1510 break;
1511 }
1512 self.bump();
1513 }
1514 }
1515
1516 /// Replace duplicated recovered parameters with `_` pattern to avoid unecessary errors.
1517 ///
1518 /// This is necessary because at this point we don't know whether we parsed a function with
1519 /// anonymous parameters or a function with names but no types. In order to minimize
1520 /// unecessary errors, we assume the parameters are in the shape of `fn foo(a, b, c)` where
1521 /// the parameters are *names* (so we don't emit errors about not being able to find `b` in
1522 /// the local scope), but if we find the same name multiple times, like in `fn foo(i8, i8)`,
1523 /// we deduplicate them to not complain about duplicated parameter names.
1524 pub(super) fn deduplicate_recovered_params_names(&self, fn_inputs: &mut Vec<Param>) {
1525 let mut seen_inputs = FxHashSet::default();
1526 for input in fn_inputs.iter_mut() {
1527 let opt_ident = if let (PatKind::Ident(_, ident, _), TyKind::Err) = (
1528 &input.pat.kind, &input.ty.kind,
1529 ) {
1530 Some(*ident)
1531 } else {
1532 None
1533 };
1534 if let Some(ident) = opt_ident {
1535 if seen_inputs.contains(&ident) {
1536 input.pat.kind = PatKind::Wild;
1537 }
1538 seen_inputs.insert(ident);
1539 }
1540 }
1541 }
1542 }