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