]> git.lizzy.rs Git - rust.git/blob - src/librustc_ast_passes/ast_validation.rs
Rollup merge of #70367 - nikomatsakis:issue-69307, r=Aaron1011
[rust.git] / src / librustc_ast_passes / ast_validation.rs
1 // Validate AST before lowering it to HIR.
2 //
3 // This pass is supposed to catch things that fit into AST data structures,
4 // but not permitted by the language. It runs after expansion when AST is frozen,
5 // so it can check for erroneous constructions produced by syntax extensions.
6 // This pass is supposed to perform only simple checks not requiring name resolution
7 // or type checking or some other kind of complex analysis.
8
9 use itertools::{Either, Itertools};
10 use rustc_ast::ast::*;
11 use rustc_ast::attr;
12 use rustc_ast::expand::is_proc_macro_attr;
13 use rustc_ast::ptr::P;
14 use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
15 use rustc_ast::walk_list;
16 use rustc_ast_pretty::pprust;
17 use rustc_data_structures::fx::FxHashMap;
18 use rustc_errors::{error_code, pluralize, struct_span_err, Applicability};
19 use rustc_parse::validate_attr;
20 use rustc_session::lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY;
21 use rustc_session::lint::LintBuffer;
22 use rustc_session::Session;
23 use rustc_span::symbol::{kw, sym};
24 use rustc_span::Span;
25 use std::mem;
26
27 const MORE_EXTERN: &str =
28     "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html";
29
30 /// Is `self` allowed semantically as the first parameter in an `FnDecl`?
31 enum SelfSemantic {
32     Yes,
33     No,
34 }
35
36 /// A syntactic context that disallows certain kinds of bounds (e.g., `?Trait` or `?const Trait`).
37 #[derive(Clone, Copy)]
38 enum BoundContext {
39     ImplTrait,
40     TraitBounds,
41     TraitObject,
42 }
43
44 impl BoundContext {
45     fn description(&self) -> &'static str {
46         match self {
47             Self::ImplTrait => "`impl Trait`",
48             Self::TraitBounds => "supertraits",
49             Self::TraitObject => "trait objects",
50         }
51     }
52 }
53
54 struct AstValidator<'a> {
55     session: &'a Session,
56
57     /// The span of the `extern` in an `extern { ... }` block, if any.
58     extern_mod: Option<&'a Item>,
59
60     /// Are we inside a trait impl?
61     in_trait_impl: bool,
62
63     has_proc_macro_decls: bool,
64
65     /// Used to ban nested `impl Trait`, e.g., `impl Into<impl Debug>`.
66     /// Nested `impl Trait` _is_ allowed in associated type position,
67     /// e.g., `impl Iterator<Item = impl Debug>`.
68     outer_impl_trait: Option<Span>,
69
70     /// Keeps track of the `BoundContext` as we recurse.
71     ///
72     /// This is used to forbid `?const Trait` bounds in, e.g.,
73     /// `impl Iterator<Item = Box<dyn ?const Trait>`.
74     bound_context: Option<BoundContext>,
75
76     /// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
77     /// or `Foo::Bar<impl Trait>`
78     is_impl_trait_banned: bool,
79
80     /// Used to ban associated type bounds (i.e., `Type<AssocType: Bounds>`) in
81     /// certain positions.
82     is_assoc_ty_bound_banned: bool,
83
84     lint_buffer: &'a mut LintBuffer,
85 }
86
87 impl<'a> AstValidator<'a> {
88     fn with_in_trait_impl(&mut self, is_in: bool, f: impl FnOnce(&mut Self)) {
89         let old = mem::replace(&mut self.in_trait_impl, is_in);
90         f(self);
91         self.in_trait_impl = old;
92     }
93
94     fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
95         let old = mem::replace(&mut self.is_impl_trait_banned, true);
96         f(self);
97         self.is_impl_trait_banned = old;
98     }
99
100     fn with_banned_assoc_ty_bound(&mut self, f: impl FnOnce(&mut Self)) {
101         let old = mem::replace(&mut self.is_assoc_ty_bound_banned, true);
102         f(self);
103         self.is_assoc_ty_bound_banned = old;
104     }
105
106     fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
107         let old = mem::replace(&mut self.outer_impl_trait, outer);
108         if outer.is_some() {
109             self.with_bound_context(BoundContext::ImplTrait, |this| f(this));
110         } else {
111             f(self)
112         }
113         self.outer_impl_trait = old;
114     }
115
116     fn with_bound_context(&mut self, ctx: BoundContext, f: impl FnOnce(&mut Self)) {
117         let old = self.bound_context.replace(ctx);
118         f(self);
119         self.bound_context = old;
120     }
121
122     fn visit_assoc_ty_constraint_from_generic_args(&mut self, constraint: &'a AssocTyConstraint) {
123         match constraint.kind {
124             AssocTyConstraintKind::Equality { .. } => {}
125             AssocTyConstraintKind::Bound { .. } => {
126                 if self.is_assoc_ty_bound_banned {
127                     self.err_handler().span_err(
128                         constraint.span,
129                         "associated type bounds are not allowed within structs, enums, or unions",
130                     );
131                 }
132             }
133         }
134         self.visit_assoc_ty_constraint(constraint);
135     }
136
137     // Mirrors `visit::walk_ty`, but tracks relevant state.
138     fn walk_ty(&mut self, t: &'a Ty) {
139         match t.kind {
140             TyKind::ImplTrait(..) => {
141                 self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t))
142             }
143             TyKind::TraitObject(..) => {
144                 self.with_bound_context(BoundContext::TraitObject, |this| visit::walk_ty(this, t));
145             }
146             TyKind::Path(ref qself, ref path) => {
147                 // We allow these:
148                 //  - `Option<impl Trait>`
149                 //  - `option::Option<impl Trait>`
150                 //  - `option::Option<T>::Foo<impl Trait>
151                 //
152                 // But not these:
153                 //  - `<impl Trait>::Foo`
154                 //  - `option::Option<impl Trait>::Foo`.
155                 //
156                 // To implement this, we disallow `impl Trait` from `qself`
157                 // (for cases like `<impl Trait>::Foo>`)
158                 // but we allow `impl Trait` in `GenericArgs`
159                 // iff there are no more PathSegments.
160                 if let Some(ref qself) = *qself {
161                     // `impl Trait` in `qself` is always illegal
162                     self.with_banned_impl_trait(|this| this.visit_ty(&qself.ty));
163                 }
164
165                 // Note that there should be a call to visit_path here,
166                 // so if any logic is added to process `Path`s a call to it should be
167                 // added both in visit_path and here. This code mirrors visit::walk_path.
168                 for (i, segment) in path.segments.iter().enumerate() {
169                     // Allow `impl Trait` iff we're on the final path segment
170                     if i == path.segments.len() - 1 {
171                         self.visit_path_segment(path.span, segment);
172                     } else {
173                         self.with_banned_impl_trait(|this| {
174                             this.visit_path_segment(path.span, segment)
175                         });
176                     }
177                 }
178             }
179             _ => visit::walk_ty(self, t),
180         }
181     }
182
183     fn err_handler(&self) -> &rustc_errors::Handler {
184         &self.session.diagnostic()
185     }
186
187     fn check_lifetime(&self, ident: Ident) {
188         let valid_names = [kw::UnderscoreLifetime, kw::StaticLifetime, kw::Invalid];
189         if !valid_names.contains(&ident.name) && ident.without_first_quote().is_reserved() {
190             self.err_handler().span_err(ident.span, "lifetimes cannot use keyword names");
191         }
192     }
193
194     fn check_label(&self, ident: Ident) {
195         if ident.without_first_quote().is_reserved() {
196             self.err_handler()
197                 .span_err(ident.span, &format!("invalid label name `{}`", ident.name));
198         }
199     }
200
201     fn invalid_visibility(&self, vis: &Visibility, note: Option<&str>) {
202         if let VisibilityKind::Inherited = vis.node {
203             return;
204         }
205
206         let mut err =
207             struct_span_err!(self.session, vis.span, E0449, "unnecessary visibility qualifier");
208         if vis.node.is_pub() {
209             err.span_label(vis.span, "`pub` not permitted here because it's implied");
210         }
211         if let Some(note) = note {
212             err.note(note);
213         }
214         err.emit();
215     }
216
217     fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, bool)) {
218         for Param { pat, .. } in &decl.inputs {
219             match pat.kind {
220                 PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, None) | PatKind::Wild => {}
221                 PatKind::Ident(BindingMode::ByValue(Mutability::Mut), _, None) => {
222                     report_err(pat.span, true)
223                 }
224                 _ => report_err(pat.span, false),
225             }
226         }
227     }
228
229     fn check_trait_fn_not_async(&self, fn_span: Span, asyncness: Async) {
230         if let Async::Yes { span, .. } = asyncness {
231             struct_span_err!(
232                 self.session,
233                 fn_span,
234                 E0706,
235                 "functions in traits cannot be declared `async`"
236             )
237             .span_label(span, "`async` because of this")
238             .note("`async` trait functions are not currently supported")
239             .note("consider using the `async-trait` crate: https://crates.io/crates/async-trait")
240             .emit();
241         }
242     }
243
244     fn check_trait_fn_not_const(&self, constness: Const) {
245         if let Const::Yes(span) = constness {
246             struct_span_err!(
247                 self.session,
248                 span,
249                 E0379,
250                 "functions in traits cannot be declared const"
251             )
252             .span_label(span, "functions in traits cannot be const")
253             .emit();
254         }
255     }
256
257     // FIXME(ecstaticmorse): Instead, use `bound_context` to check this in `visit_param_bound`.
258     fn no_questions_in_bounds(&self, bounds: &GenericBounds, where_: &str, is_trait: bool) {
259         for bound in bounds {
260             if let GenericBound::Trait(ref poly, TraitBoundModifier::Maybe) = *bound {
261                 let mut err = self.err_handler().struct_span_err(
262                     poly.span,
263                     &format!("`?Trait` is not permitted in {}", where_),
264                 );
265                 if is_trait {
266                     let path_str = pprust::path_to_string(&poly.trait_ref.path);
267                     err.note(&format!("traits are `?{}` by default", path_str));
268                 }
269                 err.emit();
270             }
271         }
272     }
273
274     /// Matches `'-' lit | lit (cf. parser::Parser::parse_literal_maybe_minus)`,
275     /// or paths for ranges.
276     //
277     // FIXME: do we want to allow `expr -> pattern` conversion to create path expressions?
278     // That means making this work:
279     //
280     // ```rust,ignore (FIXME)
281     // struct S;
282     // macro_rules! m {
283     //     ($a:expr) => {
284     //         let $a = S;
285     //     }
286     // }
287     // m!(S);
288     // ```
289     fn check_expr_within_pat(&self, expr: &Expr, allow_paths: bool) {
290         match expr.kind {
291             ExprKind::Lit(..) | ExprKind::Err => {}
292             ExprKind::Path(..) if allow_paths => {}
293             ExprKind::Unary(UnOp::Neg, ref inner) if matches!(inner.kind, ExprKind::Lit(_)) => {}
294             _ => self.err_handler().span_err(
295                 expr.span,
296                 "arbitrary expressions aren't allowed \
297                                                          in patterns",
298             ),
299         }
300     }
301
302     fn check_late_bound_lifetime_defs(&self, params: &[GenericParam]) {
303         // Check only lifetime parameters are present and that the lifetime
304         // parameters that are present have no bounds.
305         let non_lt_param_spans: Vec<_> = params
306             .iter()
307             .filter_map(|param| match param.kind {
308                 GenericParamKind::Lifetime { .. } => {
309                     if !param.bounds.is_empty() {
310                         let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
311                         self.err_handler()
312                             .span_err(spans, "lifetime bounds cannot be used in this context");
313                     }
314                     None
315                 }
316                 _ => Some(param.ident.span),
317             })
318             .collect();
319         if !non_lt_param_spans.is_empty() {
320             self.err_handler().span_err(
321                 non_lt_param_spans,
322                 "only lifetime parameters can be used in this context",
323             );
324         }
325     }
326
327     fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
328         self.check_decl_cvaradic_pos(fn_decl);
329         self.check_decl_attrs(fn_decl);
330         self.check_decl_self_param(fn_decl, self_semantic);
331     }
332
333     fn check_decl_cvaradic_pos(&self, fn_decl: &FnDecl) {
334         match &*fn_decl.inputs {
335             [Param { ty, span, .. }] => {
336                 if let TyKind::CVarArgs = ty.kind {
337                     self.err_handler().span_err(
338                         *span,
339                         "C-variadic function must be declared with at least one named argument",
340                     );
341                 }
342             }
343             [ps @ .., _] => {
344                 for Param { ty, span, .. } in ps {
345                     if let TyKind::CVarArgs = ty.kind {
346                         self.err_handler().span_err(
347                             *span,
348                             "`...` must be the last argument of a C-variadic function",
349                         );
350                     }
351                 }
352             }
353             _ => {}
354         }
355     }
356
357     fn check_decl_attrs(&self, fn_decl: &FnDecl) {
358         fn_decl
359             .inputs
360             .iter()
361             .flat_map(|i| i.attrs.as_ref())
362             .filter(|attr| {
363                 let arr = [sym::allow, sym::cfg, sym::cfg_attr, sym::deny, sym::forbid, sym::warn];
364                 !arr.contains(&attr.name_or_empty()) && rustc_attr::is_builtin_attr(attr)
365             })
366             .for_each(|attr| {
367                 if attr.is_doc_comment() {
368                     self.err_handler()
369                         .struct_span_err(
370                             attr.span,
371                             "documentation comments cannot be applied to function parameters",
372                         )
373                         .span_label(attr.span, "doc comments are not allowed here")
374                         .emit();
375                 } else {
376                     self.err_handler().span_err(
377                         attr.span,
378                         "allow, cfg, cfg_attr, deny, \
379                 forbid, and warn are the only allowed built-in attributes in function parameters",
380                     )
381                 }
382             });
383     }
384
385     fn check_decl_self_param(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
386         if let (SelfSemantic::No, [param, ..]) = (self_semantic, &*fn_decl.inputs) {
387             if param.is_self() {
388                 self.err_handler()
389                     .struct_span_err(
390                         param.span,
391                         "`self` parameter is only allowed in associated functions",
392                     )
393                     .span_label(param.span, "not semantically valid as function parameter")
394                     .note("associated functions are those in `impl` or `trait` definitions")
395                     .emit();
396             }
397         }
398     }
399
400     fn check_defaultness(&self, span: Span, defaultness: Defaultness) {
401         if let Defaultness::Default(def_span) = defaultness {
402             let span = self.session.source_map().guess_head_span(span);
403             self.err_handler()
404                 .struct_span_err(span, "`default` is only allowed on items in `impl` definitions")
405                 .span_label(def_span, "`default` because of this")
406                 .emit();
407         }
408     }
409
410     fn error_item_without_body(&self, sp: Span, ctx: &str, msg: &str, sugg: &str) {
411         self.err_handler()
412             .struct_span_err(sp, msg)
413             .span_suggestion(
414                 self.session.source_map().end_point(sp),
415                 &format!("provide a definition for the {}", ctx),
416                 sugg.to_string(),
417                 Applicability::HasPlaceholders,
418             )
419             .emit();
420     }
421
422     fn check_impl_item_provided<T>(&self, sp: Span, body: &Option<T>, ctx: &str, sugg: &str) {
423         if body.is_none() {
424             let msg = format!("associated {} in `impl` without body", ctx);
425             self.error_item_without_body(sp, ctx, &msg, sugg);
426         }
427     }
428
429     fn check_type_no_bounds(&self, bounds: &[GenericBound], ctx: &str) {
430         let span = match bounds {
431             [] => return,
432             [b0] => b0.span(),
433             [b0, .., bl] => b0.span().to(bl.span()),
434         };
435         self.err_handler()
436             .struct_span_err(span, &format!("bounds on `type`s in {} have no effect", ctx))
437             .emit();
438     }
439
440     fn check_foreign_ty_genericless(&self, generics: &Generics) {
441         let cannot_have = |span, descr, remove_descr| {
442             self.err_handler()
443                 .struct_span_err(
444                     span,
445                     &format!("`type`s inside `extern` blocks cannot have {}", descr),
446                 )
447                 .span_suggestion(
448                     span,
449                     &format!("remove the {}", remove_descr),
450                     String::new(),
451                     Applicability::MaybeIncorrect,
452                 )
453                 .span_label(self.current_extern_span(), "`extern` block begins here")
454                 .note(MORE_EXTERN)
455                 .emit();
456         };
457
458         if !generics.params.is_empty() {
459             cannot_have(generics.span, "generic parameters", "generic parameters");
460         }
461
462         if !generics.where_clause.predicates.is_empty() {
463             cannot_have(generics.where_clause.span, "`where` clauses", "`where` clause");
464         }
465     }
466
467     fn check_foreign_kind_bodyless(&self, ident: Ident, kind: &str, body: Option<Span>) {
468         let body = match body {
469             None => return,
470             Some(body) => body,
471         };
472         self.err_handler()
473             .struct_span_err(ident.span, &format!("incorrect `{}` inside `extern` block", kind))
474             .span_label(ident.span, "cannot have a body")
475             .span_label(body, "the invalid body")
476             .span_label(
477                 self.current_extern_span(),
478                 format!(
479                     "`extern` blocks define existing foreign {0}s and {0}s \
480                     inside of them cannot have a body",
481                     kind
482                 ),
483             )
484             .note(MORE_EXTERN)
485             .emit();
486     }
487
488     /// An `fn` in `extern { ... }` cannot have a body `{ ... }`.
489     fn check_foreign_fn_bodyless(&self, ident: Ident, body: Option<&Block>) {
490         let body = match body {
491             None => return,
492             Some(body) => body,
493         };
494         self.err_handler()
495             .struct_span_err(ident.span, "incorrect function inside `extern` block")
496             .span_label(ident.span, "cannot have a body")
497             .span_suggestion(
498                 body.span,
499                 "remove the invalid body",
500                 ";".to_string(),
501                 Applicability::MaybeIncorrect,
502             )
503             .help(
504                 "you might have meant to write a function accessible through FFI, \
505                 which can be done by writing `extern fn` outside of the `extern` block",
506             )
507             .span_label(
508                 self.current_extern_span(),
509                 "`extern` blocks define existing foreign functions and functions \
510                 inside of them cannot have a body",
511             )
512             .note(MORE_EXTERN)
513             .emit();
514     }
515
516     fn current_extern_span(&self) -> Span {
517         self.session.source_map().guess_head_span(self.extern_mod.unwrap().span)
518     }
519
520     /// An `fn` in `extern { ... }` cannot have qualfiers, e.g. `async fn`.
521     fn check_foreign_fn_headerless(&self, ident: Ident, span: Span, header: FnHeader) {
522         if header.has_qualifiers() {
523             self.err_handler()
524                 .struct_span_err(ident.span, "functions in `extern` blocks cannot have qualifiers")
525                 .span_label(self.current_extern_span(), "in this `extern` block")
526                 .span_suggestion(
527                     span.until(ident.span.shrink_to_lo()),
528                     "remove the qualifiers",
529                     "fn ".to_string(),
530                     Applicability::MaybeIncorrect,
531                 )
532                 .emit();
533         }
534     }
535
536     /// Reject C-varadic type unless the function is foreign,
537     /// or free and `unsafe extern "C"` semantically.
538     fn check_c_varadic_type(&self, fk: FnKind<'a>) {
539         match (fk.ctxt(), fk.header()) {
540             (Some(FnCtxt::Foreign), _) => return,
541             (Some(FnCtxt::Free), Some(header)) => match header.ext {
542                 Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }) | Extern::Implicit
543                     if matches!(header.unsafety, Unsafe::Yes(_)) =>
544                 {
545                     return;
546                 }
547                 _ => {}
548             },
549             _ => {}
550         };
551
552         for Param { ty, span, .. } in &fk.decl().inputs {
553             if let TyKind::CVarArgs = ty.kind {
554                 self.err_handler()
555                     .struct_span_err(
556                         *span,
557                         "only foreign or `unsafe extern \"C\" functions may be C-variadic",
558                     )
559                     .emit();
560             }
561         }
562     }
563
564     /// We currently do not permit const generics in `const fn`,
565     /// as this is tantamount to allowing compile-time dependent typing.
566     ///
567     /// FIXME(const_generics): Is this really true / necessary? Discuss with @varkor.
568     /// At any rate, the restriction feels too syntactic. Consider moving it to e.g. typeck.
569     fn check_const_fn_const_generic(&self, span: Span, sig: &FnSig, generics: &Generics) {
570         if let Const::Yes(const_span) = sig.header.constness {
571             // Look for const generics and error if we find any.
572             for param in &generics.params {
573                 if let GenericParamKind::Const { .. } = param.kind {
574                     self.err_handler()
575                         .struct_span_err(
576                             span,
577                             "const parameters are not permitted in const functions",
578                         )
579                         .span_label(const_span, "`const` because of this")
580                         .emit();
581                 }
582             }
583         }
584     }
585
586     fn check_item_named(&self, ident: Ident, kind: &str) {
587         if ident.name != kw::Underscore {
588             return;
589         }
590         self.err_handler()
591             .struct_span_err(ident.span, &format!("`{}` items in this context need a name", kind))
592             .span_label(ident.span, format!("`_` is not a valid name for this `{}` item", kind))
593             .emit();
594     }
595
596     fn deny_generic_params(&self, generics: &Generics, ident_span: Span) {
597         if !generics.params.is_empty() {
598             struct_span_err!(
599                 self.session,
600                 generics.span,
601                 E0567,
602                 "auto traits cannot have generic parameters"
603             )
604             .span_label(ident_span, "auto trait cannot have generic parameters")
605             .span_suggestion(
606                 generics.span,
607                 "remove the parameters",
608                 String::new(),
609                 Applicability::MachineApplicable,
610             )
611             .emit();
612         }
613     }
614
615     fn deny_super_traits(&self, bounds: &GenericBounds, ident_span: Span) {
616         if let [first @ last] | [first, .., last] = &bounds[..] {
617             let span = first.span().to(last.span());
618             struct_span_err!(self.session, span, E0568, "auto traits cannot have super traits")
619                 .span_label(ident_span, "auto trait cannot have super traits")
620                 .span_suggestion(
621                     span,
622                     "remove the super traits",
623                     String::new(),
624                     Applicability::MachineApplicable,
625                 )
626                 .emit();
627         }
628     }
629
630     fn deny_items(&self, trait_items: &[P<AssocItem>], ident_span: Span) {
631         if !trait_items.is_empty() {
632             let spans: Vec<_> = trait_items.iter().map(|i| i.ident.span).collect();
633             struct_span_err!(
634                 self.session,
635                 spans,
636                 E0380,
637                 "auto traits cannot have methods or associated items"
638             )
639             .span_label(ident_span, "auto trait cannot have items")
640             .emit();
641         }
642     }
643
644     fn correct_generic_order_suggestion(&self, data: &AngleBracketedArgs) -> String {
645         // Lifetimes always come first.
646         let lt_sugg = data.args.iter().filter_map(|arg| match arg {
647             AngleBracketedArg::Arg(lt @ GenericArg::Lifetime(_)) => {
648                 Some(pprust::to_string(|s| s.print_generic_arg(lt)))
649             }
650             _ => None,
651         });
652         let args_sugg = data.args.iter().filter_map(|a| match a {
653             AngleBracketedArg::Arg(GenericArg::Lifetime(_)) | AngleBracketedArg::Constraint(_) => {
654                 None
655             }
656             AngleBracketedArg::Arg(arg) => Some(pprust::to_string(|s| s.print_generic_arg(arg))),
657         });
658         // Constraints always come last.
659         let constraint_sugg = data.args.iter().filter_map(|a| match a {
660             AngleBracketedArg::Arg(_) => None,
661             AngleBracketedArg::Constraint(c) => {
662                 Some(pprust::to_string(|s| s.print_assoc_constraint(c)))
663             }
664         });
665         format!(
666             "<{}>",
667             lt_sugg.chain(args_sugg).chain(constraint_sugg).collect::<Vec<String>>().join(", ")
668         )
669     }
670
671     /// Enforce generic args coming before constraints in `<...>` of a path segment.
672     fn check_generic_args_before_constraints(&self, data: &AngleBracketedArgs) {
673         // Early exit in case it's partitioned as it should be.
674         if data.args.iter().is_partitioned(|arg| matches!(arg, AngleBracketedArg::Arg(_))) {
675             return;
676         }
677         // Find all generic argument coming after the first constraint...
678         let (constraint_spans, arg_spans): (Vec<Span>, Vec<Span>) =
679             data.args.iter().partition_map(|arg| match arg {
680                 AngleBracketedArg::Constraint(c) => Either::Left(c.span),
681                 AngleBracketedArg::Arg(a) => Either::Right(a.span()),
682             });
683         let args_len = arg_spans.len();
684         let constraint_len = constraint_spans.len();
685         // ...and then error:
686         self.err_handler()
687             .struct_span_err(
688                 arg_spans.clone(),
689                 "generic arguments must come before the first constraint",
690             )
691             .span_label(constraint_spans[0], &format!("constraint{}", pluralize!(constraint_len)))
692             .span_label(
693                 *arg_spans.iter().last().unwrap(),
694                 &format!("generic argument{}", pluralize!(args_len)),
695             )
696             .span_labels(constraint_spans, "")
697             .span_labels(arg_spans, "")
698             .span_suggestion_verbose(
699                 data.span,
700                 &format!(
701                     "move the constraint{} after the generic argument{}",
702                     pluralize!(constraint_len),
703                     pluralize!(args_len)
704                 ),
705                 self.correct_generic_order_suggestion(&data),
706                 Applicability::MachineApplicable,
707             )
708             .emit();
709     }
710 }
711
712 /// Checks that generic parameters are in the correct order,
713 /// which is lifetimes, then types and then consts. (`<'a, T, const N: usize>`)
714 fn validate_generic_param_order<'a>(
715     sess: &Session,
716     handler: &rustc_errors::Handler,
717     generics: impl Iterator<Item = (ParamKindOrd, Option<&'a [GenericBound]>, Span, Option<String>)>,
718     span: Span,
719 ) {
720     let mut max_param: Option<ParamKindOrd> = None;
721     let mut out_of_order = FxHashMap::default();
722     let mut param_idents = vec![];
723
724     for (kind, bounds, span, ident) in generics {
725         if let Some(ident) = ident {
726             param_idents.push((kind, bounds, param_idents.len(), ident));
727         }
728         let max_param = &mut max_param;
729         match max_param {
730             Some(max_param) if *max_param > kind => {
731                 let entry = out_of_order.entry(kind).or_insert((*max_param, vec![]));
732                 entry.1.push(span);
733             }
734             Some(_) | None => *max_param = Some(kind),
735         };
736     }
737
738     let mut ordered_params = "<".to_string();
739     if !out_of_order.is_empty() {
740         param_idents.sort_by_key(|&(po, _, i, _)| (po, i));
741         let mut first = true;
742         for (_, bounds, _, ident) in param_idents {
743             if !first {
744                 ordered_params += ", ";
745             }
746             ordered_params += &ident;
747             if let Some(bounds) = bounds {
748                 if !bounds.is_empty() {
749                     ordered_params += ": ";
750                     ordered_params += &pprust::bounds_to_string(&bounds);
751                 }
752             }
753             first = false;
754         }
755     }
756     ordered_params += ">";
757
758     for (param_ord, (max_param, spans)) in &out_of_order {
759         let mut err =
760             handler.struct_span_err(
761                 spans.clone(),
762                 &format!(
763                     "{} parameters must be declared prior to {} parameters",
764                     param_ord, max_param,
765                 ),
766             );
767         err.span_suggestion(
768             span,
769             &format!(
770                 "reorder the parameters: lifetimes, then types{}",
771                 if sess.features_untracked().const_generics { ", then consts" } else { "" },
772             ),
773             ordered_params.clone(),
774             Applicability::MachineApplicable,
775         );
776         err.emit();
777     }
778 }
779
780 impl<'a> Visitor<'a> for AstValidator<'a> {
781     fn visit_attribute(&mut self, attr: &Attribute) {
782         validate_attr::check_meta(&self.session.parse_sess, attr);
783     }
784
785     fn visit_expr(&mut self, expr: &'a Expr) {
786         match &expr.kind {
787             ExprKind::LlvmInlineAsm(..) if !self.session.target.target.options.allow_asm => {
788                 struct_span_err!(
789                     self.session,
790                     expr.span,
791                     E0472,
792                     "llvm_asm! is unsupported on this target"
793                 )
794                 .emit();
795             }
796             _ => {}
797         }
798
799         visit::walk_expr(self, expr);
800     }
801
802     fn visit_ty(&mut self, ty: &'a Ty) {
803         match ty.kind {
804             TyKind::BareFn(ref bfty) => {
805                 self.check_fn_decl(&bfty.decl, SelfSemantic::No);
806                 Self::check_decl_no_pat(&bfty.decl, |span, _| {
807                     struct_span_err!(
808                         self.session,
809                         span,
810                         E0561,
811                         "patterns aren't allowed in function pointer types"
812                     )
813                     .emit();
814                 });
815                 self.check_late_bound_lifetime_defs(&bfty.generic_params);
816             }
817             TyKind::TraitObject(ref bounds, ..) => {
818                 let mut any_lifetime_bounds = false;
819                 for bound in bounds {
820                     if let GenericBound::Outlives(ref lifetime) = *bound {
821                         if any_lifetime_bounds {
822                             struct_span_err!(
823                                 self.session,
824                                 lifetime.ident.span,
825                                 E0226,
826                                 "only a single explicit lifetime bound is permitted"
827                             )
828                             .emit();
829                             break;
830                         }
831                         any_lifetime_bounds = true;
832                     }
833                 }
834                 self.no_questions_in_bounds(bounds, "trait object types", false);
835             }
836             TyKind::ImplTrait(_, ref bounds) => {
837                 if self.is_impl_trait_banned {
838                     struct_span_err!(
839                         self.session,
840                         ty.span,
841                         E0667,
842                         "`impl Trait` is not allowed in path parameters"
843                     )
844                     .emit();
845                 }
846
847                 if let Some(outer_impl_trait_sp) = self.outer_impl_trait {
848                     struct_span_err!(
849                         self.session,
850                         ty.span,
851                         E0666,
852                         "nested `impl Trait` is not allowed"
853                     )
854                     .span_label(outer_impl_trait_sp, "outer `impl Trait`")
855                     .span_label(ty.span, "nested `impl Trait` here")
856                     .emit();
857                 }
858
859                 if !bounds
860                     .iter()
861                     .any(|b| if let GenericBound::Trait(..) = *b { true } else { false })
862                 {
863                     self.err_handler().span_err(ty.span, "at least one trait must be specified");
864                 }
865
866                 self.walk_ty(ty);
867                 return;
868             }
869             _ => {}
870         }
871
872         self.walk_ty(ty)
873     }
874
875     fn visit_label(&mut self, label: &'a Label) {
876         self.check_label(label.ident);
877         visit::walk_label(self, label);
878     }
879
880     fn visit_lifetime(&mut self, lifetime: &'a Lifetime) {
881         self.check_lifetime(lifetime.ident);
882         visit::walk_lifetime(self, lifetime);
883     }
884
885     fn visit_item(&mut self, item: &'a Item) {
886         if item.attrs.iter().any(|attr| is_proc_macro_attr(attr)) {
887             self.has_proc_macro_decls = true;
888         }
889
890         match item.kind {
891             ItemKind::Impl {
892                 unsafety,
893                 polarity,
894                 defaultness: _,
895                 constness: _,
896                 generics: _,
897                 of_trait: Some(ref t),
898                 ref self_ty,
899                 items: _,
900             } => {
901                 self.with_in_trait_impl(true, |this| {
902                     this.invalid_visibility(&item.vis, None);
903                     if let TyKind::Err = self_ty.kind {
904                         this.err_handler()
905                             .struct_span_err(
906                                 item.span,
907                                 "`impl Trait for .. {}` is an obsolete syntax",
908                             )
909                             .help("use `auto trait Trait {}` instead")
910                             .emit();
911                     }
912                     if let (Unsafe::Yes(span), ImplPolarity::Negative(sp)) = (unsafety, polarity) {
913                         struct_span_err!(
914                             this.session,
915                             sp.to(t.path.span),
916                             E0198,
917                             "negative impls cannot be unsafe"
918                         )
919                         .span_label(sp, "negative because of this")
920                         .span_label(span, "unsafe because of this")
921                         .emit();
922                     }
923
924                     visit::walk_item(this, item);
925                 });
926                 return; // Avoid visiting again.
927             }
928             ItemKind::Impl {
929                 unsafety,
930                 polarity,
931                 defaultness,
932                 constness,
933                 generics: _,
934                 of_trait: None,
935                 ref self_ty,
936                 items: _,
937             } => {
938                 let error = |annotation_span, annotation| {
939                     let mut err = self.err_handler().struct_span_err(
940                         self_ty.span,
941                         &format!("inherent impls cannot be {}", annotation),
942                     );
943                     err.span_label(annotation_span, &format!("{} because of this", annotation));
944                     err.span_label(self_ty.span, "inherent impl for this type");
945                     err
946                 };
947
948                 self.invalid_visibility(
949                     &item.vis,
950                     Some("place qualifiers on individual impl items instead"),
951                 );
952                 if let Unsafe::Yes(span) = unsafety {
953                     error(span, "unsafe").code(error_code!(E0197)).emit();
954                 }
955                 if let ImplPolarity::Negative(span) = polarity {
956                     error(span, "negative").emit();
957                 }
958                 if let Defaultness::Default(def_span) = defaultness {
959                     error(def_span, "`default`")
960                         .note("only trait implementations may be annotated with `default`")
961                         .emit();
962                 }
963                 if let Const::Yes(span) = constness {
964                     error(span, "`const`")
965                         .note("only trait implementations may be annotated with `const`")
966                         .emit();
967                 }
968             }
969             ItemKind::Fn(def, ref sig, ref generics, ref body) => {
970                 self.check_defaultness(item.span, def);
971                 self.check_const_fn_const_generic(item.span, sig, generics);
972
973                 if body.is_none() {
974                     let msg = "free function without a body";
975                     self.error_item_without_body(item.span, "function", msg, " { <body> }");
976                 }
977             }
978             ItemKind::ForeignMod(_) => {
979                 let old_item = mem::replace(&mut self.extern_mod, Some(item));
980                 self.invalid_visibility(
981                     &item.vis,
982                     Some("place qualifiers on individual foreign items instead"),
983                 );
984                 visit::walk_item(self, item);
985                 self.extern_mod = old_item;
986                 return; // Avoid visiting again.
987             }
988             ItemKind::Enum(ref def, _) => {
989                 for variant in &def.variants {
990                     self.invalid_visibility(&variant.vis, None);
991                     for field in variant.data.fields() {
992                         self.invalid_visibility(&field.vis, None);
993                     }
994                 }
995             }
996             ItemKind::Trait(is_auto, _, ref generics, ref bounds, ref trait_items) => {
997                 if is_auto == IsAuto::Yes {
998                     // Auto traits cannot have generics, super traits nor contain items.
999                     self.deny_generic_params(generics, item.ident.span);
1000                     self.deny_super_traits(bounds, item.ident.span);
1001                     self.deny_items(trait_items, item.ident.span);
1002                 }
1003                 self.no_questions_in_bounds(bounds, "supertraits", true);
1004
1005                 // Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
1006                 // context for the supertraits.
1007                 self.visit_vis(&item.vis);
1008                 self.visit_ident(item.ident);
1009                 self.visit_generics(generics);
1010                 self.with_bound_context(BoundContext::TraitBounds, |this| {
1011                     walk_list!(this, visit_param_bound, bounds);
1012                 });
1013                 walk_list!(self, visit_assoc_item, trait_items, AssocCtxt::Trait);
1014                 walk_list!(self, visit_attribute, &item.attrs);
1015                 return;
1016             }
1017             ItemKind::Mod(_) => {
1018                 // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
1019                 attr::first_attr_value_str_by_name(&item.attrs, sym::path);
1020             }
1021             ItemKind::Union(ref vdata, _) => {
1022                 if let VariantData::Tuple(..) | VariantData::Unit(..) = vdata {
1023                     self.err_handler()
1024                         .span_err(item.span, "tuple and unit unions are not permitted");
1025                 }
1026                 if vdata.fields().is_empty() {
1027                     self.err_handler().span_err(item.span, "unions cannot have zero fields");
1028                 }
1029             }
1030             ItemKind::Const(def, .., None) => {
1031                 self.check_defaultness(item.span, def);
1032                 let msg = "free constant item without body";
1033                 self.error_item_without_body(item.span, "constant", msg, " = <expr>;");
1034             }
1035             ItemKind::Static(.., None) => {
1036                 let msg = "free static item without body";
1037                 self.error_item_without_body(item.span, "static", msg, " = <expr>;");
1038             }
1039             ItemKind::TyAlias(def, _, ref bounds, ref body) => {
1040                 self.check_defaultness(item.span, def);
1041                 if body.is_none() {
1042                     let msg = "free type alias without body";
1043                     self.error_item_without_body(item.span, "type", msg, " = <type>;");
1044                 }
1045                 self.check_type_no_bounds(bounds, "this context");
1046             }
1047             _ => {}
1048         }
1049
1050         visit::walk_item(self, item)
1051     }
1052
1053     fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
1054         match &fi.kind {
1055             ForeignItemKind::Fn(def, sig, _, body) => {
1056                 self.check_defaultness(fi.span, *def);
1057                 self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
1058                 self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header);
1059             }
1060             ForeignItemKind::TyAlias(def, generics, bounds, body) => {
1061                 self.check_defaultness(fi.span, *def);
1062                 self.check_foreign_kind_bodyless(fi.ident, "type", body.as_ref().map(|b| b.span));
1063                 self.check_type_no_bounds(bounds, "`extern` blocks");
1064                 self.check_foreign_ty_genericless(generics);
1065             }
1066             ForeignItemKind::Static(_, _, body) => {
1067                 self.check_foreign_kind_bodyless(fi.ident, "static", body.as_ref().map(|b| b.span));
1068             }
1069             ForeignItemKind::MacCall(..) => {}
1070         }
1071
1072         visit::walk_foreign_item(self, fi)
1073     }
1074
1075     // Mirrors `visit::walk_generic_args`, but tracks relevant state.
1076     fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
1077         match *generic_args {
1078             GenericArgs::AngleBracketed(ref data) => {
1079                 self.check_generic_args_before_constraints(data);
1080
1081                 for arg in &data.args {
1082                     match arg {
1083                         AngleBracketedArg::Arg(arg) => self.visit_generic_arg(arg),
1084                         // Type bindings such as `Item = impl Debug` in `Iterator<Item = Debug>`
1085                         // are allowed to contain nested `impl Trait`.
1086                         AngleBracketedArg::Constraint(constraint) => {
1087                             self.with_impl_trait(None, |this| {
1088                                 this.visit_assoc_ty_constraint_from_generic_args(constraint);
1089                             });
1090                         }
1091                     }
1092                 }
1093             }
1094             GenericArgs::Parenthesized(ref data) => {
1095                 walk_list!(self, visit_ty, &data.inputs);
1096                 if let FnRetTy::Ty(ty) = &data.output {
1097                     // `-> Foo` syntax is essentially an associated type binding,
1098                     // so it is also allowed to contain nested `impl Trait`.
1099                     self.with_impl_trait(None, |this| this.visit_ty(ty));
1100                 }
1101             }
1102         }
1103     }
1104
1105     fn visit_generics(&mut self, generics: &'a Generics) {
1106         let mut prev_ty_default = None;
1107         for param in &generics.params {
1108             if let GenericParamKind::Type { ref default, .. } = param.kind {
1109                 if default.is_some() {
1110                     prev_ty_default = Some(param.ident.span);
1111                 } else if let Some(span) = prev_ty_default {
1112                     self.err_handler()
1113                         .span_err(span, "type parameters with a default must be trailing");
1114                     break;
1115                 }
1116             }
1117         }
1118
1119         validate_generic_param_order(
1120             self.session,
1121             self.err_handler(),
1122             generics.params.iter().map(|param| {
1123                 let ident = Some(param.ident.to_string());
1124                 let (kind, ident) = match &param.kind {
1125                     GenericParamKind::Lifetime { .. } => (ParamKindOrd::Lifetime, ident),
1126                     GenericParamKind::Type { .. } => (ParamKindOrd::Type, ident),
1127                     GenericParamKind::Const { ref ty } => {
1128                         let ty = pprust::ty_to_string(ty);
1129                         (ParamKindOrd::Const, Some(format!("const {}: {}", param.ident, ty)))
1130                     }
1131                 };
1132                 (kind, Some(&*param.bounds), param.ident.span, ident)
1133             }),
1134             generics.span,
1135         );
1136
1137         for predicate in &generics.where_clause.predicates {
1138             if let WherePredicate::EqPredicate(ref predicate) = *predicate {
1139                 self.err_handler()
1140                     .struct_span_err(
1141                         predicate.span,
1142                         "equality constraints are not yet supported in `where` clauses",
1143                     )
1144                     .span_label(predicate.span, "not supported")
1145                     .note(
1146                         "see issue #20041 <https://github.com/rust-lang/rust/issues/20041> \
1147                          for more information",
1148                     )
1149                     .emit();
1150             }
1151         }
1152
1153         visit::walk_generics(self, generics)
1154     }
1155
1156     fn visit_generic_param(&mut self, param: &'a GenericParam) {
1157         if let GenericParamKind::Lifetime { .. } = param.kind {
1158             self.check_lifetime(param.ident);
1159         }
1160         visit::walk_generic_param(self, param);
1161     }
1162
1163     fn visit_param_bound(&mut self, bound: &'a GenericBound) {
1164         match bound {
1165             GenericBound::Trait(_, TraitBoundModifier::MaybeConst) => {
1166                 if let Some(ctx) = self.bound_context {
1167                     let msg = format!("`?const` is not permitted in {}", ctx.description());
1168                     self.err_handler().span_err(bound.span(), &msg);
1169                 }
1170             }
1171
1172             GenericBound::Trait(_, TraitBoundModifier::MaybeConstMaybe) => {
1173                 self.err_handler()
1174                     .span_err(bound.span(), "`?const` and `?` are mutually exclusive");
1175             }
1176
1177             _ => {}
1178         }
1179
1180         visit::walk_param_bound(self, bound)
1181     }
1182
1183     fn visit_pat(&mut self, pat: &'a Pat) {
1184         match pat.kind {
1185             PatKind::Lit(ref expr) => {
1186                 self.check_expr_within_pat(expr, false);
1187             }
1188             PatKind::Range(ref start, ref end, _) => {
1189                 if let Some(expr) = start {
1190                     self.check_expr_within_pat(expr, true);
1191                 }
1192                 if let Some(expr) = end {
1193                     self.check_expr_within_pat(expr, true);
1194                 }
1195             }
1196             _ => {}
1197         }
1198
1199         visit::walk_pat(self, pat)
1200     }
1201
1202     fn visit_where_predicate(&mut self, p: &'a WherePredicate) {
1203         if let &WherePredicate::BoundPredicate(ref bound_predicate) = p {
1204             // A type binding, eg `for<'c> Foo: Send+Clone+'c`
1205             self.check_late_bound_lifetime_defs(&bound_predicate.bound_generic_params);
1206         }
1207         visit::walk_where_predicate(self, p);
1208     }
1209
1210     fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef, m: &'a TraitBoundModifier) {
1211         self.check_late_bound_lifetime_defs(&t.bound_generic_params);
1212         visit::walk_poly_trait_ref(self, t, m);
1213     }
1214
1215     fn visit_variant_data(&mut self, s: &'a VariantData) {
1216         self.with_banned_assoc_ty_bound(|this| visit::walk_struct_def(this, s))
1217     }
1218
1219     fn visit_enum_def(
1220         &mut self,
1221         enum_definition: &'a EnumDef,
1222         generics: &'a Generics,
1223         item_id: NodeId,
1224         _: Span,
1225     ) {
1226         self.with_banned_assoc_ty_bound(|this| {
1227             visit::walk_enum_def(this, enum_definition, generics, item_id)
1228         })
1229     }
1230
1231     fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) {
1232         // Only associated `fn`s can have `self` parameters.
1233         let self_semantic = match fk.ctxt() {
1234             Some(FnCtxt::Assoc(_)) => SelfSemantic::Yes,
1235             _ => SelfSemantic::No,
1236         };
1237         self.check_fn_decl(fk.decl(), self_semantic);
1238
1239         self.check_c_varadic_type(fk);
1240
1241         // Functions cannot both be `const async`
1242         if let Some(FnHeader {
1243             constness: Const::Yes(cspan),
1244             asyncness: Async::Yes { span: aspan, .. },
1245             ..
1246         }) = fk.header()
1247         {
1248             self.err_handler()
1249                 .struct_span_err(
1250                     vec![*cspan, *aspan],
1251                     "functions cannot be both `const` and `async`",
1252                 )
1253                 .span_label(*cspan, "`const` because of this")
1254                 .span_label(*aspan, "`async` because of this")
1255                 .span_label(span, "") // Point at the fn header.
1256                 .emit();
1257         }
1258
1259         // Functions without bodies cannot have patterns.
1260         if let FnKind::Fn(ctxt, _, sig, _, None) = fk {
1261             Self::check_decl_no_pat(&sig.decl, |span, mut_ident| {
1262                 let (code, msg, label) = match ctxt {
1263                     FnCtxt::Foreign => (
1264                         error_code!(E0130),
1265                         "patterns aren't allowed in foreign function declarations",
1266                         "pattern not allowed in foreign function",
1267                     ),
1268                     _ => (
1269                         error_code!(E0642),
1270                         "patterns aren't allowed in functions without bodies",
1271                         "pattern not allowed in function without body",
1272                     ),
1273                 };
1274                 if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) {
1275                     self.lint_buffer.buffer_lint(PATTERNS_IN_FNS_WITHOUT_BODY, id, span, msg);
1276                 } else {
1277                     self.err_handler()
1278                         .struct_span_err(span, msg)
1279                         .span_label(span, label)
1280                         .code(code)
1281                         .emit();
1282                 }
1283             });
1284         }
1285
1286         visit::walk_fn(self, fk, span);
1287     }
1288
1289     fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
1290         if ctxt == AssocCtxt::Trait || !self.in_trait_impl {
1291             self.check_defaultness(item.span, item.kind.defaultness());
1292         }
1293
1294         if ctxt == AssocCtxt::Impl {
1295             match &item.kind {
1296                 AssocItemKind::Const(_, _, body) => {
1297                     self.check_impl_item_provided(item.span, body, "constant", " = <expr>;");
1298                 }
1299                 AssocItemKind::Fn(_, _, _, body) => {
1300                     self.check_impl_item_provided(item.span, body, "function", " { <body> }");
1301                 }
1302                 AssocItemKind::TyAlias(_, _, bounds, body) => {
1303                     self.check_impl_item_provided(item.span, body, "type", " = <type>;");
1304                     self.check_type_no_bounds(bounds, "`impl`s");
1305                 }
1306                 _ => {}
1307             }
1308         }
1309
1310         if ctxt == AssocCtxt::Trait || self.in_trait_impl {
1311             self.invalid_visibility(&item.vis, None);
1312             if let AssocItemKind::Fn(_, sig, _, _) = &item.kind {
1313                 self.check_trait_fn_not_const(sig.header.constness);
1314                 self.check_trait_fn_not_async(item.span, sig.header.asyncness);
1315             }
1316         }
1317
1318         if let AssocItemKind::Const(..) = item.kind {
1319             self.check_item_named(item.ident, "const");
1320         }
1321
1322         self.with_in_trait_impl(false, |this| visit::walk_assoc_item(this, item, ctxt));
1323     }
1324 }
1325
1326 pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> bool {
1327     let mut validator = AstValidator {
1328         session,
1329         extern_mod: None,
1330         in_trait_impl: false,
1331         has_proc_macro_decls: false,
1332         outer_impl_trait: None,
1333         bound_context: None,
1334         is_impl_trait_banned: false,
1335         is_assoc_ty_bound_banned: false,
1336         lint_buffer: lints,
1337     };
1338     visit::walk_crate(&mut validator, krate);
1339
1340     validator.has_proc_macro_decls
1341 }