]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/parse/diagnostics.rs
Account for cases where we can find the type arg name, but the local name is `_`
[rust.git] / src / libsyntax / parse / diagnostics.rs
1 use crate::ast;
2 use crate::ast::{
3     BlockCheckMode, BinOpKind, Expr, ExprKind, Item, ItemKind, Pat, PatKind, PathSegment, QSelf,
4     Ty, TyKind, VariantData,
5 };
6 use crate::parse::{SeqSep, token, PResult, Parser};
7 use crate::parse::parser::{BlockMode, PathStyle, SemiColonMode, TokenType, TokenExpectType};
8 use crate::print::pprust;
9 use crate::ptr::P;
10 use crate::source_map::Spanned;
11 use crate::symbol::{kw, sym};
12 use crate::ThinVec;
13 use crate::util::parser::AssocOp;
14 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
15 use syntax_pos::{Span, DUMMY_SP, MultiSpan};
16 use log::{debug, trace};
17
18 pub enum Error {
19     FileNotFoundForModule {
20         mod_name: String,
21         default_path: String,
22         secondary_path: String,
23         dir_path: String,
24     },
25     DuplicatePaths {
26         mod_name: String,
27         default_path: String,
28         secondary_path: String,
29     },
30     UselessDocComment,
31     InclusiveRangeWithNoEnd,
32 }
33
34 impl Error {
35     fn span_err<S: Into<MultiSpan>>(
36         self,
37         sp: S,
38         handler: &errors::Handler,
39     ) -> DiagnosticBuilder<'_> {
40         match self {
41             Error::FileNotFoundForModule {
42                 ref mod_name,
43                 ref default_path,
44                 ref secondary_path,
45                 ref dir_path,
46             } => {
47                 let mut err = struct_span_err!(
48                     handler,
49                     sp,
50                     E0583,
51                     "file not found for module `{}`",
52                     mod_name,
53                 );
54                 err.help(&format!(
55                     "name the file either {} or {} inside the directory \"{}\"",
56                     default_path,
57                     secondary_path,
58                     dir_path,
59                 ));
60                 err
61             }
62             Error::DuplicatePaths { ref mod_name, ref default_path, ref secondary_path } => {
63                 let mut err = struct_span_err!(
64                     handler,
65                     sp,
66                     E0584,
67                     "file for module `{}` found at both {} and {}",
68                     mod_name,
69                     default_path,
70                     secondary_path,
71                 );
72                 err.help("delete or rename one of them to remove the ambiguity");
73                 err
74             }
75             Error::UselessDocComment => {
76                 let mut err = struct_span_err!(
77                     handler,
78                     sp,
79                     E0585,
80                     "found a documentation comment that doesn't document anything",
81                 );
82                 err.help("doc comments must come before what they document, maybe a comment was \
83                           intended with `//`?");
84                 err
85             }
86             Error::InclusiveRangeWithNoEnd => {
87                 let mut err = struct_span_err!(
88                     handler,
89                     sp,
90                     E0586,
91                     "inclusive range with no end",
92                 );
93                 err.help("inclusive ranges must be bounded at the end (`..=b` or `a..=b`)");
94                 err
95             }
96         }
97     }
98 }
99
100 pub trait RecoverQPath: Sized + 'static {
101     const PATH_STYLE: PathStyle = PathStyle::Expr;
102     fn to_ty(&self) -> Option<P<Ty>>;
103     fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self;
104 }
105
106 impl RecoverQPath for Ty {
107     const PATH_STYLE: PathStyle = PathStyle::Type;
108     fn to_ty(&self) -> Option<P<Ty>> {
109         Some(P(self.clone()))
110     }
111     fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self {
112         Self {
113             span: path.span,
114             node: TyKind::Path(qself, path),
115             id: ast::DUMMY_NODE_ID,
116         }
117     }
118 }
119
120 impl RecoverQPath for Pat {
121     fn to_ty(&self) -> Option<P<Ty>> {
122         self.to_ty()
123     }
124     fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self {
125         Self {
126             span: path.span,
127             node: PatKind::Path(qself, path),
128             id: ast::DUMMY_NODE_ID,
129         }
130     }
131 }
132
133 impl RecoverQPath for Expr {
134     fn to_ty(&self) -> Option<P<Ty>> {
135         self.to_ty()
136     }
137     fn recovered(qself: Option<QSelf>, path: ast::Path) -> Self {
138         Self {
139             span: path.span,
140             node: ExprKind::Path(qself, path),
141             attrs: ThinVec::new(),
142             id: ast::DUMMY_NODE_ID,
143         }
144     }
145 }
146
147 impl<'a> Parser<'a> {
148     pub fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> {
149         self.span_fatal(self.span, m)
150     }
151
152     pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
153         self.sess.span_diagnostic.struct_span_fatal(sp, m)
154     }
155
156     pub fn span_fatal_err<S: Into<MultiSpan>>(&self, sp: S, err: Error) -> DiagnosticBuilder<'a> {
157         err.span_err(sp, self.diagnostic())
158     }
159
160     pub fn bug(&self, m: &str) -> ! {
161         self.sess.span_diagnostic.span_bug(self.span, m)
162     }
163
164     pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) {
165         self.sess.span_diagnostic.span_err(sp, m)
166     }
167
168     crate fn struct_span_err<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> {
169         self.sess.span_diagnostic.struct_span_err(sp, m)
170     }
171
172     crate fn span_bug<S: Into<MultiSpan>>(&self, sp: S, m: &str) -> ! {
173         self.sess.span_diagnostic.span_bug(sp, m)
174     }
175
176     crate fn cancel(&self, err: &mut DiagnosticBuilder<'_>) {
177         self.sess.span_diagnostic.cancel(err)
178     }
179
180     crate fn diagnostic(&self) -> &'a errors::Handler {
181         &self.sess.span_diagnostic
182     }
183
184     crate fn expected_ident_found(&self) -> DiagnosticBuilder<'a> {
185         let mut err = self.struct_span_err(
186             self.span,
187             &format!("expected identifier, found {}", self.this_token_descr()),
188         );
189         if let token::Ident(ident, false) = &self.token {
190             if ident.is_raw_guess() {
191                 err.span_suggestion(
192                     self.span,
193                     "you can escape reserved keywords to use them as identifiers",
194                     format!("r#{}", ident),
195                     Applicability::MaybeIncorrect,
196                 );
197             }
198         }
199         if let Some(token_descr) = self.token_descr() {
200             err.span_label(self.span, format!("expected identifier, found {}", token_descr));
201         } else {
202             err.span_label(self.span, "expected identifier");
203             if self.token == token::Comma && self.look_ahead(1, |t| t.is_ident()) {
204                 err.span_suggestion(
205                     self.span,
206                     "remove this comma",
207                     String::new(),
208                     Applicability::MachineApplicable,
209                 );
210             }
211         }
212         err
213     }
214
215     pub fn expected_one_of_not_found(
216         &mut self,
217         edible: &[token::Token],
218         inedible: &[token::Token],
219     ) -> PResult<'a, bool /* recovered */> {
220         fn tokens_to_string(tokens: &[TokenType]) -> String {
221             let mut i = tokens.iter();
222             // This might be a sign we need a connect method on Iterator.
223             let b = i.next()
224                      .map_or(String::new(), |t| t.to_string());
225             i.enumerate().fold(b, |mut b, (i, a)| {
226                 if tokens.len() > 2 && i == tokens.len() - 2 {
227                     b.push_str(", or ");
228                 } else if tokens.len() == 2 && i == tokens.len() - 2 {
229                     b.push_str(" or ");
230                 } else {
231                     b.push_str(", ");
232                 }
233                 b.push_str(&a.to_string());
234                 b
235             })
236         }
237
238         let mut expected = edible.iter()
239             .map(|x| TokenType::Token(x.clone()))
240             .chain(inedible.iter().map(|x| TokenType::Token(x.clone())))
241             .chain(self.expected_tokens.iter().cloned())
242             .collect::<Vec<_>>();
243         expected.sort_by_cached_key(|x| x.to_string());
244         expected.dedup();
245         let expect = tokens_to_string(&expected[..]);
246         let actual = self.this_token_to_string();
247         let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 {
248             let short_expect = if expected.len() > 6 {
249                 format!("{} possible tokens", expected.len())
250             } else {
251                 expect.clone()
252             };
253             (format!("expected one of {}, found `{}`", expect, actual),
254                 (self.sess.source_map().next_point(self.prev_span),
255                 format!("expected one of {} here", short_expect)))
256         } else if expected.is_empty() {
257             (format!("unexpected token: `{}`", actual),
258                 (self.prev_span, "unexpected token after this".to_string()))
259         } else {
260             (format!("expected {}, found `{}`", expect, actual),
261                 (self.sess.source_map().next_point(self.prev_span),
262                 format!("expected {} here", expect)))
263         };
264         self.last_unexpected_token_span = Some(self.span);
265         let mut err = self.fatal(&msg_exp);
266         if self.token.is_ident_named(sym::and) {
267             err.span_suggestion_short(
268                 self.span,
269                 "use `&&` instead of `and` for the boolean operator",
270                 "&&".to_string(),
271                 Applicability::MaybeIncorrect,
272             );
273         }
274         if self.token.is_ident_named(sym::or) {
275             err.span_suggestion_short(
276                 self.span,
277                 "use `||` instead of `or` for the boolean operator",
278                 "||".to_string(),
279                 Applicability::MaybeIncorrect,
280             );
281         }
282         let sp = if self.token == token::Token::Eof {
283             // This is EOF, don't want to point at the following char, but rather the last token
284             self.prev_span
285         } else {
286             label_sp
287         };
288         match self.recover_closing_delimiter(&expected.iter().filter_map(|tt| match tt {
289             TokenType::Token(t) => Some(t.clone()),
290             _ => None,
291         }).collect::<Vec<_>>(), err) {
292             Err(e) => err = e,
293             Ok(recovered) => {
294                 return Ok(recovered);
295             }
296         }
297
298         let is_semi_suggestable = expected.iter().any(|t| match t {
299             TokenType::Token(token::Semi) => true, // we expect a `;` here
300             _ => false,
301         }) && ( // a `;` would be expected before the current keyword
302             self.token.is_keyword(kw::Break) ||
303             self.token.is_keyword(kw::Continue) ||
304             self.token.is_keyword(kw::For) ||
305             self.token.is_keyword(kw::If) ||
306             self.token.is_keyword(kw::Let) ||
307             self.token.is_keyword(kw::Loop) ||
308             self.token.is_keyword(kw::Match) ||
309             self.token.is_keyword(kw::Return) ||
310             self.token.is_keyword(kw::While)
311         );
312         let cm = self.sess.source_map();
313         match (cm.lookup_line(self.span.lo()), cm.lookup_line(sp.lo())) {
314             (Ok(ref a), Ok(ref b)) if a.line != b.line && is_semi_suggestable => {
315                 // The spans are in different lines, expected `;` and found `let` or `return`.
316                 // High likelihood that it is only a missing `;`.
317                 err.span_suggestion_short(
318                     label_sp,
319                     "a semicolon may be missing here",
320                     ";".to_string(),
321                     Applicability::MaybeIncorrect,
322                 );
323                 err.emit();
324                 return Ok(true);
325             }
326             (Ok(ref a), Ok(ref b)) if a.line == b.line => {
327                 // When the spans are in the same line, it means that the only content between
328                 // them is whitespace, point at the found token in that case:
329                 //
330                 // X |     () => { syntax error };
331                 //   |                    ^^^^^ expected one of 8 possible tokens here
332                 //
333                 // instead of having:
334                 //
335                 // X |     () => { syntax error };
336                 //   |                   -^^^^^ unexpected token
337                 //   |                   |
338                 //   |                   expected one of 8 possible tokens here
339                 err.span_label(self.span, label_exp);
340             }
341             _ if self.prev_span == syntax_pos::DUMMY_SP => {
342                 // Account for macro context where the previous span might not be
343                 // available to avoid incorrect output (#54841).
344                 err.span_label(self.span, "unexpected token");
345             }
346             _ => {
347                 err.span_label(sp, label_exp);
348                 err.span_label(self.span, "unexpected token");
349             }
350         }
351         Err(err)
352     }
353
354     /// Eats and discards tokens until one of `kets` is encountered. Respects token trees,
355     /// passes through any errors encountered. Used for error recovery.
356     crate fn eat_to_tokens(&mut self, kets: &[&token::Token]) {
357         let handler = self.diagnostic();
358
359         if let Err(ref mut err) = self.parse_seq_to_before_tokens(
360             kets,
361             SeqSep::none(),
362             TokenExpectType::Expect,
363             |p| Ok(p.parse_token_tree()),
364         ) {
365             handler.cancel(err);
366         }
367     }
368
369     /// This function checks if there are trailing angle brackets and produces
370     /// a diagnostic to suggest removing them.
371     ///
372     /// ```ignore (diagnostic)
373     /// let _ = vec![1, 2, 3].into_iter().collect::<Vec<usize>>>>();
374     ///                                                        ^^ help: remove extra angle brackets
375     /// ```
376     crate fn check_trailing_angle_brackets(&mut self, segment: &PathSegment, end: token::Token) {
377         // This function is intended to be invoked after parsing a path segment where there are two
378         // cases:
379         //
380         // 1. A specific token is expected after the path segment.
381         //    eg. `x.foo(`, `x.foo::<u32>(` (parenthesis - method call),
382         //        `Foo::`, or `Foo::<Bar>::` (mod sep - continued path).
383         // 2. No specific token is expected after the path segment.
384         //    eg. `x.foo` (field access)
385         //
386         // This function is called after parsing `.foo` and before parsing the token `end` (if
387         // present). This includes any angle bracket arguments, such as `.foo::<u32>` or
388         // `Foo::<Bar>`.
389
390         // We only care about trailing angle brackets if we previously parsed angle bracket
391         // arguments. This helps stop us incorrectly suggesting that extra angle brackets be
392         // removed in this case:
393         //
394         // `x.foo >> (3)` (where `x.foo` is a `u32` for example)
395         //
396         // This case is particularly tricky as we won't notice it just looking at the tokens -
397         // it will appear the same (in terms of upcoming tokens) as below (since the `::<u32>` will
398         // have already been parsed):
399         //
400         // `x.foo::<u32>>>(3)`
401         let parsed_angle_bracket_args = segment.args
402             .as_ref()
403             .map(|args| args.is_angle_bracketed())
404             .unwrap_or(false);
405
406         debug!(
407             "check_trailing_angle_brackets: parsed_angle_bracket_args={:?}",
408             parsed_angle_bracket_args,
409         );
410         if !parsed_angle_bracket_args {
411             return;
412         }
413
414         // Keep the span at the start so we can highlight the sequence of `>` characters to be
415         // removed.
416         let lo = self.span;
417
418         // We need to look-ahead to see if we have `>` characters without moving the cursor forward
419         // (since we might have the field access case and the characters we're eating are
420         // actual operators and not trailing characters - ie `x.foo >> 3`).
421         let mut position = 0;
422
423         // We can encounter `>` or `>>` tokens in any order, so we need to keep track of how
424         // many of each (so we can correctly pluralize our error messages) and continue to
425         // advance.
426         let mut number_of_shr = 0;
427         let mut number_of_gt = 0;
428         while self.look_ahead(position, |t| {
429             trace!("check_trailing_angle_brackets: t={:?}", t);
430             if *t == token::BinOp(token::BinOpToken::Shr) {
431                 number_of_shr += 1;
432                 true
433             } else if *t == token::Gt {
434                 number_of_gt += 1;
435                 true
436             } else {
437                 false
438             }
439         }) {
440             position += 1;
441         }
442
443         // If we didn't find any trailing `>` characters, then we have nothing to error about.
444         debug!(
445             "check_trailing_angle_brackets: number_of_gt={:?} number_of_shr={:?}",
446             number_of_gt, number_of_shr,
447         );
448         if number_of_gt < 1 && number_of_shr < 1 {
449             return;
450         }
451
452         // Finally, double check that we have our end token as otherwise this is the
453         // second case.
454         if self.look_ahead(position, |t| {
455             trace!("check_trailing_angle_brackets: t={:?}", t);
456             *t == end
457         }) {
458             // Eat from where we started until the end token so that parsing can continue
459             // as if we didn't have those extra angle brackets.
460             self.eat_to_tokens(&[&end]);
461             let span = lo.until(self.span);
462
463             let plural = number_of_gt > 1 || number_of_shr >= 1;
464             self.diagnostic()
465                 .struct_span_err(
466                     span,
467                     &format!("unmatched angle bracket{}", if plural { "s" } else { "" }),
468                 )
469                 .span_suggestion(
470                     span,
471                     &format!("remove extra angle bracket{}", if plural { "s" } else { "" }),
472                     String::new(),
473                     Applicability::MachineApplicable,
474                 )
475                 .emit();
476         }
477     }
478
479     /// Produce an error if comparison operators are chained (RFC #558).
480     /// We only need to check lhs, not rhs, because all comparison ops
481     /// have same precedence and are left-associative
482     crate fn check_no_chained_comparison(&self, lhs: &Expr, outer_op: &AssocOp) {
483         debug_assert!(outer_op.is_comparison(),
484                       "check_no_chained_comparison: {:?} is not comparison",
485                       outer_op);
486         match lhs.node {
487             ExprKind::Binary(op, _, _) if op.node.is_comparison() => {
488                 // respan to include both operators
489                 let op_span = op.span.to(self.span);
490                 let mut err = self.diagnostic().struct_span_err(op_span,
491                     "chained comparison operators require parentheses");
492                 if op.node == BinOpKind::Lt &&
493                     *outer_op == AssocOp::Less ||  // Include `<` to provide this recommendation
494                     *outer_op == AssocOp::Greater  // even in a case like the following:
495                 {                                  //     Foo<Bar<Baz<Qux, ()>>>
496                     err.help(
497                         "use `::<...>` instead of `<...>` if you meant to specify type arguments");
498                     err.help("or use `(...)` if you meant to specify fn arguments");
499                 }
500                 err.emit();
501             }
502             _ => {}
503         }
504     }
505
506     crate fn maybe_report_ambiguous_plus(
507         &mut self,
508         allow_plus: bool,
509         impl_dyn_multi: bool,
510         ty: &Ty,
511     ) {
512         if !allow_plus && impl_dyn_multi {
513             let sum_with_parens = format!("({})", pprust::ty_to_string(&ty));
514             self.struct_span_err(ty.span, "ambiguous `+` in a type")
515                 .span_suggestion(
516                     ty.span,
517                     "use parentheses to disambiguate",
518                     sum_with_parens,
519                     Applicability::MachineApplicable,
520                 )
521                 .emit();
522         }
523     }
524
525     crate fn maybe_report_invalid_custom_discriminants(
526         &mut self,
527         discriminant_spans: Vec<Span>,
528         variants: &[Spanned<ast::Variant_>],
529     ) {
530         let has_fields = variants.iter().any(|variant| match variant.node.data {
531             VariantData::Tuple(..) | VariantData::Struct(..) => true,
532             VariantData::Unit(..) => false,
533         });
534
535         if !discriminant_spans.is_empty() && has_fields {
536             let mut err = self.struct_span_err(
537                 discriminant_spans.clone(),
538                 "custom discriminant values are not allowed in enums with fields",
539             );
540             for sp in discriminant_spans {
541                 err.span_label(sp, "invalid custom discriminant");
542             }
543             for variant in variants.iter() {
544                 if let VariantData::Struct(fields, ..) | VariantData::Tuple(fields, ..) =
545                     &variant.node.data
546                 {
547                     let fields = if fields.len() > 1 {
548                         "fields"
549                     } else {
550                         "a field"
551                     };
552                     err.span_label(
553                         variant.span,
554                         &format!("variant with {fields} defined here", fields = fields),
555                     );
556
557                 }
558             }
559             err.emit();
560         }
561     }
562
563     crate fn maybe_recover_from_bad_type_plus(
564         &mut self,
565         allow_plus: bool,
566         ty: &Ty,
567     ) -> PResult<'a, ()> {
568         // Do not add `+` to expected tokens.
569         if !allow_plus || !self.token.is_like_plus() {
570             return Ok(());
571         }
572
573         self.bump(); // `+`
574         let bounds = self.parse_generic_bounds(None)?;
575         let sum_span = ty.span.to(self.prev_span);
576
577         let mut err = struct_span_err!(
578             self.sess.span_diagnostic,
579             sum_span,
580             E0178,
581             "expected a path on the left-hand side of `+`, not `{}`",
582             pprust::ty_to_string(ty)
583         );
584
585         match ty.node {
586             TyKind::Rptr(ref lifetime, ref mut_ty) => {
587                 let sum_with_parens = pprust::to_string(|s| {
588                     use crate::print::pprust::PrintState;
589
590                     s.s.word("&")?;
591                     s.print_opt_lifetime(lifetime)?;
592                     s.print_mutability(mut_ty.mutbl)?;
593                     s.popen()?;
594                     s.print_type(&mut_ty.ty)?;
595                     s.print_type_bounds(" +", &bounds)?;
596                     s.pclose()
597                 });
598                 err.span_suggestion(
599                     sum_span,
600                     "try adding parentheses",
601                     sum_with_parens,
602                     Applicability::MachineApplicable,
603                 );
604             }
605             TyKind::Ptr(..) | TyKind::BareFn(..) => {
606                 err.span_label(sum_span, "perhaps you forgot parentheses?");
607             }
608             _ => {
609                 err.span_label(sum_span, "expected a path");
610             }
611         }
612         err.emit();
613         Ok(())
614     }
615
616     /// Try to recover from associated item paths like `[T]::AssocItem`/`(T, U)::AssocItem`.
617     /// Attempt to convert the base expression/pattern/type into a type, parse the `::AssocItem`
618     /// tail, and combine them into a `<Ty>::AssocItem` expression/pattern/type.
619     crate fn maybe_recover_from_bad_qpath<T: RecoverQPath>(
620         &mut self,
621         base: P<T>,
622         allow_recovery: bool,
623     ) -> PResult<'a, P<T>> {
624         // Do not add `::` to expected tokens.
625         if allow_recovery && self.token == token::ModSep {
626             if let Some(ty) = base.to_ty() {
627                 return self.maybe_recover_from_bad_qpath_stage_2(ty.span, ty);
628             }
629         }
630         Ok(base)
631     }
632
633     /// Given an already parsed `Ty` parse the `::AssocItem` tail and
634     /// combine them into a `<Ty>::AssocItem` expression/pattern/type.
635     crate fn maybe_recover_from_bad_qpath_stage_2<T: RecoverQPath>(
636         &mut self,
637         ty_span: Span,
638         ty: P<Ty>,
639     ) -> PResult<'a, P<T>> {
640         self.expect(&token::ModSep)?;
641
642         let mut path = ast::Path {
643             segments: Vec::new(),
644             span: DUMMY_SP,
645         };
646         self.parse_path_segments(&mut path.segments, T::PATH_STYLE)?;
647         path.span = ty_span.to(self.prev_span);
648
649         let ty_str = self
650             .sess
651             .source_map()
652             .span_to_snippet(ty_span)
653             .unwrap_or_else(|_| pprust::ty_to_string(&ty));
654         self.diagnostic()
655             .struct_span_err(path.span, "missing angle brackets in associated item path")
656             .span_suggestion(
657                 // this is a best-effort recovery
658                 path.span,
659                 "try",
660                 format!("<{}>::{}", ty_str, path),
661                 Applicability::MaybeIncorrect,
662             )
663             .emit();
664
665         let path_span = ty_span.shrink_to_hi(); // use an empty path since `position` == 0
666         Ok(P(T::recovered(
667             Some(QSelf {
668                 ty,
669                 path_span,
670                 position: 0,
671             }),
672             path,
673         )))
674     }
675
676     crate fn maybe_consume_incorrect_semicolon(&mut self, items: &[P<Item>]) -> bool {
677         if self.eat(&token::Semi) {
678             let mut err = self.struct_span_err(self.prev_span, "expected item, found `;`");
679             err.span_suggestion_short(
680                 self.prev_span,
681                 "remove this semicolon",
682                 String::new(),
683                 Applicability::MachineApplicable,
684             );
685             if !items.is_empty() {
686                 let previous_item = &items[items.len() - 1];
687                 let previous_item_kind_name = match previous_item.node {
688                     // say "braced struct" because tuple-structs and
689                     // braceless-empty-struct declarations do take a semicolon
690                     ItemKind::Struct(..) => Some("braced struct"),
691                     ItemKind::Enum(..) => Some("enum"),
692                     ItemKind::Trait(..) => Some("trait"),
693                     ItemKind::Union(..) => Some("union"),
694                     _ => None,
695                 };
696                 if let Some(name) = previous_item_kind_name {
697                     err.help(&format!(
698                         "{} declarations are not followed by a semicolon",
699                         name
700                     ));
701                 }
702             }
703             err.emit();
704             true
705         } else {
706             false
707         }
708     }
709
710     /// Create a `DiagnosticBuilder` for an unexpected token `t` and try to recover if it is a
711     /// closing delimiter.
712     pub fn unexpected_try_recover(
713         &mut self,
714         t: &token::Token,
715     ) -> PResult<'a, bool /* recovered */> {
716         let token_str = pprust::token_to_string(t);
717         let this_token_str = self.this_token_descr();
718         let (prev_sp, sp) = match (&self.token, self.subparser_name) {
719             // Point at the end of the macro call when reaching end of macro arguments.
720             (token::Token::Eof, Some(_)) => {
721                 let sp = self.sess.source_map().next_point(self.span);
722                 (sp, sp)
723             }
724             // We don't want to point at the following span after DUMMY_SP.
725             // This happens when the parser finds an empty TokenStream.
726             _ if self.prev_span == DUMMY_SP => (self.span, self.span),
727             // EOF, don't want to point at the following char, but rather the last token.
728             (token::Token::Eof, None) => (self.prev_span, self.span),
729             _ => (self.sess.source_map().next_point(self.prev_span), self.span),
730         };
731         let msg = format!(
732             "expected `{}`, found {}",
733             token_str,
734             match (&self.token, self.subparser_name) {
735                 (token::Token::Eof, Some(origin)) => format!("end of {}", origin),
736                 _ => this_token_str,
737             },
738         );
739         let mut err = self.struct_span_err(sp, &msg);
740         let label_exp = format!("expected `{}`", token_str);
741         match self.recover_closing_delimiter(&[t.clone()], err) {
742             Err(e) => err = e,
743             Ok(recovered) => {
744                 return Ok(recovered);
745             }
746         }
747         let cm = self.sess.source_map();
748         match (cm.lookup_line(prev_sp.lo()), cm.lookup_line(sp.lo())) {
749             (Ok(ref a), Ok(ref b)) if a.line == b.line => {
750                 // When the spans are in the same line, it means that the only content
751                 // between them is whitespace, point only at the found token.
752                 err.span_label(sp, label_exp);
753             }
754             _ => {
755                 err.span_label(prev_sp, label_exp);
756                 err.span_label(sp, "unexpected token");
757             }
758         }
759         Err(err)
760     }
761
762     /// Consume alternative await syntaxes like `await <expr>`, `await? <expr>`, `await(<expr>)`
763     /// and `await { <expr> }`.
764     crate fn parse_incorrect_await_syntax(
765         &mut self,
766         lo: Span,
767         await_sp: Span,
768     ) -> PResult<'a, (Span, ExprKind)> {
769         let is_question = self.eat(&token::Question); // Handle `await? <expr>`.
770         let expr = if self.token == token::OpenDelim(token::Brace) {
771             // Handle `await { <expr> }`.
772             // This needs to be handled separatedly from the next arm to avoid
773             // interpreting `await { <expr> }?` as `<expr>?.await`.
774             self.parse_block_expr(
775                 None,
776                 self.span,
777                 BlockCheckMode::Default,
778                 ThinVec::new(),
779             )
780         } else {
781             self.parse_expr()
782         }.map_err(|mut err| {
783             err.span_label(await_sp, "while parsing this incorrect await expression");
784             err
785         })?;
786         let expr_str = self.sess.source_map().span_to_snippet(expr.span)
787             .unwrap_or_else(|_| pprust::expr_to_string(&expr));
788         let suggestion = format!("{}.await{}", expr_str, if is_question { "?" } else { "" });
789         let sp = lo.to(expr.span);
790         let app = match expr.node {
791             ExprKind::Try(_) => Applicability::MaybeIncorrect, // `await <expr>?`
792             _ => Applicability::MachineApplicable,
793         };
794         self.struct_span_err(sp, "incorrect use of `await`")
795             .span_suggestion(sp, "`await` is a postfix operation", suggestion, app)
796             .emit();
797         Ok((sp, ExprKind::Await(ast::AwaitOrigin::FieldLike, expr)))
798     }
799
800     /// If encountering `future.await()`, consume and emit error.
801     crate fn recover_from_await_method_call(&mut self) {
802         if self.token == token::OpenDelim(token::Paren) &&
803             self.look_ahead(1, |t| t == &token::CloseDelim(token::Paren))
804         {
805             // future.await()
806             let lo = self.span;
807             self.bump(); // (
808             let sp = lo.to(self.span);
809             self.bump(); // )
810             self.struct_span_err(sp, "incorrect use of `await`")
811                 .span_suggestion(
812                     sp,
813                     "`await` is not a method call, remove the parentheses",
814                     String::new(),
815                     Applicability::MachineApplicable,
816                 ).emit()
817         }
818     }
819
820     crate fn could_ascription_be_path(&self, node: &ast::ExprKind) -> bool {
821         self.token.is_ident() &&
822             if let ast::ExprKind::Path(..) = node { true } else { false } &&
823             !self.token.is_reserved_ident() &&           // v `foo:bar(baz)`
824             self.look_ahead(1, |t| t == &token::OpenDelim(token::Paren)) ||
825             self.look_ahead(1, |t| t == &token::Lt) &&     // `foo:bar<baz`
826             self.look_ahead(2, |t| t.is_ident()) ||
827             self.look_ahead(1, |t| t == &token::Colon) &&  // `foo:bar:baz`
828             self.look_ahead(2, |t| t.is_ident()) ||
829             self.look_ahead(1, |t| t == &token::ModSep) &&  // `foo:bar::baz`
830             self.look_ahead(2, |t| t.is_ident())
831     }
832
833     crate fn bad_type_ascription(
834         &self,
835         err: &mut DiagnosticBuilder<'a>,
836         lhs_span: Span,
837         cur_op_span: Span,
838         next_sp: Span,
839         maybe_path: bool,
840     ) {
841         err.span_label(self.span, "expecting a type here because of type ascription");
842         let cm = self.sess.source_map();
843         let next_pos = cm.lookup_char_pos(next_sp.lo());
844         let op_pos = cm.lookup_char_pos(cur_op_span.hi());
845         if op_pos.line != next_pos.line {
846             err.span_suggestion(
847                 cur_op_span,
848                 "try using a semicolon",
849                 ";".to_string(),
850                 Applicability::MaybeIncorrect,
851             );
852         } else {
853             if maybe_path {
854                 err.span_suggestion(
855                     cur_op_span,
856                     "maybe you meant to write a path separator here",
857                     "::".to_string(),
858                     Applicability::MaybeIncorrect,
859                 );
860             } else {
861                 err.note("type ascription is a nightly-only feature that lets \
862                           you annotate an expression with a type: `<expr>: <type>`")
863                     .span_note(
864                         lhs_span,
865                         "this expression expects an ascribed type after the colon",
866                     )
867                     .help("this might be indicative of a syntax error elsewhere");
868             }
869         }
870     }
871
872     crate fn recover_seq_parse_error(
873         &mut self,
874         delim: token::DelimToken,
875         lo: Span,
876         result: PResult<'a, P<Expr>>,
877     ) -> P<Expr> {
878         match result {
879             Ok(x) => x,
880             Err(mut err) => {
881                 err.emit();
882                 // recover from parse error
883                 self.consume_block(delim);
884                 self.mk_expr(lo.to(self.prev_span), ExprKind::Err, ThinVec::new())
885             }
886         }
887     }
888
889     crate fn recover_closing_delimiter(
890         &mut self,
891         tokens: &[token::Token],
892         mut err: DiagnosticBuilder<'a>,
893     ) -> PResult<'a, bool> {
894         let mut pos = None;
895         // we want to use the last closing delim that would apply
896         for (i, unmatched) in self.unclosed_delims.iter().enumerate().rev() {
897             if tokens.contains(&token::CloseDelim(unmatched.expected_delim))
898                 && Some(self.span) > unmatched.unclosed_span
899             {
900                 pos = Some(i);
901             }
902         }
903         match pos {
904             Some(pos) => {
905                 // Recover and assume that the detected unclosed delimiter was meant for
906                 // this location. Emit the diagnostic and act as if the delimiter was
907                 // present for the parser's sake.
908
909                  // Don't attempt to recover from this unclosed delimiter more than once.
910                 let unmatched = self.unclosed_delims.remove(pos);
911                 let delim = TokenType::Token(token::CloseDelim(unmatched.expected_delim));
912
913                  // We want to suggest the inclusion of the closing delimiter where it makes
914                 // the most sense, which is immediately after the last token:
915                 //
916                 //  {foo(bar {}}
917                 //      -      ^
918                 //      |      |
919                 //      |      help: `)` may belong here (FIXME: #58270)
920                 //      |
921                 //      unclosed delimiter
922                 if let Some(sp) = unmatched.unclosed_span {
923                     err.span_label(sp, "unclosed delimiter");
924                 }
925                 err.span_suggestion_short(
926                     self.sess.source_map().next_point(self.prev_span),
927                     &format!("{} may belong here", delim.to_string()),
928                     delim.to_string(),
929                     Applicability::MaybeIncorrect,
930                 );
931                 err.emit();
932                 self.expected_tokens.clear();  // reduce errors
933                 Ok(true)
934             }
935             _ => Err(err),
936         }
937     }
938
939     /// Recover from `pub` keyword in places where it seems _reasonable_ but isn't valid.
940     crate fn eat_bad_pub(&mut self) {
941         if self.token.is_keyword(kw::Pub) {
942             match self.parse_visibility(false) {
943                 Ok(vis) => {
944                     self.diagnostic()
945                         .struct_span_err(vis.span, "unnecessary visibility qualifier")
946                         .span_label(vis.span, "`pub` not permitted here")
947                         .emit();
948                 }
949                 Err(mut err) => err.emit(),
950             }
951         }
952     }
953
954     // Eat tokens until we can be relatively sure we reached the end of the
955     // statement. This is something of a best-effort heuristic.
956     //
957     // We terminate when we find an unmatched `}` (without consuming it).
958     crate fn recover_stmt(&mut self) {
959         self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore)
960     }
961
962     // If `break_on_semi` is `Break`, then we will stop consuming tokens after
963     // finding (and consuming) a `;` outside of `{}` or `[]` (note that this is
964     // approximate - it can mean we break too early due to macros, but that
965     // should only lead to sub-optimal recovery, not inaccurate parsing).
966     //
967     // If `break_on_block` is `Break`, then we will stop consuming tokens
968     // after finding (and consuming) a brace-delimited block.
969     crate fn recover_stmt_(&mut self, break_on_semi: SemiColonMode, break_on_block: BlockMode) {
970         let mut brace_depth = 0;
971         let mut bracket_depth = 0;
972         let mut in_block = false;
973         debug!("recover_stmt_ enter loop (semi={:?}, block={:?})",
974                break_on_semi, break_on_block);
975         loop {
976             debug!("recover_stmt_ loop {:?}", self.token);
977             match self.token {
978                 token::OpenDelim(token::DelimToken::Brace) => {
979                     brace_depth += 1;
980                     self.bump();
981                     if break_on_block == BlockMode::Break &&
982                        brace_depth == 1 &&
983                        bracket_depth == 0 {
984                         in_block = true;
985                     }
986                 }
987                 token::OpenDelim(token::DelimToken::Bracket) => {
988                     bracket_depth += 1;
989                     self.bump();
990                 }
991                 token::CloseDelim(token::DelimToken::Brace) => {
992                     if brace_depth == 0 {
993                         debug!("recover_stmt_ return - close delim {:?}", self.token);
994                         break;
995                     }
996                     brace_depth -= 1;
997                     self.bump();
998                     if in_block && bracket_depth == 0 && brace_depth == 0 {
999                         debug!("recover_stmt_ return - block end {:?}", self.token);
1000                         break;
1001                     }
1002                 }
1003                 token::CloseDelim(token::DelimToken::Bracket) => {
1004                     bracket_depth -= 1;
1005                     if bracket_depth < 0 {
1006                         bracket_depth = 0;
1007                     }
1008                     self.bump();
1009                 }
1010                 token::Eof => {
1011                     debug!("recover_stmt_ return - Eof");
1012                     break;
1013                 }
1014                 token::Semi => {
1015                     self.bump();
1016                     if break_on_semi == SemiColonMode::Break &&
1017                        brace_depth == 0 &&
1018                        bracket_depth == 0 {
1019                         debug!("recover_stmt_ return - Semi");
1020                         break;
1021                     }
1022                 }
1023                 token::Comma if break_on_semi == SemiColonMode::Comma &&
1024                        brace_depth == 0 &&
1025                        bracket_depth == 0 =>
1026                 {
1027                     debug!("recover_stmt_ return - Semi");
1028                     break;
1029                 }
1030                 _ => {
1031                     self.bump()
1032                 }
1033             }
1034         }
1035     }
1036
1037     crate fn check_for_for_in_in_typo(&mut self, in_span: Span) {
1038         if self.eat_keyword(kw::In) {
1039             // a common typo: `for _ in in bar {}`
1040             let mut err = self.sess.span_diagnostic.struct_span_err(
1041                 self.prev_span,
1042                 "expected iterable, found keyword `in`",
1043             );
1044             err.span_suggestion_short(
1045                 in_span.until(self.prev_span),
1046                 "remove the duplicated `in`",
1047                 String::new(),
1048                 Applicability::MachineApplicable,
1049             );
1050             err.emit();
1051         }
1052     }
1053
1054     crate fn expected_semi_or_open_brace(&mut self) -> PResult<'a, ast::TraitItem> {
1055         let token_str = self.this_token_descr();
1056         let mut err = self.fatal(&format!("expected `;` or `{{`, found {}", token_str));
1057         err.span_label(self.span, "expected `;` or `{`");
1058         Err(err)
1059     }
1060
1061     crate fn eat_incorrect_doc_comment(&mut self, applied_to: &str) {
1062         if let token::DocComment(_) = self.token {
1063             let mut err = self.diagnostic().struct_span_err(
1064                 self.span,
1065                 &format!("documentation comments cannot be applied to {}", applied_to),
1066             );
1067             err.span_label(self.span, "doc comments are not allowed here");
1068             err.emit();
1069             self.bump();
1070         } else if self.token == token::Pound && self.look_ahead(1, |t| {
1071             *t == token::OpenDelim(token::Bracket)
1072         }) {
1073             let lo = self.span;
1074             // Skip every token until next possible arg.
1075             while self.token != token::CloseDelim(token::Bracket) {
1076                 self.bump();
1077             }
1078             let sp = lo.to(self.span);
1079             self.bump();
1080             let mut err = self.diagnostic().struct_span_err(
1081                 sp,
1082                 &format!("attributes cannot be applied to {}", applied_to),
1083             );
1084             err.span_label(sp, "attributes are not allowed here");
1085             err.emit();
1086         }
1087     }
1088
1089     crate fn argument_without_type(
1090         &mut self,
1091         err: &mut DiagnosticBuilder<'_>,
1092         pat: P<ast::Pat>,
1093         require_name: bool,
1094         is_trait_item: bool,
1095     ) {
1096         // If we find a pattern followed by an identifier, it could be an (incorrect)
1097         // C-style parameter declaration.
1098         if self.check_ident() && self.look_ahead(1, |t| {
1099             *t == token::Comma || *t == token::CloseDelim(token::Paren)
1100         }) {
1101             let ident = self.parse_ident().unwrap();
1102             let span = pat.span.with_hi(ident.span.hi());
1103
1104             err.span_suggestion(
1105                 span,
1106                 "declare the type after the parameter binding",
1107                 String::from("<identifier>: <type>"),
1108                 Applicability::HasPlaceholders,
1109             );
1110         } else if require_name && is_trait_item {
1111             if let PatKind::Ident(_, ident, _) = pat.node {
1112                 err.span_suggestion(
1113                     pat.span,
1114                     "explicitly ignore parameter",
1115                     format!("_: {}", ident),
1116                     Applicability::MachineApplicable,
1117                 );
1118             }
1119
1120             err.note("anonymous parameters are removed in the 2018 edition (see RFC 1685)");
1121         }
1122     }
1123
1124     crate fn recover_arg_parse(&mut self) -> PResult<'a, (P<ast::Pat>, P<ast::Ty>)> {
1125         let pat = self.parse_pat(Some("argument name"))?;
1126         self.expect(&token::Colon)?;
1127         let ty = self.parse_ty()?;
1128
1129         let mut err = self.diagnostic().struct_span_err_with_code(
1130             pat.span,
1131             "patterns aren't allowed in methods without bodies",
1132             DiagnosticId::Error("E0642".into()),
1133         );
1134         err.span_suggestion_short(
1135             pat.span,
1136             "give this argument a name or use an underscore to ignore it",
1137             "_".to_owned(),
1138             Applicability::MachineApplicable,
1139         );
1140         err.emit();
1141
1142         // Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
1143         let pat = P(Pat {
1144             node: PatKind::Wild,
1145             span: pat.span,
1146             id: ast::DUMMY_NODE_ID
1147         });
1148         Ok((pat, ty))
1149     }
1150
1151     crate fn recover_bad_self_arg(
1152         &mut self,
1153         mut arg: ast::Arg,
1154         is_trait_item: bool,
1155     ) -> PResult<'a, ast::Arg> {
1156         let sp = arg.pat.span;
1157         arg.ty.node = TyKind::Err;
1158         let mut err = self.struct_span_err(sp, "unexpected `self` parameter in function");
1159         if is_trait_item {
1160             err.span_label(sp, "must be the first associated function parameter");
1161         } else {
1162             err.span_label(sp, "not valid as function parameter");
1163             err.note("`self` is only valid as the first parameter of an associated function");
1164         }
1165         err.emit();
1166         Ok(arg)
1167     }
1168
1169     crate fn consume_block(&mut self, delim: token::DelimToken) {
1170         let mut brace_depth = 0;
1171         loop {
1172             if self.eat(&token::OpenDelim(delim)) {
1173                 brace_depth += 1;
1174             } else if self.eat(&token::CloseDelim(delim)) {
1175                 if brace_depth == 0 {
1176                     return;
1177                 } else {
1178                     brace_depth -= 1;
1179                     continue;
1180                 }
1181             } else if self.token == token::Eof || self.eat(&token::CloseDelim(token::NoDelim)) {
1182                 return;
1183             } else {
1184                 self.bump();
1185             }
1186         }
1187     }
1188
1189     crate fn expected_expression_found(&self) -> DiagnosticBuilder<'a> {
1190         let (span, msg) = match (&self.token, self.subparser_name) {
1191             (&token::Token::Eof, Some(origin)) => {
1192                 let sp = self.sess.source_map().next_point(self.span);
1193                 (sp, format!("expected expression, found end of {}", origin))
1194             }
1195             _ => (self.span, format!(
1196                 "expected expression, found {}",
1197                 self.this_token_descr(),
1198             )),
1199         };
1200         let mut err = self.struct_span_err(span, &msg);
1201         let sp = self.sess.source_map().start_point(self.span);
1202         if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) {
1203             self.sess.expr_parentheses_needed(&mut err, *sp, None);
1204         }
1205         err.span_label(span, "expected expression");
1206         err
1207     }
1208 }