]> git.lizzy.rs Git - rust.git/blob - src/librustc_passes/ast_validation.rs
Rollup merge of #63055 - Mark-Simulacrum:save-analysis-clean-2, r=Xanewok
[rust.git] / src / librustc_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 std::mem;
10 use syntax::print::pprust;
11 use rustc::lint;
12 use rustc::lint::builtin::{BuiltinLintDiagnostics, NESTED_IMPL_TRAIT};
13 use rustc::session::Session;
14 use rustc_data_structures::fx::FxHashMap;
15 use syntax::ast::*;
16 use syntax::attr;
17 use syntax::ext::proc_macro::is_proc_macro_attr;
18 use syntax::feature_gate::is_builtin_attr;
19 use syntax::source_map::Spanned;
20 use syntax::symbol::{kw, sym};
21 use syntax::visit::{self, Visitor};
22 use syntax::{span_err, struct_span_err, walk_list};
23 use syntax_pos::{Span, MultiSpan};
24 use errors::{Applicability, FatalError};
25
26 #[derive(Copy, Clone, Debug)]
27 struct OuterImplTrait {
28     span: Span,
29
30     /// rust-lang/rust#57979: a bug in original implementation caused
31     /// us to fail sometimes to record an outer `impl Trait`.
32     /// Therefore, in order to reliably issue a warning (rather than
33     /// an error) in the *precise* places where we are newly injecting
34     /// the diagnostic, we have to distinguish between the places
35     /// where the outer `impl Trait` has always been recorded, versus
36     /// the places where it has only recently started being recorded.
37     only_recorded_since_pull_request_57730: bool,
38 }
39
40 impl OuterImplTrait {
41     /// This controls whether we should downgrade the nested impl
42     /// trait diagnostic to a warning rather than an error, based on
43     /// whether the outer impl trait had been improperly skipped in
44     /// earlier implementations of the analysis on the stable
45     /// compiler.
46     fn should_warn_instead_of_error(&self) -> bool {
47         self.only_recorded_since_pull_request_57730
48     }
49 }
50
51 struct AstValidator<'a> {
52     session: &'a Session,
53     has_proc_macro_decls: bool,
54
55     /// Used to ban nested `impl Trait`, e.g., `impl Into<impl Debug>`.
56     /// Nested `impl Trait` _is_ allowed in associated type position,
57     /// e.g., `impl Iterator<Item = impl Debug>`.
58     outer_impl_trait: Option<OuterImplTrait>,
59
60     /// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
61     /// or `Foo::Bar<impl Trait>`
62     is_impl_trait_banned: bool,
63
64     /// Used to ban associated type bounds (i.e., `Type<AssocType: Bounds>`) in
65     /// certain positions.
66     is_assoc_ty_bound_banned: bool,
67
68     /// rust-lang/rust#57979: the ban of nested `impl Trait` was buggy
69     /// until PRs #57730 and #57981 landed: it would jump directly to
70     /// walk_ty rather than visit_ty (or skip recurring entirely for
71     /// impl trait in projections), and thus miss some cases. We track
72     /// whether we should downgrade to a warning for short-term via
73     /// these booleans.
74     warning_period_57979_didnt_record_next_impl_trait: bool,
75     warning_period_57979_impl_trait_in_proj: bool,
76 }
77
78 impl<'a> AstValidator<'a> {
79     fn with_impl_trait_in_proj_warning<T>(&mut self, v: bool, f: impl FnOnce(&mut Self) -> T) -> T {
80         let old = mem::replace(&mut self.warning_period_57979_impl_trait_in_proj, v);
81         let ret = f(self);
82         self.warning_period_57979_impl_trait_in_proj = old;
83         ret
84     }
85
86     fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
87         let old = mem::replace(&mut self.is_impl_trait_banned, true);
88         f(self);
89         self.is_impl_trait_banned = old;
90     }
91
92     fn with_banned_assoc_ty_bound(&mut self, f: impl FnOnce(&mut Self)) {
93         let old = mem::replace(&mut self.is_assoc_ty_bound_banned, true);
94         f(self);
95         self.is_assoc_ty_bound_banned = old;
96     }
97
98     fn with_impl_trait(&mut self, outer: Option<OuterImplTrait>, f: impl FnOnce(&mut Self)) {
99         let old = mem::replace(&mut self.outer_impl_trait, outer);
100         f(self);
101         self.outer_impl_trait = old;
102     }
103
104     fn visit_assoc_ty_constraint_from_generic_args(&mut self, constraint: &'a AssocTyConstraint) {
105         match constraint.kind {
106             AssocTyConstraintKind::Equality { ref ty } => {
107                 // rust-lang/rust#57979: bug in old `visit_generic_args` called
108                 // `walk_ty` rather than `visit_ty`, skipping outer `impl Trait`
109                 // if it happened to occur at `ty`.
110                 if let TyKind::ImplTrait(..) = ty.node {
111                     self.warning_period_57979_didnt_record_next_impl_trait = true;
112                 }
113             }
114             AssocTyConstraintKind::Bound { .. } => {
115                 if self.is_assoc_ty_bound_banned {
116                     self.err_handler().span_err(constraint.span,
117                         "associated type bounds are not allowed within structs, enums, or unions"
118                     );
119                 }
120             }
121         }
122         self.visit_assoc_ty_constraint(constraint);
123     }
124
125     fn visit_ty_from_generic_args(&mut self, ty: &'a Ty) {
126         // rust-lang/rust#57979: bug in old `visit_generic_args` called
127         // `walk_ty` rather than `visit_ty`, skippping outer `impl Trait`
128         // if it happened to occur at `ty`.
129         if let TyKind::ImplTrait(..) = ty.node {
130             self.warning_period_57979_didnt_record_next_impl_trait = true;
131         }
132         self.visit_ty(ty);
133     }
134
135     fn outer_impl_trait(&mut self, span: Span) -> OuterImplTrait {
136         let only_recorded_since_pull_request_57730 =
137             self.warning_period_57979_didnt_record_next_impl_trait;
138
139         // (This flag is designed to be set to `true`, and then only
140         // reach the construction point for the outer impl trait once,
141         // so its safe and easiest to unconditionally reset it to
142         // false.)
143         self.warning_period_57979_didnt_record_next_impl_trait = false;
144
145         OuterImplTrait {
146             span, only_recorded_since_pull_request_57730,
147         }
148     }
149
150     // Mirrors `visit::walk_ty`, but tracks relevant state.
151     fn walk_ty(&mut self, t: &'a Ty) {
152         match t.node {
153             TyKind::ImplTrait(..) => {
154                 let outer_impl_trait = self.outer_impl_trait(t.span);
155                 self.with_impl_trait(Some(outer_impl_trait), |this| visit::walk_ty(this, t))
156             }
157             TyKind::Path(ref qself, ref path) => {
158                 // We allow these:
159                 //  - `Option<impl Trait>`
160                 //  - `option::Option<impl Trait>`
161                 //  - `option::Option<T>::Foo<impl Trait>
162                 //
163                 // But not these:
164                 //  - `<impl Trait>::Foo`
165                 //  - `option::Option<impl Trait>::Foo`.
166                 //
167                 // To implement this, we disallow `impl Trait` from `qself`
168                 // (for cases like `<impl Trait>::Foo>`)
169                 // but we allow `impl Trait` in `GenericArgs`
170                 // iff there are no more PathSegments.
171                 if let Some(ref qself) = *qself {
172                     // `impl Trait` in `qself` is always illegal
173                     self.with_banned_impl_trait(|this| this.visit_ty(&qself.ty));
174                 }
175
176                 // Note that there should be a call to visit_path here,
177                 // so if any logic is added to process `Path`s a call to it should be
178                 // added both in visit_path and here. This code mirrors visit::walk_path.
179                 for (i, segment) in path.segments.iter().enumerate() {
180                     // Allow `impl Trait` iff we're on the final path segment
181                     if i == path.segments.len() - 1 {
182                         self.visit_path_segment(path.span, segment);
183                     } else {
184                         self.with_banned_impl_trait(|this| {
185                             this.visit_path_segment(path.span, segment)
186                         });
187                     }
188                 }
189             }
190             _ => visit::walk_ty(self, t),
191         }
192     }
193
194     fn err_handler(&self) -> &errors::Handler {
195         &self.session.diagnostic()
196     }
197
198     fn check_lifetime(&self, ident: Ident) {
199         let valid_names = [kw::UnderscoreLifetime,
200                            kw::StaticLifetime,
201                            kw::Invalid];
202         if !valid_names.contains(&ident.name) && ident.without_first_quote().is_reserved() {
203             self.err_handler().span_err(ident.span, "lifetimes cannot use keyword names");
204         }
205     }
206
207     fn check_label(&self, ident: Ident) {
208         if ident.without_first_quote().is_reserved() {
209             self.err_handler()
210                 .span_err(ident.span, &format!("invalid label name `{}`", ident.name));
211         }
212     }
213
214     fn invalid_visibility(&self, vis: &Visibility, note: Option<&str>) {
215         if let VisibilityKind::Inherited = vis.node {
216             return
217         }
218
219         let mut err = struct_span_err!(self.session,
220                                         vis.span,
221                                         E0449,
222                                         "unnecessary visibility qualifier");
223         if vis.node.is_pub() {
224             err.span_label(vis.span, "`pub` not permitted here because it's implied");
225         }
226         if let Some(note) = note {
227             err.note(note);
228         }
229         err.emit();
230     }
231
232     fn check_decl_no_pat<ReportFn: Fn(Span, bool)>(&self, decl: &FnDecl, report_err: ReportFn) {
233         for arg in &decl.inputs {
234             match arg.pat.node {
235                 PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), _, None) |
236                 PatKind::Wild => {}
237                 PatKind::Ident(BindingMode::ByValue(Mutability::Mutable), _, None) =>
238                     report_err(arg.pat.span, true),
239                 _ => report_err(arg.pat.span, false),
240             }
241         }
242     }
243
244     fn check_trait_fn_not_async(&self, span: Span, asyncness: IsAsync) {
245         if asyncness.is_async() {
246             struct_span_err!(self.session, span, E0706,
247                              "trait fns cannot be declared `async`").emit()
248         }
249     }
250
251     fn check_trait_fn_not_const(&self, constness: Spanned<Constness>) {
252         if constness.node == Constness::Const {
253             struct_span_err!(self.session, constness.span, E0379,
254                              "trait fns cannot be declared const")
255                 .span_label(constness.span, "trait fns cannot be const")
256                 .emit();
257         }
258     }
259
260     fn no_questions_in_bounds(&self, bounds: &GenericBounds, where_: &str, is_trait: bool) {
261         for bound in bounds {
262             if let GenericBound::Trait(ref poly, TraitBoundModifier::Maybe) = *bound {
263                 let mut err = self.err_handler().struct_span_err(poly.span,
264                     &format!("`?Trait` is not permitted in {}", where_));
265                 if is_trait {
266                     err.note(&format!("traits are `?{}` by default", poly.trait_ref.path));
267                 }
268                 err.emit();
269             }
270         }
271     }
272
273     /// Matches `'-' lit | lit (cf. parser::Parser::parse_literal_maybe_minus)`,
274     /// or paths for ranges.
275     //
276     // FIXME: do we want to allow `expr -> pattern` conversion to create path expressions?
277     // That means making this work:
278     //
279     // ```rust,ignore (FIXME)
280     // struct S;
281     // macro_rules! m {
282     //     ($a:expr) => {
283     //         let $a = S;
284     //     }
285     // }
286     // m!(S);
287     // ```
288     fn check_expr_within_pat(&self, expr: &Expr, allow_paths: bool) {
289         match expr.node {
290             ExprKind::Lit(..) | ExprKind::Err => {}
291             ExprKind::Path(..) if allow_paths => {}
292             ExprKind::Unary(UnOp::Neg, ref inner)
293                 if match inner.node { ExprKind::Lit(_) => true, _ => false } => {}
294             _ => self.err_handler().span_err(expr.span, "arbitrary expressions aren't allowed \
295                                                          in patterns")
296         }
297     }
298
299     fn check_late_bound_lifetime_defs(&self, params: &[GenericParam]) {
300         // Check only lifetime parameters are present and that the lifetime
301         // parameters that are present have no bounds.
302         let non_lt_param_spans: Vec<_> = params.iter().filter_map(|param| match param.kind {
303             GenericParamKind::Lifetime { .. } => {
304                 if !param.bounds.is_empty() {
305                     let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
306                     self.err_handler()
307                         .span_err(spans, "lifetime bounds cannot be used in this context");
308                 }
309                 None
310             }
311             _ => Some(param.ident.span),
312         }).collect();
313         if !non_lt_param_spans.is_empty() {
314             self.err_handler().span_err(non_lt_param_spans,
315                 "only lifetime parameters can be used in this context");
316         }
317     }
318
319     fn check_fn_decl(&self, fn_decl: &FnDecl) {
320         fn_decl
321             .inputs
322             .iter()
323             .flat_map(|i| i.attrs.as_ref())
324             .filter(|attr| {
325                 let arr = [sym::allow, sym::cfg, sym::cfg_attr, sym::deny, sym::forbid, sym::warn];
326                 !arr.contains(&attr.name_or_empty()) && is_builtin_attr(attr)
327             })
328             .for_each(|attr| if attr.is_sugared_doc {
329                 let mut err = self.err_handler().struct_span_err(
330                     attr.span,
331                     "documentation comments cannot be applied to function parameters"
332                 );
333                 err.span_label(attr.span, "doc comments are not allowed here");
334                 err.emit();
335             }
336             else {
337                 self.err_handler().span_err(attr.span, "allow, cfg, cfg_attr, deny, \
338                 forbid, and warn are the only allowed built-in attributes in function parameters")
339             });
340     }
341 }
342
343 enum GenericPosition {
344     Param,
345     Arg,
346 }
347
348 fn validate_generics_order<'a>(
349     sess: &Session,
350     handler: &errors::Handler,
351     generics: impl Iterator<
352         Item = (
353             ParamKindOrd,
354             Option<&'a [GenericBound]>,
355             Span,
356             Option<String>
357         ),
358     >,
359     pos: GenericPosition,
360     span: Span,
361 ) {
362     let mut max_param: Option<ParamKindOrd> = None;
363     let mut out_of_order = FxHashMap::default();
364     let mut param_idents = vec![];
365     let mut found_type = false;
366     let mut found_const = false;
367
368     for (kind, bounds, span, ident) in generics {
369         if let Some(ident) = ident {
370             param_idents.push((kind, bounds, param_idents.len(), ident));
371         }
372         let max_param = &mut max_param;
373         match max_param {
374             Some(max_param) if *max_param > kind => {
375                 let entry = out_of_order.entry(kind).or_insert((*max_param, vec![]));
376                 entry.1.push(span);
377             }
378             Some(_) | None => *max_param = Some(kind),
379         };
380         match kind {
381             ParamKindOrd::Type => found_type = true,
382             ParamKindOrd::Const => found_const = true,
383             _ => {}
384         }
385     }
386
387     let mut ordered_params = "<".to_string();
388     if !out_of_order.is_empty() {
389         param_idents.sort_by_key(|&(po, _, i, _)| (po, i));
390         let mut first = true;
391         for (_, bounds, _, ident) in param_idents {
392             if !first {
393                 ordered_params += ", ";
394             }
395             ordered_params += &ident;
396             if let Some(bounds) = bounds {
397                 if !bounds.is_empty() {
398                     ordered_params += ": ";
399                     ordered_params += &pprust::bounds_to_string(&bounds);
400                 }
401             }
402             first = false;
403         }
404     }
405     ordered_params += ">";
406
407     let pos_str = match pos {
408         GenericPosition::Param => "parameter",
409         GenericPosition::Arg => "argument",
410     };
411
412     for (param_ord, (max_param, spans)) in &out_of_order {
413         let mut err = handler.struct_span_err(spans.clone(),
414             &format!(
415                 "{} {pos}s must be declared prior to {} {pos}s",
416                 param_ord,
417                 max_param,
418                 pos = pos_str,
419             ));
420         if let GenericPosition::Param = pos {
421             err.span_suggestion(
422                 span,
423                 &format!(
424                     "reorder the {}s: lifetimes, then types{}",
425                     pos_str,
426                     if sess.features_untracked().const_generics { ", then consts" } else { "" },
427                 ),
428                 ordered_params.clone(),
429                 Applicability::MachineApplicable,
430             );
431         }
432         err.emit();
433     }
434
435     // FIXME(const_generics): we shouldn't have to abort here at all, but we currently get ICEs
436     // if we don't. Const parameters and type parameters can currently conflict if they
437     // are out-of-order.
438     if !out_of_order.is_empty() && found_type && found_const {
439         FatalError.raise();
440     }
441 }
442
443 impl<'a> Visitor<'a> for AstValidator<'a> {
444     fn visit_expr(&mut self, expr: &'a Expr) {
445         match &expr.node {
446             ExprKind::Closure(_, _, _, fn_decl, _, _) => {
447                 self.check_fn_decl(fn_decl);
448             }
449             ExprKind::InlineAsm(..) if !self.session.target.target.options.allow_asm => {
450                 span_err!(self.session, expr.span, E0472, "asm! is unsupported on this target");
451             }
452             _ => {}
453         }
454
455         visit::walk_expr(self, expr);
456     }
457
458     fn visit_ty(&mut self, ty: &'a Ty) {
459         match ty.node {
460             TyKind::BareFn(ref bfty) => {
461                 self.check_fn_decl(&bfty.decl);
462                 self.check_decl_no_pat(&bfty.decl, |span, _| {
463                     struct_span_err!(self.session, span, E0561,
464                                      "patterns aren't allowed in function pointer types").emit();
465                 });
466                 self.check_late_bound_lifetime_defs(&bfty.generic_params);
467             }
468             TyKind::TraitObject(ref bounds, ..) => {
469                 let mut any_lifetime_bounds = false;
470                 for bound in bounds {
471                     if let GenericBound::Outlives(ref lifetime) = *bound {
472                         if any_lifetime_bounds {
473                             span_err!(self.session, lifetime.ident.span, E0226,
474                                       "only a single explicit lifetime bound is permitted");
475                             break;
476                         }
477                         any_lifetime_bounds = true;
478                     }
479                 }
480                 self.no_questions_in_bounds(bounds, "trait object types", false);
481             }
482             TyKind::ImplTrait(_, ref bounds) => {
483                 if self.is_impl_trait_banned {
484                     if self.warning_period_57979_impl_trait_in_proj {
485                         self.session.buffer_lint(
486                             NESTED_IMPL_TRAIT, ty.id, ty.span,
487                             "`impl Trait` is not allowed in path parameters");
488                     } else {
489                         struct_span_err!(self.session, ty.span, E0667,
490                             "`impl Trait` is not allowed in path parameters").emit();
491                     }
492                 }
493
494                 if let Some(outer_impl_trait) = self.outer_impl_trait {
495                     if outer_impl_trait.should_warn_instead_of_error() {
496                         self.session.buffer_lint_with_diagnostic(
497                             NESTED_IMPL_TRAIT, ty.id, ty.span,
498                             "nested `impl Trait` is not allowed",
499                             BuiltinLintDiagnostics::NestedImplTrait {
500                                 outer_impl_trait_span: outer_impl_trait.span,
501                                 inner_impl_trait_span: ty.span,
502                             });
503                     } else {
504                         struct_span_err!(self.session, ty.span, E0666,
505                             "nested `impl Trait` is not allowed")
506                             .span_label(outer_impl_trait.span, "outer `impl Trait`")
507                             .span_label(ty.span, "nested `impl Trait` here")
508                             .emit();
509                     }
510                 }
511
512                 if !bounds.iter()
513                           .any(|b| if let GenericBound::Trait(..) = *b { true } else { false }) {
514                     self.err_handler().span_err(ty.span, "at least one trait must be specified");
515                 }
516
517                 self.with_impl_trait_in_proj_warning(true, |this| this.walk_ty(ty));
518                 return;
519             }
520             _ => {}
521         }
522
523         self.walk_ty(ty)
524     }
525
526     fn visit_label(&mut self, label: &'a Label) {
527         self.check_label(label.ident);
528         visit::walk_label(self, label);
529     }
530
531     fn visit_lifetime(&mut self, lifetime: &'a Lifetime) {
532         self.check_lifetime(lifetime.ident);
533         visit::walk_lifetime(self, lifetime);
534     }
535
536     fn visit_item(&mut self, item: &'a Item) {
537         if item.attrs.iter().any(|attr| is_proc_macro_attr(attr)  ) {
538             self.has_proc_macro_decls = true;
539         }
540
541         match item.node {
542             ItemKind::Impl(unsafety, polarity, _, _, Some(..), ref ty, ref impl_items) => {
543                 self.invalid_visibility(&item.vis, None);
544                 if let TyKind::Err = ty.node {
545                     self.err_handler()
546                         .struct_span_err(item.span, "`impl Trait for .. {}` is an obsolete syntax")
547                         .help("use `auto trait Trait {}` instead").emit();
548                 }
549                 if unsafety == Unsafety::Unsafe && polarity == ImplPolarity::Negative {
550                     span_err!(self.session, item.span, E0198, "negative impls cannot be unsafe");
551                 }
552                 for impl_item in impl_items {
553                     self.invalid_visibility(&impl_item.vis, None);
554                     if let ImplItemKind::Method(ref sig, _) = impl_item.node {
555                         self.check_trait_fn_not_const(sig.header.constness);
556                         self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness.node);
557                     }
558                 }
559             }
560             ItemKind::Impl(unsafety, polarity, defaultness, _, None, _, _) => {
561                 self.invalid_visibility(&item.vis,
562                                         Some("place qualifiers on individual impl items instead"));
563                 if unsafety == Unsafety::Unsafe {
564                     span_err!(self.session, item.span, E0197, "inherent impls cannot be unsafe");
565                 }
566                 if polarity == ImplPolarity::Negative {
567                     self.err_handler().span_err(item.span, "inherent impls cannot be negative");
568                 }
569                 if defaultness == Defaultness::Default {
570                     self.err_handler()
571                         .struct_span_err(item.span, "inherent impls cannot be default")
572                         .note("only trait implementations may be annotated with default").emit();
573                 }
574             }
575             ItemKind::Fn(ref decl, ref header, ref generics, _) => {
576                 self.visit_fn_header(header);
577                 self.check_fn_decl(decl);
578                 // We currently do not permit const generics in `const fn`, as
579                 // this is tantamount to allowing compile-time dependent typing.
580                 if header.constness.node == Constness::Const {
581                     // Look for const generics and error if we find any.
582                     for param in &generics.params {
583                         match param.kind {
584                             GenericParamKind::Const { .. } => {
585                                 self.err_handler()
586                                     .struct_span_err(
587                                         item.span,
588                                         "const parameters are not permitted in `const fn`",
589                                     )
590                                     .emit();
591                             }
592                             _ => {}
593                         }
594                     }
595                 }
596             }
597             ItemKind::ForeignMod(..) => {
598                 self.invalid_visibility(
599                     &item.vis,
600                     Some("place qualifiers on individual foreign items instead"),
601                 );
602             }
603             ItemKind::Enum(ref def, _) => {
604                 for variant in &def.variants {
605                     for field in variant.node.data.fields() {
606                         self.invalid_visibility(&field.vis, None);
607                     }
608                 }
609             }
610             ItemKind::Trait(is_auto, _, ref generics, ref bounds, ref trait_items) => {
611                 if is_auto == IsAuto::Yes {
612                     // Auto traits cannot have generics, super traits nor contain items.
613                     if !generics.params.is_empty() {
614                         struct_span_err!(self.session, item.span, E0567,
615                             "auto traits cannot have generic parameters"
616                         ).emit();
617                     }
618                     if !bounds.is_empty() {
619                         struct_span_err!(self.session, item.span, E0568,
620                             "auto traits cannot have super traits"
621                         ).emit();
622                     }
623                     if !trait_items.is_empty() {
624                         struct_span_err!(self.session, item.span, E0380,
625                             "auto traits cannot have methods or associated items"
626                         ).emit();
627                     }
628                 }
629                 self.no_questions_in_bounds(bounds, "supertraits", true);
630                 for trait_item in trait_items {
631                     if let TraitItemKind::Method(ref sig, ref block) = trait_item.node {
632                         self.check_fn_decl(&sig.decl);
633                         self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness.node);
634                         self.check_trait_fn_not_const(sig.header.constness);
635                         if block.is_none() {
636                             self.check_decl_no_pat(&sig.decl, |span, mut_ident| {
637                                 if mut_ident {
638                                     self.session.buffer_lint(
639                                         lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY,
640                                         trait_item.id, span,
641                                         "patterns aren't allowed in methods without bodies");
642                                 } else {
643                                     struct_span_err!(self.session, span, E0642,
644                                         "patterns aren't allowed in methods without bodies").emit();
645                                 }
646                             });
647                         }
648                     }
649                 }
650             }
651             ItemKind::Mod(_) => {
652                 // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
653                 attr::first_attr_value_str_by_name(&item.attrs, sym::path);
654                 if attr::contains_name(&item.attrs, sym::warn_directory_ownership) {
655                     let lint = lint::builtin::LEGACY_DIRECTORY_OWNERSHIP;
656                     let msg = "cannot declare a new module at this location";
657                     self.session.buffer_lint(lint, item.id, item.span, msg);
658                 }
659             }
660             ItemKind::Union(ref vdata, _) => {
661                 if let VariantData::Tuple(..) | VariantData::Unit(..) = vdata {
662                     self.err_handler().span_err(item.span,
663                                                 "tuple and unit unions are not permitted");
664                 }
665                 if vdata.fields().is_empty() {
666                     self.err_handler().span_err(item.span,
667                                                 "unions cannot have zero fields");
668                 }
669             }
670             ItemKind::Existential(ref bounds, _) => {
671                 if !bounds.iter()
672                           .any(|b| if let GenericBound::Trait(..) = *b { true } else { false }) {
673                     let msp = MultiSpan::from_spans(bounds.iter()
674                         .map(|bound| bound.span()).collect());
675                     self.err_handler().span_err(msp, "at least one trait must be specified");
676                 }
677             }
678             _ => {}
679         }
680
681         visit::walk_item(self, item)
682     }
683
684     fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
685         match fi.node {
686             ForeignItemKind::Fn(ref decl, _) => {
687                 self.check_fn_decl(decl);
688                 self.check_decl_no_pat(decl, |span, _| {
689                     struct_span_err!(self.session, span, E0130,
690                                      "patterns aren't allowed in foreign function declarations")
691                         .span_label(span, "pattern not allowed in foreign function").emit();
692                 });
693             }
694             ForeignItemKind::Static(..) | ForeignItemKind::Ty | ForeignItemKind::Macro(..) => {}
695         }
696
697         visit::walk_foreign_item(self, fi)
698     }
699
700     // Mirrors `visit::walk_generic_args`, but tracks relevant state.
701     fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) {
702         match *generic_args {
703             GenericArgs::AngleBracketed(ref data) => {
704                 walk_list!(self, visit_generic_arg, &data.args);
705                 validate_generics_order(
706                     self.session,
707                     self.err_handler(),
708                     data.args.iter().map(|arg| {
709                         (match arg {
710                             GenericArg::Lifetime(..) => ParamKindOrd::Lifetime,
711                             GenericArg::Type(..) => ParamKindOrd::Type,
712                             GenericArg::Const(..) => ParamKindOrd::Const,
713                         }, None, arg.span(), None)
714                     }),
715                     GenericPosition::Arg,
716                     generic_args.span(),
717                 );
718
719                 // Type bindings such as `Item = impl Debug` in `Iterator<Item = Debug>`
720                 // are allowed to contain nested `impl Trait`.
721                 self.with_impl_trait(None, |this| {
722                     walk_list!(this, visit_assoc_ty_constraint_from_generic_args,
723                         &data.constraints);
724                 });
725             }
726             GenericArgs::Parenthesized(ref data) => {
727                 walk_list!(self, visit_ty, &data.inputs);
728                 if let Some(ref type_) = data.output {
729                     // `-> Foo` syntax is essentially an associated type binding,
730                     // so it is also allowed to contain nested `impl Trait`.
731                     self.with_impl_trait(None, |this| this.visit_ty_from_generic_args(type_));
732                 }
733             }
734         }
735     }
736
737     fn visit_generics(&mut self, generics: &'a Generics) {
738         let mut prev_ty_default = None;
739         for param in &generics.params {
740             if let GenericParamKind::Type { ref default, .. } = param.kind {
741                 if default.is_some() {
742                     prev_ty_default = Some(param.ident.span);
743                 } else if let Some(span) = prev_ty_default {
744                     self.err_handler()
745                         .span_err(span, "type parameters with a default must be trailing");
746                     break;
747                 }
748             }
749         }
750
751         validate_generics_order(
752             self.session,
753             self.err_handler(),
754             generics.params.iter().map(|param| {
755                 let ident = Some(param.ident.to_string());
756                 let (kind, ident) = match &param.kind {
757                     GenericParamKind::Lifetime { .. } => (ParamKindOrd::Lifetime, ident),
758                     GenericParamKind::Type { .. } => (ParamKindOrd::Type, ident),
759                     GenericParamKind::Const { ref ty } => {
760                         let ty = pprust::ty_to_string(ty);
761                         (ParamKindOrd::Const, Some(format!("const {}: {}", param.ident, ty)))
762                     }
763                 };
764                 (kind, Some(&*param.bounds), param.ident.span, ident)
765             }),
766             GenericPosition::Param,
767             generics.span,
768         );
769
770         for predicate in &generics.where_clause.predicates {
771             if let WherePredicate::EqPredicate(ref predicate) = *predicate {
772                 self.err_handler()
773                     .span_err(predicate.span, "equality constraints are not yet \
774                                                supported in where clauses (see #20041)");
775             }
776         }
777
778         visit::walk_generics(self, generics)
779     }
780
781     fn visit_generic_param(&mut self, param: &'a GenericParam) {
782         if let GenericParamKind::Lifetime { .. } = param.kind {
783             self.check_lifetime(param.ident);
784         }
785         visit::walk_generic_param(self, param);
786     }
787
788     fn visit_pat(&mut self, pat: &'a Pat) {
789         match pat.node {
790             PatKind::Lit(ref expr) => {
791                 self.check_expr_within_pat(expr, false);
792             }
793             PatKind::Range(ref start, ref end, _) => {
794                 self.check_expr_within_pat(start, true);
795                 self.check_expr_within_pat(end, true);
796             }
797             _ => {}
798         }
799
800         visit::walk_pat(self, pat)
801     }
802
803     fn visit_where_predicate(&mut self, p: &'a WherePredicate) {
804         if let &WherePredicate::BoundPredicate(ref bound_predicate) = p {
805             // A type binding, eg `for<'c> Foo: Send+Clone+'c`
806             self.check_late_bound_lifetime_defs(&bound_predicate.bound_generic_params);
807         }
808         visit::walk_where_predicate(self, p);
809     }
810
811     fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef, m: &'a TraitBoundModifier) {
812         self.check_late_bound_lifetime_defs(&t.bound_generic_params);
813         visit::walk_poly_trait_ref(self, t, m);
814     }
815
816     fn visit_variant_data(&mut self, s: &'a VariantData, _: Ident,
817                           _: &'a Generics, _: NodeId, _: Span) {
818         self.with_banned_assoc_ty_bound(|this| visit::walk_struct_def(this, s))
819     }
820
821     fn visit_enum_def(&mut self, enum_definition: &'a EnumDef,
822                       generics: &'a Generics, item_id: NodeId, _: Span) {
823         self.with_banned_assoc_ty_bound(
824             |this| visit::walk_enum_def(this, enum_definition, generics, item_id))
825     }
826
827     fn visit_mac(&mut self, mac: &Spanned<Mac_>) {
828         // when a new macro kind is added but the author forgets to set it up for expansion
829         // because that's the only part that won't cause a compiler error
830         self.session.diagnostic()
831             .span_bug(mac.span, "macro invocation missed in expansion; did you forget to override \
832                                  the relevant `fold_*()` method in `PlaceholderExpander`?");
833     }
834
835     fn visit_impl_item(&mut self, ii: &'a ImplItem) {
836         match ii.node {
837             ImplItemKind::Method(ref sig, _) => {
838                 self.check_fn_decl(&sig.decl);
839             }
840             _ => {}
841         }
842         visit::walk_impl_item(self, ii);
843     }
844 }
845
846 pub fn check_crate(session: &Session, krate: &Crate) -> bool {
847     let mut validator = AstValidator {
848         session,
849         has_proc_macro_decls: false,
850         outer_impl_trait: None,
851         is_impl_trait_banned: false,
852         is_assoc_ty_bound_banned: false,
853         warning_period_57979_didnt_record_next_impl_trait: false,
854         warning_period_57979_impl_trait_in_proj: false,
855     };
856     visit::walk_crate(&mut validator, krate);
857
858     validator.has_proc_macro_decls
859 }