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