]> git.lizzy.rs Git - rust.git/blob - src/librustc_ast_passes/ast_validation.rs
Rollup merge of #68140 - ecstatic-morse:const-trait-bound-opt-out, r=oli-obk
[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 rustc_data_structures::fx::FxHashMap;
10 use rustc_errors::{struct_span_err, Applicability, FatalError};
11 use rustc_parse::validate_attr;
12 use rustc_session::lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY;
13 use rustc_session::lint::LintBuffer;
14 use rustc_session::Session;
15 use rustc_span::source_map::Spanned;
16 use rustc_span::symbol::{kw, sym};
17 use rustc_span::Span;
18 use std::mem;
19 use syntax::ast::*;
20 use syntax::attr;
21 use syntax::expand::is_proc_macro_attr;
22 use syntax::print::pprust;
23 use syntax::visit::{self, Visitor};
24 use syntax::walk_list;
25
26 /// A syntactic context that disallows certain kinds of bounds (e.g., `?Trait` or `?const Trait`).
27 #[derive(Clone, Copy)]
28 enum BoundContext {
29     ImplTrait,
30     TraitBounds,
31     TraitObject,
32 }
33
34 impl BoundContext {
35     fn description(&self) -> &'static str {
36         match self {
37             Self::ImplTrait => "`impl Trait`",
38             Self::TraitBounds => "supertraits",
39             Self::TraitObject => "trait objects",
40         }
41     }
42 }
43
44 struct AstValidator<'a> {
45     session: &'a Session,
46     has_proc_macro_decls: bool,
47
48     /// Used to ban nested `impl Trait`, e.g., `impl Into<impl Debug>`.
49     /// Nested `impl Trait` _is_ allowed in associated type position,
50     /// e.g., `impl Iterator<Item = impl Debug>`.
51     outer_impl_trait: Option<Span>,
52
53     /// Keeps track of the `BoundContext` as we recurse.
54     ///
55     /// This is used to forbid `?const Trait` bounds in, e.g.,
56     /// `impl Iterator<Item = Box<dyn ?const Trait>`.
57     bound_context: Option<BoundContext>,
58
59     /// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
60     /// or `Foo::Bar<impl Trait>`
61     is_impl_trait_banned: bool,
62
63     /// Used to ban associated type bounds (i.e., `Type<AssocType: Bounds>`) in
64     /// certain positions.
65     is_assoc_ty_bound_banned: bool,
66
67     lint_buffer: &'a mut LintBuffer,
68 }
69
70 impl<'a> AstValidator<'a> {
71     fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
72         let old = mem::replace(&mut self.is_impl_trait_banned, true);
73         f(self);
74         self.is_impl_trait_banned = old;
75     }
76
77     fn with_banned_assoc_ty_bound(&mut self, f: impl FnOnce(&mut Self)) {
78         let old = mem::replace(&mut self.is_assoc_ty_bound_banned, true);
79         f(self);
80         self.is_assoc_ty_bound_banned = old;
81     }
82
83     fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
84         let old = mem::replace(&mut self.outer_impl_trait, outer);
85         if outer.is_some() {
86             self.with_bound_context(BoundContext::ImplTrait, |this| f(this));
87         } else {
88             f(self)
89         }
90         self.outer_impl_trait = old;
91     }
92
93     fn with_bound_context(&mut self, ctx: BoundContext, f: impl FnOnce(&mut Self)) {
94         let old = self.bound_context.replace(ctx);
95         f(self);
96         self.bound_context = old;
97     }
98
99     fn visit_assoc_ty_constraint_from_generic_args(&mut self, constraint: &'a AssocTyConstraint) {
100         match constraint.kind {
101             AssocTyConstraintKind::Equality { .. } => {}
102             AssocTyConstraintKind::Bound { .. } => {
103                 if self.is_assoc_ty_bound_banned {
104                     self.err_handler().span_err(
105                         constraint.span,
106                         "associated type bounds are not allowed within structs, enums, or unions",
107                     );
108                 }
109             }
110         }
111         self.visit_assoc_ty_constraint(constraint);
112     }
113
114     // Mirrors `visit::walk_ty`, but tracks relevant state.
115     fn walk_ty(&mut self, t: &'a Ty) {
116         match t.kind {
117             TyKind::ImplTrait(..) => {
118                 self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t))
119             }
120             TyKind::TraitObject(..) => {
121                 self.with_bound_context(BoundContext::TraitObject, |this| visit::walk_ty(this, t));
122             }
123             TyKind::Path(ref qself, ref path) => {
124                 // We allow these:
125                 //  - `Option<impl Trait>`
126                 //  - `option::Option<impl Trait>`
127                 //  - `option::Option<T>::Foo<impl Trait>
128                 //
129                 // But not these:
130                 //  - `<impl Trait>::Foo`
131                 //  - `option::Option<impl Trait>::Foo`.
132                 //
133                 // To implement this, we disallow `impl Trait` from `qself`
134                 // (for cases like `<impl Trait>::Foo>`)
135                 // but we allow `impl Trait` in `GenericArgs`
136                 // iff there are no more PathSegments.
137                 if let Some(ref qself) = *qself {
138                     // `impl Trait` in `qself` is always illegal
139                     self.with_banned_impl_trait(|this| this.visit_ty(&qself.ty));
140                 }
141
142                 // Note that there should be a call to visit_path here,
143                 // so if any logic is added to process `Path`s a call to it should be
144                 // added both in visit_path and here. This code mirrors visit::walk_path.
145                 for (i, segment) in path.segments.iter().enumerate() {
146                     // Allow `impl Trait` iff we're on the final path segment
147                     if i == path.segments.len() - 1 {
148                         self.visit_path_segment(path.span, segment);
149                     } else {
150                         self.with_banned_impl_trait(|this| {
151                             this.visit_path_segment(path.span, segment)
152                         });
153                     }
154                 }
155             }
156             _ => visit::walk_ty(self, t),
157         }
158     }
159
160     fn err_handler(&self) -> &rustc_errors::Handler {
161         &self.session.diagnostic()
162     }
163
164     fn check_lifetime(&self, ident: Ident) {
165         let valid_names = [kw::UnderscoreLifetime, kw::StaticLifetime, kw::Invalid];
166         if !valid_names.contains(&ident.name) && ident.without_first_quote().is_reserved() {
167             self.err_handler().span_err(ident.span, "lifetimes cannot use keyword names");
168         }
169     }
170
171     fn check_label(&self, ident: Ident) {
172         if ident.without_first_quote().is_reserved() {
173             self.err_handler()
174                 .span_err(ident.span, &format!("invalid label name `{}`", ident.name));
175         }
176     }
177
178     fn invalid_visibility(&self, vis: &Visibility, note: Option<&str>) {
179         if let VisibilityKind::Inherited = vis.node {
180             return;
181         }
182
183         let mut err =
184             struct_span_err!(self.session, vis.span, E0449, "unnecessary visibility qualifier");
185         if vis.node.is_pub() {
186             err.span_label(vis.span, "`pub` not permitted here because it's implied");
187         }
188         if let Some(note) = note {
189             err.note(note);
190         }
191         err.emit();
192     }
193
194     fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, bool)) {
195         for Param { pat, .. } in &decl.inputs {
196             match pat.kind {
197                 PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, None) | PatKind::Wild => {}
198                 PatKind::Ident(BindingMode::ByValue(Mutability::Mut), _, None) => {
199                     report_err(pat.span, true)
200                 }
201                 _ => report_err(pat.span, false),
202             }
203         }
204     }
205
206     fn check_trait_fn_not_async(&self, span: Span, asyncness: IsAsync) {
207         if asyncness.is_async() {
208             struct_span_err!(self.session, span, E0706, "trait fns cannot be declared `async`")
209                 .note("`async` trait functions are not currently supported")
210                 .note(
211                     "consider using the `async-trait` crate: \
212                        https://crates.io/crates/async-trait",
213                 )
214                 .emit();
215         }
216     }
217
218     fn check_trait_fn_not_const(&self, constness: Spanned<Constness>) {
219         if constness.node == Constness::Const {
220             struct_span_err!(
221                 self.session,
222                 constness.span,
223                 E0379,
224                 "trait fns cannot be declared const"
225             )
226             .span_label(constness.span, "trait fns cannot be const")
227             .emit();
228         }
229     }
230
231     // FIXME(ecstaticmorse): Instead, use `bound_context` to check this in `visit_param_bound`.
232     fn no_questions_in_bounds(&self, bounds: &GenericBounds, where_: &str, is_trait: bool) {
233         for bound in bounds {
234             if let GenericBound::Trait(ref poly, TraitBoundModifier::Maybe) = *bound {
235                 let mut err = self.err_handler().struct_span_err(
236                     poly.span,
237                     &format!("`?Trait` is not permitted in {}", where_),
238                 );
239                 if is_trait {
240                     let path_str = pprust::path_to_string(&poly.trait_ref.path);
241                     err.note(&format!("traits are `?{}` by default", path_str));
242                 }
243                 err.emit();
244             }
245         }
246     }
247
248     /// Matches `'-' lit | lit (cf. parser::Parser::parse_literal_maybe_minus)`,
249     /// or paths for ranges.
250     //
251     // FIXME: do we want to allow `expr -> pattern` conversion to create path expressions?
252     // That means making this work:
253     //
254     // ```rust,ignore (FIXME)
255     // struct S;
256     // macro_rules! m {
257     //     ($a:expr) => {
258     //         let $a = S;
259     //     }
260     // }
261     // m!(S);
262     // ```
263     fn check_expr_within_pat(&self, expr: &Expr, allow_paths: bool) {
264         match expr.kind {
265             ExprKind::Lit(..) | ExprKind::Err => {}
266             ExprKind::Path(..) if allow_paths => {}
267             ExprKind::Unary(UnOp::Neg, ref inner)
268                 if match inner.kind {
269                     ExprKind::Lit(_) => true,
270                     _ => false,
271                 } => {}
272             _ => self.err_handler().span_err(
273                 expr.span,
274                 "arbitrary expressions aren't allowed \
275                                                          in patterns",
276             ),
277         }
278     }
279
280     fn check_late_bound_lifetime_defs(&self, params: &[GenericParam]) {
281         // Check only lifetime parameters are present and that the lifetime
282         // parameters that are present have no bounds.
283         let non_lt_param_spans: Vec<_> = params
284             .iter()
285             .filter_map(|param| match param.kind {
286                 GenericParamKind::Lifetime { .. } => {
287                     if !param.bounds.is_empty() {
288                         let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
289                         self.err_handler()
290                             .span_err(spans, "lifetime bounds cannot be used in this context");
291                     }
292                     None
293                 }
294                 _ => Some(param.ident.span),
295             })
296             .collect();
297         if !non_lt_param_spans.is_empty() {
298             self.err_handler().span_err(
299                 non_lt_param_spans,
300                 "only lifetime parameters can be used in this context",
301             );
302         }
303     }
304
305     fn check_fn_decl(&self, fn_decl: &FnDecl) {
306         match &*fn_decl.inputs {
307             [Param { ty, span, .. }] => {
308                 if let TyKind::CVarArgs = ty.kind {
309                     self.err_handler().span_err(
310                         *span,
311                         "C-variadic function must be declared with at least one named argument",
312                     );
313                 }
314             }
315             [ps @ .., _] => {
316                 for Param { ty, span, .. } in ps {
317                     if let TyKind::CVarArgs = ty.kind {
318                         self.err_handler().span_err(
319                             *span,
320                             "`...` must be the last argument of a C-variadic function",
321                         );
322                     }
323                 }
324             }
325             _ => {}
326         }
327
328         fn_decl
329             .inputs
330             .iter()
331             .flat_map(|i| i.attrs.as_ref())
332             .filter(|attr| {
333                 let arr = [sym::allow, sym::cfg, sym::cfg_attr, sym::deny, sym::forbid, sym::warn];
334                 !arr.contains(&attr.name_or_empty()) && attr::is_builtin_attr(attr)
335             })
336             .for_each(|attr| {
337                 if attr.is_doc_comment() {
338                     self.err_handler()
339                         .struct_span_err(
340                             attr.span,
341                             "documentation comments cannot be applied to function parameters",
342                         )
343                         .span_label(attr.span, "doc comments are not allowed here")
344                         .emit();
345                 } else {
346                     self.err_handler().span_err(
347                         attr.span,
348                         "allow, cfg, cfg_attr, deny, \
349                 forbid, and warn are the only allowed built-in attributes in function parameters",
350                     )
351                 }
352             });
353     }
354
355     fn check_defaultness(&self, span: Span, defaultness: Defaultness) {
356         if let Defaultness::Default = defaultness {
357             self.err_handler()
358                 .struct_span_err(span, "`default` is only allowed on items in `impl` definitions")
359                 .emit();
360         }
361     }
362
363     fn check_impl_item_provided<T>(&self, sp: Span, body: &Option<T>, ctx: &str, sugg: &str) {
364         if body.is_some() {
365             return;
366         }
367
368         self.err_handler()
369             .struct_span_err(sp, &format!("associated {} in `impl` without body", ctx))
370             .span_suggestion(
371                 self.session.source_map().end_point(sp),
372                 &format!("provide a definition for the {}", ctx),
373                 sugg.to_string(),
374                 Applicability::HasPlaceholders,
375             )
376             .emit();
377     }
378
379     fn check_impl_assoc_type_no_bounds(&self, bounds: &[GenericBound]) {
380         let span = match bounds {
381             [] => return,
382             [b0] => b0.span(),
383             [b0, .., bl] => b0.span().to(bl.span()),
384         };
385         self.err_handler()
386             .struct_span_err(span, "bounds on associated `type`s in `impl`s have no effect")
387             .emit();
388     }
389
390     fn check_c_varadic_type(&self, decl: &FnDecl) {
391         for Param { ty, span, .. } in &decl.inputs {
392             if let TyKind::CVarArgs = ty.kind {
393                 self.err_handler()
394                     .struct_span_err(
395                         *span,
396                         "only foreign or `unsafe extern \"C\" functions may be C-variadic",
397                     )
398                     .emit();
399             }
400         }
401     }
402 }
403
404 enum GenericPosition {
405     Param,
406     Arg,
407 }
408
409 fn validate_generics_order<'a>(
410     sess: &Session,
411     handler: &rustc_errors::Handler,
412     generics: impl Iterator<Item = (ParamKindOrd, Option<&'a [GenericBound]>, Span, Option<String>)>,
413     pos: GenericPosition,
414     span: Span,
415 ) {
416     let mut max_param: Option<ParamKindOrd> = None;
417     let mut out_of_order = FxHashMap::default();
418     let mut param_idents = vec![];
419     let mut found_type = false;
420     let mut found_const = false;
421
422     for (kind, bounds, span, ident) in generics {
423         if let Some(ident) = ident {
424             param_idents.push((kind, bounds, param_idents.len(), ident));
425         }
426         let max_param = &mut max_param;
427         match max_param {
428             Some(max_param) if *max_param > kind => {
429                 let entry = out_of_order.entry(kind).or_insert((*max_param, vec![]));
430                 entry.1.push(span);
431             }
432             Some(_) | None => *max_param = Some(kind),
433         };
434         match kind {
435             ParamKindOrd::Type => found_type = true,
436             ParamKindOrd::Const => found_const = true,
437             _ => {}
438         }
439     }
440
441     let mut ordered_params = "<".to_string();
442     if !out_of_order.is_empty() {
443         param_idents.sort_by_key(|&(po, _, i, _)| (po, i));
444         let mut first = true;
445         for (_, bounds, _, ident) in param_idents {
446             if !first {
447                 ordered_params += ", ";
448             }
449             ordered_params += &ident;
450             if let Some(bounds) = bounds {
451                 if !bounds.is_empty() {
452                     ordered_params += ": ";
453                     ordered_params += &pprust::bounds_to_string(&bounds);
454                 }
455             }
456             first = false;
457         }
458     }
459     ordered_params += ">";
460
461     let pos_str = match pos {
462         GenericPosition::Param => "parameter",
463         GenericPosition::Arg => "argument",
464     };
465
466     for (param_ord, (max_param, spans)) in &out_of_order {
467         let mut err = handler.struct_span_err(
468             spans.clone(),
469             &format!(
470                 "{} {pos}s must be declared prior to {} {pos}s",
471                 param_ord,
472                 max_param,
473                 pos = pos_str,
474             ),
475         );
476         if let GenericPosition::Param = pos {
477             err.span_suggestion(
478                 span,
479                 &format!(
480                     "reorder the {}s: lifetimes, then types{}",
481                     pos_str,
482                     if sess.features_untracked().const_generics { ", then consts" } else { "" },
483                 ),
484                 ordered_params.clone(),
485                 Applicability::MachineApplicable,
486             );
487         }
488         err.emit();
489     }
490
491     // FIXME(const_generics): we shouldn't have to abort here at all, but we currently get ICEs
492     // if we don't. Const parameters and type parameters can currently conflict if they
493     // are out-of-order.
494     if !out_of_order.is_empty() && found_type && found_const {
495         FatalError.raise();
496     }
497 }
498
499 impl<'a> Visitor<'a> for AstValidator<'a> {
500     fn visit_attribute(&mut self, attr: &Attribute) {
501         validate_attr::check_meta(&self.session.parse_sess, attr);
502     }
503
504     fn visit_expr(&mut self, expr: &'a Expr) {
505         match &expr.kind {
506             ExprKind::Closure(_, _, _, fn_decl, _, _) => {
507                 self.check_fn_decl(fn_decl);
508             }
509             ExprKind::InlineAsm(..) if !self.session.target.target.options.allow_asm => {
510                 struct_span_err!(
511                     self.session,
512                     expr.span,
513                     E0472,
514                     "asm! is unsupported on this target"
515                 )
516                 .emit();
517             }
518             _ => {}
519         }
520
521         visit::walk_expr(self, expr);
522     }
523
524     fn visit_ty(&mut self, ty: &'a Ty) {
525         match ty.kind {
526             TyKind::BareFn(ref bfty) => {
527                 self.check_fn_decl(&bfty.decl);
528                 Self::check_decl_no_pat(&bfty.decl, |span, _| {
529                     struct_span_err!(
530                         self.session,
531                         span,
532                         E0561,
533                         "patterns aren't allowed in function pointer types"
534                     )
535                     .emit();
536                 });
537                 self.check_late_bound_lifetime_defs(&bfty.generic_params);
538             }
539             TyKind::TraitObject(ref bounds, ..) => {
540                 let mut any_lifetime_bounds = false;
541                 for bound in bounds {
542                     if let GenericBound::Outlives(ref lifetime) = *bound {
543                         if any_lifetime_bounds {
544                             struct_span_err!(
545                                 self.session,
546                                 lifetime.ident.span,
547                                 E0226,
548                                 "only a single explicit lifetime bound is permitted"
549                             )
550                             .emit();
551                             break;
552                         }
553                         any_lifetime_bounds = true;
554                     }
555                 }
556                 self.no_questions_in_bounds(bounds, "trait object types", false);
557             }
558             TyKind::ImplTrait(_, ref bounds) => {
559                 if self.is_impl_trait_banned {
560                     struct_span_err!(
561                         self.session,
562                         ty.span,
563                         E0667,
564                         "`impl Trait` is not allowed in path parameters"
565                     )
566                     .emit();
567                 }
568
569                 if let Some(outer_impl_trait_sp) = self.outer_impl_trait {
570                     struct_span_err!(
571                         self.session,
572                         ty.span,
573                         E0666,
574                         "nested `impl Trait` is not allowed"
575                     )
576                     .span_label(outer_impl_trait_sp, "outer `impl Trait`")
577                     .span_label(ty.span, "nested `impl Trait` here")
578                     .emit();
579                 }
580
581                 if !bounds
582                     .iter()
583                     .any(|b| if let GenericBound::Trait(..) = *b { true } else { false })
584                 {
585                     self.err_handler().span_err(ty.span, "at least one trait must be specified");
586                 }
587
588                 self.walk_ty(ty);
589                 return;
590             }
591             _ => {}
592         }
593
594         self.walk_ty(ty)
595     }
596
597     fn visit_label(&mut self, label: &'a Label) {
598         self.check_label(label.ident);
599         visit::walk_label(self, label);
600     }
601
602     fn visit_lifetime(&mut self, lifetime: &'a Lifetime) {
603         self.check_lifetime(lifetime.ident);
604         visit::walk_lifetime(self, lifetime);
605     }
606
607     fn visit_item(&mut self, item: &'a Item) {
608         if item.attrs.iter().any(|attr| is_proc_macro_attr(attr)) {
609             self.has_proc_macro_decls = true;
610         }
611
612         match item.kind {
613             ItemKind::Impl {
614                 unsafety,
615                 polarity,
616                 defaultness: _,
617                 constness: _,
618                 generics: _,
619                 of_trait: Some(_),
620                 ref self_ty,
621                 ref items,
622             } => {
623                 self.invalid_visibility(&item.vis, None);
624                 if let TyKind::Err = self_ty.kind {
625                     self.err_handler()
626                         .struct_span_err(item.span, "`impl Trait for .. {}` is an obsolete syntax")
627                         .help("use `auto trait Trait {}` instead")
628                         .emit();
629                 }
630                 if unsafety == Unsafety::Unsafe && polarity == ImplPolarity::Negative {
631                     struct_span_err!(
632                         self.session,
633                         item.span,
634                         E0198,
635                         "negative impls cannot be unsafe"
636                     )
637                     .emit();
638                 }
639                 for impl_item in items {
640                     self.invalid_visibility(&impl_item.vis, None);
641                     if let AssocItemKind::Fn(ref sig, _) = impl_item.kind {
642                         self.check_trait_fn_not_const(sig.header.constness);
643                         self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness.node);
644                     }
645                 }
646             }
647             ItemKind::Impl {
648                 unsafety,
649                 polarity,
650                 defaultness,
651                 constness,
652                 generics: _,
653                 of_trait: None,
654                 self_ty: _,
655                 items: _,
656             } => {
657                 self.invalid_visibility(
658                     &item.vis,
659                     Some("place qualifiers on individual impl items instead"),
660                 );
661                 if unsafety == Unsafety::Unsafe {
662                     struct_span_err!(
663                         self.session,
664                         item.span,
665                         E0197,
666                         "inherent impls cannot be unsafe"
667                     )
668                     .emit();
669                 }
670                 if polarity == ImplPolarity::Negative {
671                     self.err_handler().span_err(item.span, "inherent impls cannot be negative");
672                 }
673                 if defaultness == Defaultness::Default {
674                     self.err_handler()
675                         .struct_span_err(item.span, "inherent impls cannot be default")
676                         .note("only trait implementations may be annotated with default")
677                         .emit();
678                 }
679                 if constness == Constness::Const {
680                     self.err_handler()
681                         .struct_span_err(item.span, "inherent impls cannot be `const`")
682                         .note("only trait implementations may be annotated with `const`")
683                         .emit();
684                 }
685             }
686             ItemKind::Fn(ref sig, ref generics, _) => {
687                 self.visit_fn_header(&sig.header);
688                 self.check_fn_decl(&sig.decl);
689                 // We currently do not permit const generics in `const fn`, as
690                 // this is tantamount to allowing compile-time dependent typing.
691                 if sig.header.constness.node == Constness::Const {
692                     // Look for const generics and error if we find any.
693                     for param in &generics.params {
694                         match param.kind {
695                             GenericParamKind::Const { .. } => {
696                                 self.err_handler()
697                                     .struct_span_err(
698                                         item.span,
699                                         "const parameters are not permitted in `const fn`",
700                                     )
701                                     .emit();
702                             }
703                             _ => {}
704                         }
705                     }
706                 }
707                 // Reject C-varadic type unless the function is `unsafe extern "C"` semantically.
708                 match sig.header.ext {
709                     Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. })
710                     | Extern::Implicit
711                         if sig.header.unsafety == Unsafety::Unsafe => {}
712                     _ => self.check_c_varadic_type(&sig.decl),
713                 }
714             }
715             ItemKind::ForeignMod(..) => {
716                 self.invalid_visibility(
717                     &item.vis,
718                     Some("place qualifiers on individual foreign items instead"),
719                 );
720             }
721             ItemKind::Enum(ref def, _) => {
722                 for variant in &def.variants {
723                     self.invalid_visibility(&variant.vis, None);
724                     for field in variant.data.fields() {
725                         self.invalid_visibility(&field.vis, None);
726                     }
727                 }
728             }
729             ItemKind::Trait(is_auto, _, ref generics, ref bounds, ref trait_items) => {
730                 if is_auto == IsAuto::Yes {
731                     // Auto traits cannot have generics, super traits nor contain items.
732                     if !generics.params.is_empty() {
733                         struct_span_err!(
734                             self.session,
735                             item.span,
736                             E0567,
737                             "auto traits cannot have generic parameters"
738                         )
739                         .emit();
740                     }
741                     if !bounds.is_empty() {
742                         struct_span_err!(
743                             self.session,
744                             item.span,
745                             E0568,
746                             "auto traits cannot have super traits"
747                         )
748                         .emit();
749                     }
750                     if !trait_items.is_empty() {
751                         struct_span_err!(
752                             self.session,
753                             item.span,
754                             E0380,
755                             "auto traits cannot have methods or associated items"
756                         )
757                         .emit();
758                     }
759                 }
760                 self.no_questions_in_bounds(bounds, "supertraits", true);
761
762                 // Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
763                 // context for the supertraits.
764                 self.visit_vis(&item.vis);
765                 self.visit_ident(item.ident);
766                 self.visit_generics(generics);
767                 self.with_bound_context(BoundContext::TraitBounds, |this| {
768                     walk_list!(this, visit_param_bound, bounds);
769                 });
770                 walk_list!(self, visit_trait_item, trait_items);
771                 walk_list!(self, visit_attribute, &item.attrs);
772                 return;
773             }
774             ItemKind::Mod(_) => {
775                 // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
776                 attr::first_attr_value_str_by_name(&item.attrs, sym::path);
777             }
778             ItemKind::Union(ref vdata, _) => {
779                 if let VariantData::Tuple(..) | VariantData::Unit(..) = vdata {
780                     self.err_handler()
781                         .span_err(item.span, "tuple and unit unions are not permitted");
782                 }
783                 if vdata.fields().is_empty() {
784                     self.err_handler().span_err(item.span, "unions cannot have zero fields");
785                 }
786             }
787             _ => {}
788         }
789
790         visit::walk_item(self, item)
791     }
792
793     fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
794         match fi.kind {
795             ForeignItemKind::Fn(ref decl, _) => {
796                 self.check_fn_decl(decl);
797                 Self::check_decl_no_pat(decl, |span, _| {
798                     struct_span_err!(
799                         self.session,
800                         span,
801                         E0130,
802                         "patterns aren't allowed in foreign function declarations"
803                     )
804                     .span_label(span, "pattern not allowed in foreign function")
805                     .emit();
806                 });
807             }
808             ForeignItemKind::Static(..) | ForeignItemKind::Ty | ForeignItemKind::Macro(..) => {}
809         }
810
811         visit::walk_foreign_item(self, fi)
812     }
813
814     // Mirrors `visit::walk_generic_args`, but tracks relevant state.
815     fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
816         match *generic_args {
817             GenericArgs::AngleBracketed(ref data) => {
818                 walk_list!(self, visit_generic_arg, &data.args);
819                 validate_generics_order(
820                     self.session,
821                     self.err_handler(),
822                     data.args.iter().map(|arg| {
823                         (
824                             match arg {
825                                 GenericArg::Lifetime(..) => ParamKindOrd::Lifetime,
826                                 GenericArg::Type(..) => ParamKindOrd::Type,
827                                 GenericArg::Const(..) => ParamKindOrd::Const,
828                             },
829                             None,
830                             arg.span(),
831                             None,
832                         )
833                     }),
834                     GenericPosition::Arg,
835                     generic_args.span(),
836                 );
837
838                 // Type bindings such as `Item = impl Debug` in `Iterator<Item = Debug>`
839                 // are allowed to contain nested `impl Trait`.
840                 self.with_impl_trait(None, |this| {
841                     walk_list!(
842                         this,
843                         visit_assoc_ty_constraint_from_generic_args,
844                         &data.constraints
845                     );
846                 });
847             }
848             GenericArgs::Parenthesized(ref data) => {
849                 walk_list!(self, visit_ty, &data.inputs);
850                 if let FunctionRetTy::Ty(ty) = &data.output {
851                     // `-> Foo` syntax is essentially an associated type binding,
852                     // so it is also allowed to contain nested `impl Trait`.
853                     self.with_impl_trait(None, |this| this.visit_ty(ty));
854                 }
855             }
856         }
857     }
858
859     fn visit_generics(&mut self, generics: &'a Generics) {
860         let mut prev_ty_default = None;
861         for param in &generics.params {
862             if let GenericParamKind::Type { ref default, .. } = param.kind {
863                 if default.is_some() {
864                     prev_ty_default = Some(param.ident.span);
865                 } else if let Some(span) = prev_ty_default {
866                     self.err_handler()
867                         .span_err(span, "type parameters with a default must be trailing");
868                     break;
869                 }
870             }
871         }
872
873         validate_generics_order(
874             self.session,
875             self.err_handler(),
876             generics.params.iter().map(|param| {
877                 let ident = Some(param.ident.to_string());
878                 let (kind, ident) = match &param.kind {
879                     GenericParamKind::Lifetime { .. } => (ParamKindOrd::Lifetime, ident),
880                     GenericParamKind::Type { .. } => (ParamKindOrd::Type, ident),
881                     GenericParamKind::Const { ref ty } => {
882                         let ty = pprust::ty_to_string(ty);
883                         (ParamKindOrd::Const, Some(format!("const {}: {}", param.ident, ty)))
884                     }
885                 };
886                 (kind, Some(&*param.bounds), param.ident.span, ident)
887             }),
888             GenericPosition::Param,
889             generics.span,
890         );
891
892         for predicate in &generics.where_clause.predicates {
893             if let WherePredicate::EqPredicate(ref predicate) = *predicate {
894                 self.err_handler()
895                     .struct_span_err(
896                         predicate.span,
897                         "equality constraints are not yet supported in `where` clauses",
898                     )
899                     .span_label(predicate.span, "not supported")
900                     .note(
901                         "for more information, see https://github.com/rust-lang/rust/issues/20041",
902                     )
903                     .emit();
904             }
905         }
906
907         visit::walk_generics(self, generics)
908     }
909
910     fn visit_generic_param(&mut self, param: &'a GenericParam) {
911         if let GenericParamKind::Lifetime { .. } = param.kind {
912             self.check_lifetime(param.ident);
913         }
914         visit::walk_generic_param(self, param);
915     }
916
917     fn visit_param_bound(&mut self, bound: &'a GenericBound) {
918         match bound {
919             GenericBound::Trait(_, TraitBoundModifier::MaybeConst) => {
920                 if let Some(ctx) = self.bound_context {
921                     let msg = format!("`?const` is not permitted in {}", ctx.description());
922                     self.err_handler().span_err(bound.span(), &msg);
923                 }
924             }
925
926             GenericBound::Trait(_, TraitBoundModifier::MaybeConstMaybe) => {
927                 self.err_handler()
928                     .span_err(bound.span(), "`?const` and `?` are mutually exclusive");
929             }
930
931             _ => {}
932         }
933
934         visit::walk_param_bound(self, bound)
935     }
936
937     fn visit_pat(&mut self, pat: &'a Pat) {
938         match pat.kind {
939             PatKind::Lit(ref expr) => {
940                 self.check_expr_within_pat(expr, false);
941             }
942             PatKind::Range(ref start, ref end, _) => {
943                 if let Some(expr) = start {
944                     self.check_expr_within_pat(expr, true);
945                 }
946                 if let Some(expr) = end {
947                     self.check_expr_within_pat(expr, true);
948                 }
949             }
950             _ => {}
951         }
952
953         visit::walk_pat(self, pat)
954     }
955
956     fn visit_where_predicate(&mut self, p: &'a WherePredicate) {
957         if let &WherePredicate::BoundPredicate(ref bound_predicate) = p {
958             // A type binding, eg `for<'c> Foo: Send+Clone+'c`
959             self.check_late_bound_lifetime_defs(&bound_predicate.bound_generic_params);
960         }
961         visit::walk_where_predicate(self, p);
962     }
963
964     fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef, m: &'a TraitBoundModifier) {
965         self.check_late_bound_lifetime_defs(&t.bound_generic_params);
966         visit::walk_poly_trait_ref(self, t, m);
967     }
968
969     fn visit_variant_data(&mut self, s: &'a VariantData) {
970         self.with_banned_assoc_ty_bound(|this| visit::walk_struct_def(this, s))
971     }
972
973     fn visit_enum_def(
974         &mut self,
975         enum_definition: &'a EnumDef,
976         generics: &'a Generics,
977         item_id: NodeId,
978         _: Span,
979     ) {
980         self.with_banned_assoc_ty_bound(|this| {
981             visit::walk_enum_def(this, enum_definition, generics, item_id)
982         })
983     }
984
985     fn visit_impl_item(&mut self, ii: &'a AssocItem) {
986         match &ii.kind {
987             AssocItemKind::Const(_, body) => {
988                 self.check_impl_item_provided(ii.span, body, "constant", " = <expr>;");
989             }
990             AssocItemKind::Fn(sig, body) => {
991                 self.check_impl_item_provided(ii.span, body, "function", " { <body> }");
992                 self.check_fn_decl(&sig.decl);
993             }
994             AssocItemKind::TyAlias(bounds, body) => {
995                 self.check_impl_item_provided(ii.span, body, "type", " = <type>;");
996                 self.check_impl_assoc_type_no_bounds(bounds);
997             }
998             _ => {}
999         }
1000         visit::walk_impl_item(self, ii);
1001     }
1002
1003     fn visit_trait_item(&mut self, ti: &'a AssocItem) {
1004         self.invalid_visibility(&ti.vis, None);
1005         self.check_defaultness(ti.span, ti.defaultness);
1006
1007         if let AssocItemKind::Fn(sig, block) = &ti.kind {
1008             self.check_fn_decl(&sig.decl);
1009             self.check_trait_fn_not_async(ti.span, sig.header.asyncness.node);
1010             self.check_trait_fn_not_const(sig.header.constness);
1011             if block.is_none() {
1012                 Self::check_decl_no_pat(&sig.decl, |span, mut_ident| {
1013                     if mut_ident {
1014                         self.lint_buffer.buffer_lint(
1015                             PATTERNS_IN_FNS_WITHOUT_BODY,
1016                             ti.id,
1017                             span,
1018                             "patterns aren't allowed in methods without bodies",
1019                         );
1020                     } else {
1021                         struct_span_err!(
1022                             self.session,
1023                             span,
1024                             E0642,
1025                             "patterns aren't allowed in methods without bodies"
1026                         )
1027                         .emit();
1028                     }
1029                 });
1030             }
1031         }
1032
1033         visit::walk_trait_item(self, ti);
1034     }
1035
1036     fn visit_assoc_item(&mut self, item: &'a AssocItem) {
1037         if let AssocItemKind::Fn(sig, _) = &item.kind {
1038             self.check_c_varadic_type(&sig.decl);
1039         }
1040         visit::walk_assoc_item(self, item);
1041     }
1042 }
1043
1044 pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> bool {
1045     let mut validator = AstValidator {
1046         session,
1047         has_proc_macro_decls: false,
1048         outer_impl_trait: None,
1049         bound_context: None,
1050         is_impl_trait_banned: false,
1051         is_assoc_ty_bound_banned: false,
1052         lint_buffer: lints,
1053     };
1054     visit::walk_crate(&mut validator, krate);
1055
1056     validator.has_proc_macro_decls
1057 }