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