1 // Validate AST before lowering it to HIR.
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.
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;
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};
24 use rustc_target::spec::abi;
26 use std::ops::DerefMut;
28 const MORE_EXTERN: &str =
29 "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html";
31 /// Is `self` allowed semantically as the first parameter in an `FnDecl`?
37 struct AstValidator<'a> {
40 /// The span of the `extern` in an `extern { ... }` block, if any.
41 extern_mod: Option<&'a Item>,
43 /// Are we inside a trait impl?
46 in_const_trait_impl: bool,
48 has_proc_macro_decls: bool,
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>,
55 is_tilde_const_allowed: bool,
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,
61 /// Used to ban associated type bounds (i.e., `Type<AssocType: Bounds>`) in
62 /// certain positions.
63 is_assoc_ty_bound_banned: bool,
65 /// Used to allow `let` expressions in certain syntactic locations.
68 lint_buffer: &'a mut LintBuffer,
71 impl<'a> AstValidator<'a> {
72 fn with_in_trait_impl(
75 constness: Option<Const>,
76 f: impl FnOnce(&mut Self),
78 let old = mem::replace(&mut self.in_trait_impl, is_in);
80 mem::replace(&mut self.in_const_trait_impl, matches!(constness, Some(Const::Yes(_))));
82 self.in_trait_impl = old;
83 self.in_const_trait_impl = old_const;
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);
89 self.is_impl_trait_banned = old;
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);
95 self.is_tilde_const_allowed = old;
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);
101 self.is_tilde_const_allowed = old;
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);
107 self.is_let_allowed = old;
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")
119 sess.struct_span_err(expr.span, "expected expression, found statement (`let`)")
120 .note("variable declaration using `let` is a statement")
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);
128 self.is_assoc_ty_bound_banned = old;
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);
134 self.with_banned_tilde_const(f);
138 self.outer_impl_trait = old;
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(
148 "associated type bounds are not allowed within structs, enums, or unions",
153 self.visit_assoc_ty_constraint(constraint);
156 // Mirrors `visit::walk_ty`, but tracks relevant state.
157 fn walk_ty(&mut self, t: &'a Ty) {
159 TyKind::ImplTrait(..) => {
160 self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t))
162 TyKind::TraitObject(..) => self.with_banned_tilde_const(|this| visit::walk_ty(this, t)),
163 TyKind::Path(ref qself, ref path) => {
165 // - `Option<impl Trait>`
166 // - `option::Option<impl Trait>`
167 // - `option::Option<T>::Foo<impl Trait>
170 // - `<impl Trait>::Foo`
171 // - `option::Option<impl Trait>::Foo`.
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));
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);
190 self.with_banned_impl_trait(|this| {
191 this.visit_path_segment(path.span, segment)
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)
201 _ => visit::walk_ty(self, t),
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);
217 self.visit_field_def(field);
220 fn err_handler(&self) -> &rustc_errors::Handler {
221 &self.session.diagnostic()
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");
231 fn check_label(&self, ident: Ident) {
232 if ident.without_first_quote().is_reserved() {
234 .span_err(ident.span, &format!("invalid label name `{}`", ident.name));
238 fn invalid_visibility(&self, vis: &Visibility, note: Option<&str>) {
239 if let VisibilityKind::Inherited = vis.kind {
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");
248 if let Some(note) = note {
254 fn check_anonymous_field(&self, field: &FieldDef) {
255 let FieldDef { ty, .. } = field;
257 TyKind::AnonymousStruct(..) | TyKind::AnonymousUnion(..) => {
258 // We already checked for `kw::Underscore` before calling this function,
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
266 let msg = "unnamed fields can only have struct or union types";
267 let label = "not a struct or union";
269 .struct_span_err(field.span, msg)
270 .span_label(ty.span, label)
276 fn deny_anonymous_struct(&self, ty: &Ty) {
278 TyKind::AnonymousStruct(..) => {
282 "anonymous structs are not allowed outside of unnamed struct or union fields",
284 .span_label(ty.span, "anonymous struct declared here")
287 TyKind::AnonymousUnion(..) => {
291 "anonymous unions are not allowed outside of unnamed struct or union fields",
293 .span_label(ty.span, "anonymous union declared here")
300 fn deny_anonymous_field(&self, field: &FieldDef) {
301 if let Some(ident) = field.ident {
302 if ident.name == kw::Underscore {
306 "anonymous fields are not allowed outside of structs or unions",
308 .span_label(ident.span, "anonymous field declared here")
314 fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
315 for Param { pat, .. } in &decl.inputs {
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)
321 _ => report_err(pat.span, None, false),
326 fn check_trait_fn_not_async(&self, fn_span: Span, asyncness: Async) {
327 if let Async::Yes { span, .. } = asyncness {
332 "functions in traits cannot be declared `async`"
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")
341 fn check_trait_fn_not_const(&self, constness: Const) {
342 if let Const::Yes(span) = constness {
347 "functions in traits cannot be declared const"
349 .span_label(span, "functions in traits cannot be const")
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(
360 &format!("`?Trait` is not permitted in {}", where_),
363 let path_str = pprust::path_to_string(&poly.trait_ref.path);
364 err.note(&format!("traits are `?{}` by default", path_str));
371 /// Matches `'-' lit | lit (cf. parser::Parser::parse_literal_maybe_minus)`,
372 /// or paths for ranges.
374 // FIXME: do we want to allow `expr -> pattern` conversion to create path expressions?
375 // That means making this work:
377 // ```rust,ignore (FIXME)
386 fn check_expr_within_pat(&self, expr: &Expr, allow_paths: bool) {
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(
393 "arbitrary expressions aren't allowed \
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
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();
409 .span_err(spans, "lifetime bounds cannot be used in this context");
413 _ => Some(param.ident.span),
416 if !non_lt_param_spans.is_empty() {
417 self.err_handler().span_err(
419 "only lifetime parameters can be used in this context",
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);
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(
439 &format!("function can not have more than {} arguments", max_num_args),
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(
450 "C-variadic function must be declared with at least one named argument",
455 for Param { ty, span, .. } in ps {
456 if let TyKind::CVarArgs = ty.kind {
457 self.err_handler().span_err(
459 "`...` must be the last argument of a C-variadic function",
468 fn check_decl_attrs(&self, fn_decl: &FnDecl) {
472 .flat_map(|i| i.attrs.as_ref())
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)
478 if attr.is_doc_comment() {
482 "documentation comments cannot be applied to function parameters",
484 .span_label(attr.span, "doc comments are not allowed here")
487 self.err_handler().span_err(
489 "allow, cfg, cfg_attr, deny, \
490 forbid, and warn are the only allowed built-in attributes in function parameters",
496 fn check_decl_self_param(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
497 if let (SelfSemantic::No, [param, ..]) = (self_semantic, &*fn_decl.inputs) {
502 "`self` parameter is only allowed in associated functions",
504 .span_label(param.span, "not semantically valid as function parameter")
505 .note("associated functions are those in `impl` or `trait` definitions")
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);
515 .struct_span_err(span, "`default` is only allowed on items in trait impls")
516 .span_label(def_span, "`default` because of this")
521 fn error_item_without_body(&self, sp: Span, ctx: &str, msg: &str, sugg: &str) {
523 .struct_span_err(sp, msg)
525 self.session.source_map().end_point(sp),
526 &format!("provide a definition for the {}", ctx),
528 Applicability::HasPlaceholders,
533 fn check_impl_item_provided<T>(&self, sp: Span, body: &Option<T>, ctx: &str, sugg: &str) {
535 let msg = format!("associated {} in `impl` without body", ctx);
536 self.error_item_without_body(sp, ctx, &msg, sugg);
540 fn check_type_no_bounds(&self, bounds: &[GenericBound], ctx: &str) {
541 let span = match bounds {
544 [b0, .., bl] => b0.span().to(bl.span()),
547 .struct_span_err(span, &format!("bounds on `type`s in {} have no effect", ctx))
551 fn check_foreign_ty_genericless(&self, generics: &Generics) {
552 let cannot_have = |span, descr, remove_descr| {
556 &format!("`type`s inside `extern` blocks cannot have {}", descr),
560 &format!("remove the {}", remove_descr),
562 Applicability::MaybeIncorrect,
564 .span_label(self.current_extern_span(), "`extern` block begins here")
569 if !generics.params.is_empty() {
570 cannot_have(generics.span, "generic parameters", "generic parameters");
573 if !generics.where_clause.predicates.is_empty() {
574 cannot_have(generics.where_clause.span, "`where` clauses", "`where` clause");
578 fn check_foreign_kind_bodyless(&self, ident: Ident, kind: &str, body: Option<Span>) {
579 let body = match body {
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")
588 self.current_extern_span(),
590 "`extern` blocks define existing foreign {0}s and {0}s \
591 inside of them cannot have a body",
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 {
606 .struct_span_err(ident.span, "incorrect function inside `extern` block")
607 .span_label(ident.span, "cannot have a body")
610 "remove the invalid body",
612 Applicability::MaybeIncorrect,
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",
619 self.current_extern_span(),
620 "`extern` blocks define existing foreign functions and functions \
621 inside of them cannot have a body",
627 fn current_extern_span(&self) -> Span {
628 self.session.source_map().guess_head_span(self.extern_mod.unwrap().span)
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() {
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",
641 Applicability::MaybeIncorrect,
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() {
655 "items in `extern` blocks cannot use non-ascii identifiers",
657 .span_label(self.current_extern_span(), "in this `extern` block")
659 "This limitation may be lifted in the future; see issue #{} <https://github.com/rust-lang/rust/issues/{}> for more information",
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(_)) =>
682 for Param { ty, span, .. } in &fk.decl().inputs {
683 if let TyKind::CVarArgs = ty.kind {
687 "only foreign or `unsafe extern \"C\"` functions may be C-variadic",
694 fn check_item_named(&self, ident: Ident, kind: &str) {
695 if ident.name != kw::Underscore {
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))
704 fn check_nomangle_item_asciionly(&self, ident: Ident, item_span: Span) {
705 if ident.name.as_str().is_ascii() {
708 let head_span = self.session.source_map().guess_head_span(item_span);
713 "`#[no_mangle]` requires ASCII identifier"
718 fn check_mod_file_item_asciionly(&self, ident: Ident) {
719 if ident.name.as_str().is_ascii() {
726 "trying to load file for module `{}` with non-ascii identifier name",
729 .help("consider using `#[path]` attribute to specify filesystem path")
733 fn deny_generic_params(&self, generics: &Generics, ident_span: Span) {
734 if !generics.params.is_empty() {
739 "auto traits cannot have generic parameters"
741 .span_label(ident_span, "auto trait cannot have generic parameters")
744 "remove the parameters",
746 Applicability::MachineApplicable,
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")
759 "remove the super traits",
761 Applicability::MachineApplicable,
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();
774 "auto traits cannot have methods or associated items"
776 .span_label(ident_span, "auto trait cannot have items")
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)))
789 let args_sugg = data.args.iter().filter_map(|a| match a {
790 AngleBracketedArg::Arg(GenericArg::Lifetime(_)) | AngleBracketedArg::Constraint(_) => {
793 AngleBracketedArg::Arg(arg) => Some(pprust::to_string(|s| s.print_generic_arg(arg))),
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)))
804 lt_sugg.chain(args_sugg).chain(constraint_sugg).collect::<Vec<String>>().join(", ")
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(_))) {
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()),
820 let args_len = arg_spans.len();
821 let constraint_len = constraint_spans.len();
822 // ...and then error:
826 "generic arguments must come before the first constraint",
828 .span_label(constraint_spans[0], &format!("constraint{}", pluralize!(constraint_len)))
830 *arg_spans.iter().last().unwrap(),
831 &format!("generic argument{}", pluralize!(args_len)),
833 .span_labels(constraint_spans, "")
834 .span_labels(arg_spans, "")
835 .span_suggestion_verbose(
838 "move the constraint{} after the generic argument{}",
839 pluralize!(constraint_len),
842 self.correct_generic_order_suggestion(&data),
843 Applicability::MachineApplicable,
848 fn visit_ty_common(&mut self, ty: &'a Ty) {
850 TyKind::BareFn(ref bfty) => {
851 self.check_fn_decl(&bfty.decl, SelfSemantic::No);
852 Self::check_decl_no_pat(&bfty.decl, |span, _, _| {
857 "patterns aren't allowed in function pointer types"
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);
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 {
876 "only a single explicit lifetime bound is permitted"
881 any_lifetime_bounds = true;
884 self.no_questions_in_bounds(bounds, "trait object types", false);
886 TyKind::ImplTrait(_, ref bounds) => {
887 if self.is_impl_trait_banned {
892 "`impl Trait` is not allowed in path parameters"
897 if let Some(outer_impl_trait_sp) = self.outer_impl_trait {
902 "nested `impl Trait` is not allowed"
904 .span_label(outer_impl_trait_sp, "outer `impl Trait`")
905 .span_label(ty.span, "nested `impl Trait` here")
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");
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
923 .span_to_snippet(span)
924 .map(|snippet| snippet.starts_with("#["))
926 if !is_macro_callsite {
927 self.lint_buffer.buffer_lint_with_diagnostic(
931 "extern declarations without an explicit ABI are deprecated",
932 BuiltinLintDiagnostics::MissingAbi(span, abi::Abi::FALLBACK),
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(
942 handler: &rustc_errors::Handler,
943 generics: &[GenericParam],
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());
950 for (idx, param) in generics.iter().enumerate() {
951 let ident = param.ident;
952 let (kind, bounds, span) = (¶m.kind, ¶m.bounds, ident.span);
953 let (ord_kind, ident) = match ¶m.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))
962 param_idents.push((kind, ord_kind, bounds, idx, ident));
964 Some(max_param) if max_param > ord_kind => {
965 let entry = out_of_order.entry(ord_kind).or_insert((max_param, vec![]));
968 Some(_) | None => max_param = Some(ord_kind),
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 {
978 ordered_params += ", ";
980 ordered_params += &ident;
982 if !bounds.is_empty() {
983 ordered_params += ": ";
984 ordered_params += &pprust::bounds_to_string(&bounds);
988 GenericParamKind::Type { default: Some(default) } => {
989 ordered_params += " = ";
990 ordered_params += &pprust::ty_to_string(default);
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);
998 GenericParamKind::Const { ty: _, kw_span: _, default: None } => (),
1003 ordered_params += ">";
1005 for (param_ord, (max_param, spans)) in &out_of_order {
1006 let mut err = handler.struct_span_err(
1009 "{} parameters must be declared prior to {} parameters",
1010 param_ord, max_param,
1013 err.span_suggestion(
1016 "reorder the parameters: lifetimes, {}",
1017 if sess.features_untracked().unordered_const_ty_params() {
1018 "then consts and types"
1020 "then types, then consts"
1023 ordered_params.clone(),
1024 Applicability::MachineApplicable,
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);
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));
1044 ExprKind::Let(..) if !let_allowed => this.ban_let_expr(expr),
1045 ExprKind::LlvmInlineAsm(..) if !this.session.target.allow_asm => {
1050 "llvm_asm! is unsupported on this target"
1054 ExprKind::Match(expr, arms) => {
1055 this.visit_expr(expr);
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));
1068 ExprKind::Paren(_) | ExprKind::Binary(Spanned { node: BinOpKind::And, .. }, ..) => {
1069 this.with_let_allowed(let_allowed, |this, _| visit::walk_expr(this, expr));
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));
1078 _ => visit::walk_expr(this, expr),
1082 fn visit_ty(&mut self, ty: &'a Ty) {
1083 self.visit_ty_common(ty);
1084 self.deny_anonymous_struct(ty);
1088 fn visit_label(&mut self, label: &'a Label) {
1089 self.check_label(label.ident);
1090 visit::walk_label(self, label);
1093 fn visit_lifetime(&mut self, lifetime: &'a Lifetime) {
1094 self.check_lifetime(lifetime.ident);
1095 visit::walk_lifetime(self, lifetime);
1098 fn visit_field_def(&mut self, s: &'a FieldDef) {
1099 self.deny_anonymous_field(s);
1100 visit::walk_field_def(self, s)
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;
1108 if self.session.contains_name(&item.attrs, sym::no_mangle) {
1109 self.check_nomangle_item_asciionly(item.ident, item.span);
1113 ItemKind::Impl(box ImplKind {
1119 of_trait: Some(ref t),
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 {
1129 "`impl Trait for .. {}` is an obsolete syntax",
1131 .help("use `auto trait Trait {}` instead")
1134 if let (Unsafe::Yes(span), ImplPolarity::Negative(sp)) = (unsafety, polarity) {
1139 "negative impls cannot be unsafe"
1141 .span_label(sp, "negative because of this")
1142 .span_label(span, "unsafe because of this")
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));
1151 this.visit_generics(generics);
1153 this.visit_trait_ref(t);
1154 this.visit_ty(self_ty);
1156 walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl);
1158 return; // Avoid visiting again.
1160 ItemKind::Impl(box ImplKind {
1170 let error = |annotation_span, annotation| {
1171 let mut err = self.err_handler().struct_span_err(
1173 &format!("inherent impls cannot be {}", annotation),
1175 err.span_label(annotation_span, &format!("{} because of this", annotation));
1176 err.span_label(self_ty.span, "inherent impl for this type");
1180 self.invalid_visibility(
1182 Some("place qualifiers on individual impl items instead"),
1184 if let Unsafe::Yes(span) = unsafety {
1185 error(span, "unsafe").code(error_code!(E0197)).emit();
1187 if let ImplPolarity::Negative(span) = polarity {
1188 error(span, "negative").emit();
1190 if let Defaultness::Default(def_span) = defaultness {
1191 error(def_span, "`default`")
1192 .note("only trait implementations may be annotated with `default`")
1195 if let Const::Yes(span) = constness {
1196 error(span, "`const`")
1197 .note("only trait implementations may be annotated with `const`")
1201 ItemKind::Fn(box FnKind(def, ref sig, ref generics, ref body)) => {
1202 self.check_defaultness(item.span, def);
1205 let msg = "free function without a body";
1206 self.error_item_without_body(item.span, "function", msg, " { <body> }");
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));
1213 self.visit_generics(generics);
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.
1220 ItemKind::ForeignMod(ForeignMod { abi, unsafety, .. }) => {
1221 let old_item = mem::replace(&mut self.extern_mod, Some(item));
1222 self.invalid_visibility(
1224 Some("place qualifiers on individual foreign items instead"),
1226 if let Unsafe::Yes(span) = unsafety {
1227 self.err_handler().span_err(span, "extern block cannot be declared unsafe");
1230 self.maybe_lint_missing_abi(item.span, item.id);
1232 visit::walk_item(self, item);
1233 self.extern_mod = old_item;
1234 return; // Avoid visiting again.
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);
1244 ItemKind::Trait(box TraitKind(
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);
1257 self.no_questions_in_bounds(bounds, "supertraits", true);
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);
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");
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)
1277 self.check_mod_file_item_asciionly(item.ident);
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.
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);
1294 walk_list!(self, visit_attribute, &item.attrs);
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");
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);
1311 walk_list!(self, visit_attribute, &item.attrs);
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>;");
1322 ItemKind::Static(.., None) => {
1323 let msg = "free static item without body";
1324 self.error_item_without_body(item.span, "static", msg, " = <expr>;");
1326 ItemKind::TyAlias(box TyAliasKind(def, _, ref bounds, ref body)) => {
1327 self.check_defaultness(item.span, def);
1329 let msg = "free type alias without body";
1330 self.error_item_without_body(item.span, "type", msg, " = <type>;");
1332 self.check_type_no_bounds(bounds, "this context");
1337 visit::walk_item(self, item);
1340 fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
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);
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);
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);
1359 ForeignItemKind::MacCall(..) => {}
1362 visit::walk_foreign_item(self, fi)
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);
1371 for arg in &data.args {
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);
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));
1395 fn visit_generics(&mut self, generics: &'a Generics) {
1396 let cg_defaults = self.session.features_untracked().unordered_const_ty_params();
1398 let mut prev_param_default = None;
1399 for param in &generics.params {
1401 GenericParamKind::Lifetime => (),
1402 GenericParamKind::Type { default: Some(_), .. }
1403 | GenericParamKind::Const { default: Some(_), .. } => {
1404 prev_param_default = Some(param.ident.span);
1406 GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
1407 if let Some(span) = prev_param_default {
1408 let mut err = self.err_handler().struct_span_err(
1410 "generic parameters with a default must be trailing",
1412 if matches!(param.kind, GenericParamKind::Const { .. }) && !cg_defaults {
1414 "using type defaults and const parameters \
1415 in the same parameter list is currently not permitted",
1425 validate_generic_param_order(
1432 for predicate in &generics.where_clause.predicates {
1433 if let WherePredicate::EqPredicate(ref predicate) = *predicate {
1434 deny_equality_constraints(self, predicate, generics);
1437 walk_list!(self, visit_generic_param, &generics.params);
1438 for predicate in &generics.where_clause.predicates {
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);
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 {
1452 GenericBound::Trait(t, _) => {
1453 if !t.bound_generic_params.is_empty() {
1458 "nested quantification of lifetimes"
1463 GenericBound::Outlives(_) => {}
1470 self.visit_where_predicate(predicate);
1474 fn visit_generic_param(&mut self, param: &'a GenericParam) {
1475 if let GenericParamKind::Lifetime { .. } = param.kind {
1476 self.check_lifetime(param.ident);
1478 visit::walk_generic_param(self, param);
1481 fn visit_param_bound(&mut self, bound: &'a GenericBound) {
1483 GenericBound::Trait(_, TraitBoundModifier::MaybeConst) => {
1484 if !self.is_tilde_const_allowed {
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")
1492 GenericBound::Trait(_, TraitBoundModifier::MaybeConstMaybe) => {
1494 .span_err(bound.span(), "`~const` and `?` are mutually exclusive");
1500 visit::walk_param_bound(self, bound)
1503 fn visit_pat(&mut self, pat: &'a Pat) {
1505 PatKind::Lit(expr) => {
1506 self.check_expr_within_pat(expr, false);
1508 PatKind::Range(start, end, _) => {
1509 if let Some(expr) = start {
1510 self.check_expr_within_pat(expr, true);
1512 if let Some(expr) = end {
1513 self.check_expr_within_pat(expr, true);
1519 visit::walk_pat(self, pat)
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);
1527 fn visit_variant_data(&mut self, s: &'a VariantData) {
1528 self.with_banned_assoc_ty_bound(|this| visit::walk_struct_def(this, s))
1533 enum_definition: &'a EnumDef,
1534 generics: &'a Generics,
1538 self.with_banned_assoc_ty_bound(|this| {
1539 visit::walk_enum_def(this, enum_definition, generics, item_id)
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,
1549 self.check_fn_decl(fk.decl(), self_semantic);
1551 self.check_c_varadic_type(fk);
1553 // Functions cannot both be `const async`
1554 if let Some(FnHeader {
1555 constness: Const::Yes(cspan),
1556 asyncness: Async::Yes { span: aspan, .. },
1562 vec![*cspan, *aspan],
1563 "functions cannot be both `const` and `async`",
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.
1574 FnSig { span: sig_span, header: FnHeader { ext: Extern::Implicit, .. }, .. },
1579 self.maybe_lint_missing_abi(*sig_span, id);
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 => (
1588 "patterns aren't allowed in foreign function declarations",
1589 "pattern not allowed in foreign function",
1593 "patterns aren't allowed in functions without bodies",
1594 "pattern not allowed in function without body",
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,
1610 .struct_span_err(span, msg)
1611 .span_label(span, label)
1618 visit::walk_fn(self, fk, span);
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);
1626 if ctxt == AssocCtxt::Trait || !self.in_trait_impl {
1627 self.check_defaultness(item.span, item.kind.defaultness());
1630 if ctxt == AssocCtxt::Impl {
1632 AssocItemKind::Const(_, _, body) => {
1633 self.check_impl_item_provided(item.span, body, "constant", " = <expr>;");
1635 AssocItemKind::Fn(box FnKind(_, _, _, body)) => {
1636 self.check_impl_item_provided(item.span, body, "function", " { <body> }");
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");
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);
1654 if let AssocItemKind::Const(..) = item.kind {
1655 self.check_item_named(item.ident, "const");
1659 AssocItemKind::TyAlias(box TyAliasKind(_, ref generics, ref bounds, ref ty))
1660 if ctxt == AssocCtxt::Trait =>
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);
1669 walk_list!(self, visit_ty, ty);
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(_)) =>
1676 self.visit_vis(&item.vis);
1677 self.visit_ident(item.ident);
1678 self.with_tilde_const_allowed(|this| this.visit_generics(generics));
1680 FnKind::Fn(FnCtxt::Assoc(ctxt), item.ident, sig, &item.vis, body.as_deref());
1681 self.visit_fn(kind, item.span, item.id);
1684 .with_in_trait_impl(false, None, |this| visit::walk_assoc_item(this, item, ctxt)),
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,
1696 let mut err = this.err_handler().struct_span_err(
1698 "equality constraints are not yet supported in `where` clauses",
1700 err.span_label(predicate.span, "not supported");
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 {
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,
1723 kind: AssocTyConstraintKind::Equality {
1724 ty: predicate.rhs_ty.clone(),
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);
1737 *empty_args = AngleBracketedArgs {
1744 err.span_suggestion_verbose(
1747 "if `{}` is an associated type you're trying to set, \
1748 use the associated type binding syntax",
1754 pprust::path_to_string(&assoc_path)
1756 Applicability::MaybeIncorrect,
1769 "see issue #20041 <https://github.com/rust-lang/rust/issues/20041> for more information",
1774 pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) -> bool {
1775 let mut validator = AstValidator {
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,
1788 visit::walk_crate(&mut validator, krate);
1790 validator.has_proc_macro_decls