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