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