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