]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_ast_passes/src/ast_validation.rs
Rollup merge of #104952 - jyn514:setup, r=Mark-Simulacrum
[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(qself, 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(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(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(bounds, ..) => {
760                 let mut any_lifetime_bounds = false;
761                 for bound in bounds {
762                     if let GenericBound::Outlives(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(_, 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 { .. } => (ParamKindOrd::TypeOrConst, ident.to_string()),
846             GenericParamKind::Const { ty, .. } => {
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_attr(&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(_, lhs, 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                 generics,
1015                 of_trait: Some(t),
1016                 self_ty,
1017                 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                     {
1032                         struct_span_err!(
1033                             this.session,
1034                             sp.to(t.path.span),
1035                             E0198,
1036                             "negative impls cannot be unsafe"
1037                         )
1038                         .span_label(sp, "negative because of this")
1039                         .span_label(span, "unsafe because of this")
1040                         .emit();
1041                     }
1042
1043                     this.visit_vis(&item.vis);
1044                     this.visit_ident(item.ident);
1045                     if let Const::Yes(_) = constness {
1046                         this.with_tilde_const_allowed(|this| this.visit_generics(generics));
1047                     } else {
1048                         this.visit_generics(generics);
1049                     }
1050                     this.visit_trait_ref(t);
1051                     this.visit_ty(self_ty);
1052
1053                     walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl);
1054                 });
1055                 walk_list!(self, visit_attribute, &item.attrs);
1056                 return; // Avoid visiting again.
1057             }
1058             ItemKind::Impl(box Impl {
1059                 unsafety,
1060                 polarity,
1061                 defaultness,
1062                 constness,
1063                 generics: _,
1064                 of_trait: None,
1065                 self_ty,
1066                 items: _,
1067             }) => {
1068                 let error = |annotation_span, annotation| {
1069                     let mut err = self.err_handler().struct_span_err(
1070                         self_ty.span,
1071                         &format!("inherent impls cannot be {}", annotation),
1072                     );
1073                     err.span_label(annotation_span, &format!("{} because of this", annotation));
1074                     err.span_label(self_ty.span, "inherent impl for this type");
1075                     err
1076                 };
1077
1078                 self.invalid_visibility(
1079                     &item.vis,
1080                     Some(InvalidVisibilityNote::IndividualImplItems),
1081                 );
1082                 if let &Unsafe::Yes(span) = unsafety {
1083                     error(span, "unsafe").code(error_code!(E0197)).emit();
1084                 }
1085                 if let &ImplPolarity::Negative(span) = polarity {
1086                     error(span, "negative").emit();
1087                 }
1088                 if let &Defaultness::Default(def_span) = defaultness {
1089                     error(def_span, "`default`")
1090                         .note("only trait implementations may be annotated with `default`")
1091                         .emit();
1092                 }
1093                 if let &Const::Yes(span) = constness {
1094                     error(span, "`const`")
1095                         .note("only trait implementations may be annotated with `const`")
1096                         .emit();
1097                 }
1098             }
1099             ItemKind::Fn(box Fn { defaultness, sig, generics, body }) => {
1100                 self.check_defaultness(item.span, *defaultness);
1101
1102                 if body.is_none() {
1103                     self.session.emit_err(FnWithoutBody {
1104                         span: item.span,
1105                         replace_span: self.ending_semi_or_hi(item.span),
1106                         extern_block_suggestion: match sig.header.ext {
1107                             Extern::None => None,
1108                             Extern::Implicit(start_span) => Some(ExternBlockSuggestion {
1109                                 start_span,
1110                                 end_span: item.span.shrink_to_hi(),
1111                                 abi: None,
1112                             }),
1113                             Extern::Explicit(abi, start_span) => Some(ExternBlockSuggestion {
1114                                 start_span,
1115                                 end_span: item.span.shrink_to_hi(),
1116                                 abi: Some(abi.symbol_unescaped),
1117                             }),
1118                         },
1119                     });
1120                 }
1121
1122                 self.visit_vis(&item.vis);
1123                 self.visit_ident(item.ident);
1124                 let kind =
1125                     FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, generics, body.as_deref());
1126                 self.visit_fn(kind, item.span, item.id);
1127                 walk_list!(self, visit_attribute, &item.attrs);
1128                 return; // Avoid visiting again.
1129             }
1130             ItemKind::ForeignMod(ForeignMod { abi, unsafety, .. }) => {
1131                 let old_item = mem::replace(&mut self.extern_mod, Some(item));
1132                 self.invalid_visibility(
1133                     &item.vis,
1134                     Some(InvalidVisibilityNote::IndividualForeignItems),
1135                 );
1136                 if let &Unsafe::Yes(span) = unsafety {
1137                     self.err_handler().span_err(span, "extern block cannot be declared unsafe");
1138                 }
1139                 if abi.is_none() {
1140                     self.maybe_lint_missing_abi(item.span, item.id);
1141                 }
1142                 visit::walk_item(self, item);
1143                 self.extern_mod = old_item;
1144                 return; // Avoid visiting again.
1145             }
1146             ItemKind::Enum(def, _) => {
1147                 for variant in &def.variants {
1148                     self.invalid_visibility(&variant.vis, None);
1149                     for field in variant.data.fields() {
1150                         self.invalid_visibility(&field.vis, None);
1151                     }
1152                 }
1153             }
1154             ItemKind::Trait(box Trait { is_auto, generics, bounds, items, .. }) => {
1155                 if *is_auto == IsAuto::Yes {
1156                     // Auto traits cannot have generics, super traits nor contain items.
1157                     self.deny_generic_params(generics, item.ident.span);
1158                     self.deny_super_traits(bounds, item.ident.span);
1159                     self.deny_where_clause(&generics.where_clause, item.ident.span);
1160                     self.deny_items(items, item.ident.span);
1161                 }
1162
1163                 // Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
1164                 // context for the supertraits.
1165                 self.visit_vis(&item.vis);
1166                 self.visit_ident(item.ident);
1167                 self.visit_generics(generics);
1168                 self.with_tilde_const_allowed(|this| {
1169                     walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
1170                 });
1171                 walk_list!(self, visit_assoc_item, items, AssocCtxt::Trait);
1172                 walk_list!(self, visit_attribute, &item.attrs);
1173                 return; // Avoid visiting again
1174             }
1175             ItemKind::Mod(unsafety, mod_kind) => {
1176                 if let &Unsafe::Yes(span) = unsafety {
1177                     self.err_handler().span_err(span, "module cannot be declared unsafe");
1178                 }
1179                 // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
1180                 if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _))
1181                     && !self.session.contains_name(&item.attrs, sym::path)
1182                 {
1183                     self.check_mod_file_item_asciionly(item.ident);
1184                 }
1185             }
1186             ItemKind::Union(vdata, ..) => {
1187                 if vdata.fields().is_empty() {
1188                     self.err_handler().span_err(item.span, "unions cannot have zero fields");
1189                 }
1190             }
1191             ItemKind::Const(def, .., None) => {
1192                 self.check_defaultness(item.span, *def);
1193                 self.session.emit_err(ConstWithoutBody {
1194                     span: item.span,
1195                     replace_span: self.ending_semi_or_hi(item.span),
1196                 });
1197             }
1198             ItemKind::Static(.., None) => {
1199                 self.session.emit_err(StaticWithoutBody {
1200                     span: item.span,
1201                     replace_span: self.ending_semi_or_hi(item.span),
1202                 });
1203             }
1204             ItemKind::TyAlias(box TyAlias { defaultness, where_clauses, bounds, ty, .. }) => {
1205                 self.check_defaultness(item.span, *defaultness);
1206                 if ty.is_none() {
1207                     self.session.emit_err(TyAliasWithoutBody {
1208                         span: item.span,
1209                         replace_span: self.ending_semi_or_hi(item.span),
1210                     });
1211                 }
1212                 self.check_type_no_bounds(bounds, "this context");
1213                 if where_clauses.1.0 {
1214                     let mut err = self.err_handler().struct_span_err(
1215                         where_clauses.1.1,
1216                         "where clauses are not allowed after the type for type aliases",
1217                     );
1218                     err.note(
1219                         "see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information",
1220                     );
1221                     err.emit();
1222                 }
1223             }
1224             _ => {}
1225         }
1226
1227         visit::walk_item(self, item);
1228     }
1229
1230     fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
1231         match &fi.kind {
1232             ForeignItemKind::Fn(box Fn { defaultness, sig, body, .. }) => {
1233                 self.check_defaultness(fi.span, *defaultness);
1234                 self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
1235                 self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header);
1236                 self.check_foreign_item_ascii_only(fi.ident);
1237             }
1238             ForeignItemKind::TyAlias(box TyAlias {
1239                 defaultness,
1240                 generics,
1241                 where_clauses,
1242                 bounds,
1243                 ty,
1244                 ..
1245             }) => {
1246                 self.check_defaultness(fi.span, *defaultness);
1247                 self.check_foreign_kind_bodyless(fi.ident, "type", ty.as_ref().map(|b| b.span));
1248                 self.check_type_no_bounds(bounds, "`extern` blocks");
1249                 self.check_foreign_ty_genericless(generics, where_clauses.0.1);
1250                 self.check_foreign_item_ascii_only(fi.ident);
1251             }
1252             ForeignItemKind::Static(_, _, body) => {
1253                 self.check_foreign_kind_bodyless(fi.ident, "static", body.as_ref().map(|b| b.span));
1254                 self.check_foreign_item_ascii_only(fi.ident);
1255             }
1256             ForeignItemKind::MacCall(..) => {}
1257         }
1258
1259         visit::walk_foreign_item(self, fi)
1260     }
1261
1262     // Mirrors `visit::walk_generic_args`, but tracks relevant state.
1263     fn visit_generic_args(&mut self, generic_args: &'a GenericArgs) {
1264         match generic_args {
1265             GenericArgs::AngleBracketed(data) => {
1266                 self.check_generic_args_before_constraints(data);
1267
1268                 for arg in &data.args {
1269                     match arg {
1270                         AngleBracketedArg::Arg(arg) => self.visit_generic_arg(arg),
1271                         // Type bindings such as `Item = impl Debug` in `Iterator<Item = Debug>`
1272                         // are allowed to contain nested `impl Trait`.
1273                         AngleBracketedArg::Constraint(constraint) => {
1274                             self.with_impl_trait(None, |this| {
1275                                 this.visit_assoc_constraint_from_generic_args(constraint);
1276                             });
1277                         }
1278                     }
1279                 }
1280             }
1281             GenericArgs::Parenthesized(data) => {
1282                 walk_list!(self, visit_ty, &data.inputs);
1283                 if let FnRetTy::Ty(ty) = &data.output {
1284                     // `-> Foo` syntax is essentially an associated type binding,
1285                     // so it is also allowed to contain nested `impl Trait`.
1286                     self.with_impl_trait(None, |this| this.visit_ty(ty));
1287                 }
1288             }
1289         }
1290     }
1291
1292     fn visit_generics(&mut self, generics: &'a Generics) {
1293         let mut prev_param_default = None;
1294         for param in &generics.params {
1295             match param.kind {
1296                 GenericParamKind::Lifetime => (),
1297                 GenericParamKind::Type { default: Some(_), .. }
1298                 | GenericParamKind::Const { default: Some(_), .. } => {
1299                     prev_param_default = Some(param.ident.span);
1300                 }
1301                 GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
1302                     if let Some(span) = prev_param_default {
1303                         let mut err = self.err_handler().struct_span_err(
1304                             span,
1305                             "generic parameters with a default must be trailing",
1306                         );
1307                         err.emit();
1308                         break;
1309                     }
1310                 }
1311             }
1312         }
1313
1314         validate_generic_param_order(self.err_handler(), &generics.params, generics.span);
1315
1316         for predicate in &generics.where_clause.predicates {
1317             if let WherePredicate::EqPredicate(predicate) = predicate {
1318                 deny_equality_constraints(self, predicate, generics);
1319             }
1320         }
1321         walk_list!(self, visit_generic_param, &generics.params);
1322         for predicate in &generics.where_clause.predicates {
1323             match predicate {
1324                 WherePredicate::BoundPredicate(bound_pred) => {
1325                     // A type binding, eg `for<'c> Foo: Send+Clone+'c`
1326                     self.check_late_bound_lifetime_defs(&bound_pred.bound_generic_params);
1327
1328                     // This is slightly complicated. Our representation for poly-trait-refs contains a single
1329                     // binder and thus we only allow a single level of quantification. However,
1330                     // the syntax of Rust permits quantification in two places in where clauses,
1331                     // e.g., `T: for <'a> Foo<'a>` and `for <'a, 'b> &'b T: Foo<'a>`. If both are
1332                     // defined, then error.
1333                     if !bound_pred.bound_generic_params.is_empty() {
1334                         for bound in &bound_pred.bounds {
1335                             match bound {
1336                                 GenericBound::Trait(t, _) => {
1337                                     if !t.bound_generic_params.is_empty() {
1338                                         struct_span_err!(
1339                                             self.err_handler(),
1340                                             t.span,
1341                                             E0316,
1342                                             "nested quantification of lifetimes"
1343                                         )
1344                                         .emit();
1345                                     }
1346                                 }
1347                                 GenericBound::Outlives(_) => {}
1348                             }
1349                         }
1350                     }
1351                 }
1352                 _ => {}
1353             }
1354             self.visit_where_predicate(predicate);
1355         }
1356     }
1357
1358     fn visit_generic_param(&mut self, param: &'a GenericParam) {
1359         if let GenericParamKind::Lifetime { .. } = param.kind {
1360             self.check_lifetime(param.ident);
1361         }
1362         visit::walk_generic_param(self, param);
1363     }
1364
1365     fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) {
1366         if let GenericBound::Trait(poly, modify) = bound {
1367             match (ctxt, modify) {
1368                 (BoundKind::SuperTraits, TraitBoundModifier::Maybe) => {
1369                     let mut err = self
1370                         .err_handler()
1371                         .struct_span_err(poly.span, "`?Trait` is not permitted in supertraits");
1372                     let path_str = pprust::path_to_string(&poly.trait_ref.path);
1373                     err.note(&format!("traits are `?{}` by default", path_str));
1374                     err.emit();
1375                 }
1376                 (BoundKind::TraitObject, TraitBoundModifier::Maybe) => {
1377                     let mut err = self.err_handler().struct_span_err(
1378                         poly.span,
1379                         "`?Trait` is not permitted in trait object types",
1380                     );
1381                     err.emit();
1382                 }
1383                 (_, TraitBoundModifier::MaybeConst) if let Some(reason) = &self.disallow_tilde_const => {
1384                     let mut err = self.err_handler().struct_span_err(bound.span(), "`~const` is not allowed here");
1385                     match reason {
1386                         DisallowTildeConstContext::TraitObject => err.note("trait objects cannot have `~const` trait bounds"),
1387                         DisallowTildeConstContext::ImplTrait => err.note("`impl Trait`s cannot have `~const` trait bounds"),
1388                         DisallowTildeConstContext::Fn(FnKind::Closure(..)) => err.note("closures cannot have `~const` trait bounds"),
1389                         DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => err.span_note(ident.span, "this function is not `const`, so it cannot have `~const` trait bounds"),
1390                     };
1391                     err.emit();
1392                 }
1393                 (_, TraitBoundModifier::MaybeConstMaybe) => {
1394                     self.err_handler()
1395                         .span_err(bound.span(), "`~const` and `?` are mutually exclusive");
1396                 }
1397                 _ => {}
1398             }
1399         }
1400
1401         visit::walk_param_bound(self, bound)
1402     }
1403
1404     fn visit_poly_trait_ref(&mut self, t: &'a PolyTraitRef) {
1405         self.check_late_bound_lifetime_defs(&t.bound_generic_params);
1406         visit::walk_poly_trait_ref(self, t);
1407     }
1408
1409     fn visit_variant_data(&mut self, s: &'a VariantData) {
1410         self.with_banned_assoc_ty_bound(|this| visit::walk_struct_def(this, s))
1411     }
1412
1413     fn visit_enum_def(&mut self, enum_definition: &'a EnumDef) {
1414         self.with_banned_assoc_ty_bound(|this| visit::walk_enum_def(this, enum_definition))
1415     }
1416
1417     fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) {
1418         // Only associated `fn`s can have `self` parameters.
1419         let self_semantic = match fk.ctxt() {
1420             Some(FnCtxt::Assoc(_)) => SelfSemantic::Yes,
1421             _ => SelfSemantic::No,
1422         };
1423         self.check_fn_decl(fk.decl(), self_semantic);
1424
1425         self.check_c_variadic_type(fk);
1426
1427         // Functions cannot both be `const async`
1428         if let Some(FnHeader {
1429             constness: Const::Yes(cspan),
1430             asyncness: Async::Yes { span: aspan, .. },
1431             ..
1432         }) = fk.header()
1433         {
1434             self.err_handler()
1435                 .struct_span_err(
1436                     vec![*cspan, *aspan],
1437                     "functions cannot be both `const` and `async`",
1438                 )
1439                 .span_label(*cspan, "`const` because of this")
1440                 .span_label(*aspan, "`async` because of this")
1441                 .span_label(span, "") // Point at the fn header.
1442                 .emit();
1443         }
1444
1445         if let FnKind::Closure(ClosureBinder::For { generic_params, .. }, ..) = fk {
1446             self.check_late_bound_lifetime_defs(generic_params);
1447         }
1448
1449         if let FnKind::Fn(
1450             _,
1451             _,
1452             FnSig { span: sig_span, header: FnHeader { ext: Extern::Implicit(_), .. }, .. },
1453             _,
1454             _,
1455             _,
1456         ) = fk
1457         {
1458             self.maybe_lint_missing_abi(*sig_span, id);
1459         }
1460
1461         // Functions without bodies cannot have patterns.
1462         if let FnKind::Fn(ctxt, _, sig, _, _, None) = fk {
1463             Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| {
1464                 let (code, msg, label) = match ctxt {
1465                     FnCtxt::Foreign => (
1466                         error_code!(E0130),
1467                         "patterns aren't allowed in foreign function declarations",
1468                         "pattern not allowed in foreign function",
1469                     ),
1470                     _ => (
1471                         error_code!(E0642),
1472                         "patterns aren't allowed in functions without bodies",
1473                         "pattern not allowed in function without body",
1474                     ),
1475                 };
1476                 if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) {
1477                     if let Some(ident) = ident {
1478                         let diag = BuiltinLintDiagnostics::PatternsInFnsWithoutBody(span, ident);
1479                         self.lint_buffer.buffer_lint_with_diagnostic(
1480                             PATTERNS_IN_FNS_WITHOUT_BODY,
1481                             id,
1482                             span,
1483                             msg,
1484                             diag,
1485                         )
1486                     }
1487                 } else {
1488                     self.err_handler()
1489                         .struct_span_err(span, msg)
1490                         .span_label(span, label)
1491                         .code(code)
1492                         .emit();
1493                 }
1494             });
1495         }
1496
1497         let tilde_const_allowed =
1498             matches!(fk.header(), Some(FnHeader { constness: ast::Const::Yes(_), .. }))
1499                 || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)));
1500
1501         let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk));
1502
1503         self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
1504     }
1505
1506     fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
1507         if self.session.contains_name(&item.attrs, sym::no_mangle) {
1508             self.check_nomangle_item_asciionly(item.ident, item.span);
1509         }
1510
1511         if ctxt == AssocCtxt::Trait || !self.in_trait_impl {
1512             self.check_defaultness(item.span, item.kind.defaultness());
1513         }
1514
1515         if ctxt == AssocCtxt::Impl {
1516             match &item.kind {
1517                 AssocItemKind::Const(_, _, body) => {
1518                     if body.is_none() {
1519                         self.session.emit_err(AssocConstWithoutBody {
1520                             span: item.span,
1521                             replace_span: self.ending_semi_or_hi(item.span),
1522                         });
1523                     }
1524                 }
1525                 AssocItemKind::Fn(box Fn { body, .. }) => {
1526                     if body.is_none() {
1527                         self.session.emit_err(AssocFnWithoutBody {
1528                             span: item.span,
1529                             replace_span: self.ending_semi_or_hi(item.span),
1530                         });
1531                     }
1532                 }
1533                 AssocItemKind::Type(box TyAlias {
1534                     generics,
1535                     where_clauses,
1536                     where_predicates_split,
1537                     bounds,
1538                     ty,
1539                     ..
1540                 }) => {
1541                     if ty.is_none() {
1542                         self.session.emit_err(AssocTypeWithoutBody {
1543                             span: item.span,
1544                             replace_span: self.ending_semi_or_hi(item.span),
1545                         });
1546                     }
1547                     self.check_type_no_bounds(bounds, "`impl`s");
1548                     if ty.is_some() {
1549                         self.check_gat_where(
1550                             item.id,
1551                             generics.where_clause.predicates.split_at(*where_predicates_split).0,
1552                             *where_clauses,
1553                         );
1554                     }
1555                 }
1556                 _ => {}
1557             }
1558         }
1559
1560         if ctxt == AssocCtxt::Trait || self.in_trait_impl {
1561             self.invalid_visibility(&item.vis, None);
1562             if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
1563                 self.check_trait_fn_not_const(sig.header.constness);
1564             }
1565         }
1566
1567         if let AssocItemKind::Const(..) = item.kind {
1568             self.check_item_named(item.ident, "const");
1569         }
1570
1571         match &item.kind {
1572             AssocItemKind::Type(box TyAlias { generics, bounds, ty, .. })
1573                 if ctxt == AssocCtxt::Trait =>
1574             {
1575                 self.visit_vis(&item.vis);
1576                 self.visit_ident(item.ident);
1577                 walk_list!(self, visit_attribute, &item.attrs);
1578                 self.with_tilde_const_allowed(|this| {
1579                     this.visit_generics(generics);
1580                     walk_list!(this, visit_param_bound, bounds, BoundKind::Bound);
1581                 });
1582                 walk_list!(self, visit_ty, ty);
1583             }
1584             AssocItemKind::Fn(box Fn { sig, generics, body, .. })
1585                 if self.in_const_trait_impl
1586                     || ctxt == AssocCtxt::Trait
1587                     || matches!(sig.header.constness, Const::Yes(_)) =>
1588             {
1589                 self.visit_vis(&item.vis);
1590                 self.visit_ident(item.ident);
1591                 let kind = FnKind::Fn(
1592                     FnCtxt::Assoc(ctxt),
1593                     item.ident,
1594                     sig,
1595                     &item.vis,
1596                     generics,
1597                     body.as_deref(),
1598                 );
1599                 self.visit_fn(kind, item.span, item.id);
1600             }
1601             _ => self
1602                 .with_in_trait_impl(false, None, |this| visit::walk_assoc_item(this, item, ctxt)),
1603         }
1604     }
1605 }
1606
1607 /// When encountering an equality constraint in a `where` clause, emit an error. If the code seems
1608 /// like it's setting an associated type, provide an appropriate suggestion.
1609 fn deny_equality_constraints(
1610     this: &mut AstValidator<'_>,
1611     predicate: &WhereEqPredicate,
1612     generics: &Generics,
1613 ) {
1614     let mut err = this.err_handler().struct_span_err(
1615         predicate.span,
1616         "equality constraints are not yet supported in `where` clauses",
1617     );
1618     err.span_label(predicate.span, "not supported");
1619
1620     // Given `<A as Foo>::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
1621     if let TyKind::Path(Some(qself), full_path) = &predicate.lhs_ty.kind {
1622         if let TyKind::Path(None, path) = &qself.ty.kind {
1623             match &path.segments[..] {
1624                 [PathSegment { ident, args: None, .. }] => {
1625                     for param in &generics.params {
1626                         if param.ident == *ident {
1627                             let param = ident;
1628                             match &full_path.segments[qself.position..] {
1629                                 [PathSegment { ident, args, .. }] => {
1630                                     // Make a new `Path` from `foo::Bar` to `Foo<Bar = RhsTy>`.
1631                                     let mut assoc_path = full_path.clone();
1632                                     // Remove `Bar` from `Foo::Bar`.
1633                                     assoc_path.segments.pop();
1634                                     let len = assoc_path.segments.len() - 1;
1635                                     let gen_args = args.as_deref().cloned();
1636                                     // Build `<Bar = RhsTy>`.
1637                                     let arg = AngleBracketedArg::Constraint(AssocConstraint {
1638                                         id: rustc_ast::node_id::DUMMY_NODE_ID,
1639                                         ident: *ident,
1640                                         gen_args,
1641                                         kind: AssocConstraintKind::Equality {
1642                                             term: predicate.rhs_ty.clone().into(),
1643                                         },
1644                                         span: ident.span,
1645                                     });
1646                                     // Add `<Bar = RhsTy>` to `Foo`.
1647                                     match &mut assoc_path.segments[len].args {
1648                                         Some(args) => match args.deref_mut() {
1649                                             GenericArgs::Parenthesized(_) => continue,
1650                                             GenericArgs::AngleBracketed(args) => {
1651                                                 args.args.push(arg);
1652                                             }
1653                                         },
1654                                         empty_args => {
1655                                             *empty_args = AngleBracketedArgs {
1656                                                 span: ident.span,
1657                                                 args: vec![arg],
1658                                             }
1659                                             .into();
1660                                         }
1661                                     }
1662                                     err.span_suggestion_verbose(
1663                                         predicate.span,
1664                                         &format!(
1665                                             "if `{}` is an associated type you're trying to set, \
1666                                             use the associated type binding syntax",
1667                                             ident
1668                                         ),
1669                                         format!(
1670                                             "{}: {}",
1671                                             param,
1672                                             pprust::path_to_string(&assoc_path)
1673                                         ),
1674                                         Applicability::MaybeIncorrect,
1675                                     );
1676                                 }
1677                                 _ => {}
1678                             };
1679                         }
1680                     }
1681                 }
1682                 _ => {}
1683             }
1684         }
1685     }
1686     // Given `A: Foo, A::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
1687     if let TyKind::Path(None, full_path) = &predicate.lhs_ty.kind {
1688         if let [potential_param, potential_assoc] = &full_path.segments[..] {
1689             for param in &generics.params {
1690                 if param.ident == potential_param.ident {
1691                     for bound in &param.bounds {
1692                         if let ast::GenericBound::Trait(trait_ref, TraitBoundModifier::None) = bound
1693                         {
1694                             if let [trait_segment] = &trait_ref.trait_ref.path.segments[..] {
1695                                 let assoc = pprust::path_to_string(&ast::Path::from_ident(
1696                                     potential_assoc.ident,
1697                                 ));
1698                                 let ty = pprust::ty_to_string(&predicate.rhs_ty);
1699                                 let (args, span) = match &trait_segment.args {
1700                                     Some(args) => match args.deref() {
1701                                         ast::GenericArgs::AngleBracketed(args) => {
1702                                             let Some(arg) = args.args.last() else {
1703                                                 continue;
1704                                             };
1705                                             (
1706                                                 format!(", {} = {}", assoc, ty),
1707                                                 arg.span().shrink_to_hi(),
1708                                             )
1709                                         }
1710                                         _ => continue,
1711                                     },
1712                                     None => (
1713                                         format!("<{} = {}>", assoc, ty),
1714                                         trait_segment.span().shrink_to_hi(),
1715                                     ),
1716                                 };
1717                                 err.multipart_suggestion(
1718                                     &format!(
1719                                         "if `{}::{}` is an associated type you're trying to set, \
1720                                         use the associated type binding syntax",
1721                                         trait_segment.ident, potential_assoc.ident,
1722                                     ),
1723                                     vec![(span, args), (predicate.span, String::new())],
1724                                     Applicability::MaybeIncorrect,
1725                                 );
1726                             }
1727                         }
1728                     }
1729                 }
1730             }
1731         }
1732     }
1733     err.note(
1734         "see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information",
1735     );
1736     err.emit();
1737 }
1738
1739 pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> bool {
1740     let mut validator = AstValidator {
1741         session,
1742         extern_mod: None,
1743         in_trait_impl: false,
1744         in_const_trait_impl: false,
1745         has_proc_macro_decls: false,
1746         outer_impl_trait: None,
1747         disallow_tilde_const: None,
1748         is_impl_trait_banned: false,
1749         is_assoc_ty_bound_banned: false,
1750         forbidden_let_reason: Some(ForbiddenLetReason::GenericForbidden),
1751         lint_buffer: lints,
1752     };
1753     visit::walk_crate(&mut validator, krate);
1754
1755     validator.has_proc_macro_decls
1756 }
1757
1758 /// Used to forbid `let` expressions in certain syntactic locations.
1759 #[derive(Clone, Copy, Subdiagnostic)]
1760 pub(crate) enum ForbiddenLetReason {
1761     /// `let` is not valid and the source environment is not important
1762     GenericForbidden,
1763     /// A let chain with the `||` operator
1764     #[note(not_supported_or)]
1765     NotSupportedOr(#[primary_span] Span),
1766     /// A let chain with invalid parentheses
1767     ///
1768     /// For example, `let 1 = 1 && (expr && expr)` is allowed
1769     /// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not
1770     #[note(not_supported_parentheses)]
1771     NotSupportedParentheses(#[primary_span] Span),
1772 }