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