Reduce scope of AstValidator::with_* calls.

`AstValidator` has several `with_*` methods, each one setting a field
that adjust how checking takes place for items within certain other
items. E.g. `with_in_trait_impl` is used to adjust the checking done on
items inside an `impl` item. Weirdly, the scopes used for most of the
`with_*` calls are very broad, and include things that aren't "inside"
the item, such as visibility, unsafety, and constness.

This commit minimizes the scope of these `with_*` calls so they only
apply to the things inside the item.
This commit is contained in:
Nicholas Nethercote 2025-04-02 14:31:27 +11:00
parent fb01485690
commit 2e7de1a924

View File

@ -855,19 +855,17 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
items, items,
}) => { }) => {
self.visit_attrs_vis(&item.attrs, &item.vis); self.visit_attrs_vis(&item.attrs, &item.vis);
self.with_in_trait_impl(Some((*constness, *polarity, t)), |this| { self.visibility_not_permitted(
this.visibility_not_permitted(
&item.vis, &item.vis,
errors::VisibilityNotPermittedNote::TraitImpl, errors::VisibilityNotPermittedNote::TraitImpl,
); );
if let TyKind::Dummy = self_ty.kind { if let TyKind::Dummy = self_ty.kind {
// Abort immediately otherwise the `TyKind::Dummy` will reach HIR lowering, // Abort immediately otherwise the `TyKind::Dummy` will reach HIR lowering,
// which isn't allowed. Not a problem for this obscure, obsolete syntax. // which isn't allowed. Not a problem for this obscure, obsolete syntax.
this.dcx().emit_fatal(errors::ObsoleteAuto { span: item.span }); self.dcx().emit_fatal(errors::ObsoleteAuto { span: item.span });
} }
if let (&Safety::Unsafe(span), &ImplPolarity::Negative(sp)) = (safety, polarity) if let (&Safety::Unsafe(span), &ImplPolarity::Negative(sp)) = (safety, polarity) {
{ self.dcx().emit_err(errors::UnsafeNegativeImpl {
this.dcx().emit_err(errors::UnsafeNegativeImpl {
span: sp.to(t.path.span), span: sp.to(t.path.span),
negative: sp, negative: sp,
r#unsafe: span, r#unsafe: span,
@ -876,10 +874,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
let disallowed = matches!(constness, Const::No) let disallowed = matches!(constness, Const::No)
.then(|| TildeConstReason::TraitImpl { span: item.span }); .then(|| TildeConstReason::TraitImpl { span: item.span });
this.with_tilde_const(disallowed, |this| this.visit_generics(generics)); self.with_tilde_const(disallowed, |this| this.visit_generics(generics));
this.visit_trait_ref(t); self.visit_trait_ref(t);
this.visit_ty(self_ty); self.visit_ty(self_ty);
self.with_in_trait_impl(Some((*constness, *polarity, t)), |this| {
walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl { of_trait: true }); walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl { of_trait: true });
}); });
} }
@ -902,13 +901,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}; };
self.visit_attrs_vis(&item.attrs, &item.vis); self.visit_attrs_vis(&item.attrs, &item.vis);
self.with_in_trait_impl(None, |this| { self.visibility_not_permitted(
this.visibility_not_permitted(
&item.vis, &item.vis,
errors::VisibilityNotPermittedNote::IndividualImplItems, errors::VisibilityNotPermittedNote::IndividualImplItems,
); );
if let &Safety::Unsafe(span) = safety { if let &Safety::Unsafe(span) = safety {
this.dcx().emit_err(errors::InherentImplCannotUnsafe { self.dcx().emit_err(errors::InherentImplCannotUnsafe {
span: self_ty.span, span: self_ty.span,
annotation_span: span, annotation_span: span,
annotation: "unsafe", annotation: "unsafe",
@ -916,20 +914,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}); });
} }
if let &ImplPolarity::Negative(span) = polarity { if let &ImplPolarity::Negative(span) = polarity {
this.dcx().emit_err(error(span, "negative", false)); self.dcx().emit_err(error(span, "negative", false));
} }
if let &Defaultness::Default(def_span) = defaultness { if let &Defaultness::Default(def_span) = defaultness {
this.dcx().emit_err(error(def_span, "`default`", true)); self.dcx().emit_err(error(def_span, "`default`", true));
} }
if let &Const::Yes(span) = constness { if let &Const::Yes(span) = constness {
this.dcx().emit_err(error(span, "`const`", true)); self.dcx().emit_err(error(span, "`const`", true));
} }
this.with_tilde_const( self.with_tilde_const(Some(TildeConstReason::Impl { span: item.span }), |this| {
Some(TildeConstReason::Impl { span: item.span }), this.visit_generics(generics)
|this| this.visit_generics(generics), });
); self.visit_ty(self_ty);
this.visit_ty(self_ty); self.with_in_trait_impl(None, |this| {
walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl { of_trait: false }); walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl { of_trait: false });
}); });
} }
@ -976,18 +974,17 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.visit_fn(kind, item.span, item.id); self.visit_fn(kind, item.span, item.id);
} }
ItemKind::ForeignMod(ForeignMod { extern_span, abi, safety, .. }) => { ItemKind::ForeignMod(ForeignMod { extern_span, abi, safety, .. }) => {
self.with_in_extern_mod(*safety, |this| { let old_item = mem::replace(&mut self.extern_mod_span, Some(item.span));
let old_item = mem::replace(&mut this.extern_mod_span, Some(item.span)); self.visibility_not_permitted(
this.visibility_not_permitted(
&item.vis, &item.vis,
errors::VisibilityNotPermittedNote::IndividualForeignItems, errors::VisibilityNotPermittedNote::IndividualForeignItems,
); );
if &Safety::Default == safety { if &Safety::Default == safety {
if item.span.at_least_rust_2024() { if item.span.at_least_rust_2024() {
this.dcx().emit_err(errors::MissingUnsafeOnExtern { span: item.span }); self.dcx().emit_err(errors::MissingUnsafeOnExtern { span: item.span });
} else { } else {
this.lint_buffer.buffer_lint( self.lint_buffer.buffer_lint(
MISSING_UNSAFE_ON_EXTERN, MISSING_UNSAFE_ON_EXTERN,
item.id, item.id,
item.span, item.span,
@ -999,11 +996,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
} }
if abi.is_none() { if abi.is_none() {
this.maybe_lint_missing_abi(*extern_span, item.id); self.maybe_lint_missing_abi(*extern_span, item.id);
} }
self.with_in_extern_mod(*safety, |this| {
visit::walk_item(this, item); visit::walk_item(this, item);
this.extern_mod_span = old_item;
}); });
self.extern_mod_span = old_item;
} }
ItemKind::Enum(_, def, _) => { ItemKind::Enum(_, def, _) => {
for variant in &def.variants { for variant in &def.variants {
@ -1024,24 +1022,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident); self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident);
let is_const_trait = let is_const_trait =
attr::find_by_name(&item.attrs, sym::const_trait).map(|attr| attr.span); attr::find_by_name(&item.attrs, sym::const_trait).map(|attr| attr.span);
self.with_in_trait(item.span, is_const_trait, |this| {
if *is_auto == IsAuto::Yes { if *is_auto == IsAuto::Yes {
// Auto traits cannot have generics, super traits nor contain items. // Auto traits cannot have generics, super traits nor contain items.
this.deny_generic_params(generics, ident.span); self.deny_generic_params(generics, ident.span);
this.deny_super_traits(bounds, ident.span); self.deny_super_traits(bounds, ident.span);
this.deny_where_clause(&generics.where_clause, ident.span); self.deny_where_clause(&generics.where_clause, ident.span);
this.deny_items(items, ident.span); self.deny_items(items, ident.span);
} }
// Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound // Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
// context for the supertraits. // context for the supertraits.
let disallowed = is_const_trait let disallowed =
.is_none() is_const_trait.is_none().then(|| TildeConstReason::Trait { span: item.span });
.then(|| TildeConstReason::Trait { span: item.span }); self.with_tilde_const(disallowed, |this| {
this.with_tilde_const(disallowed, |this| {
this.visit_generics(generics); this.visit_generics(generics);
walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits) walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
}); });
self.with_in_trait(item.span, is_const_trait, |this| {
walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait); walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait);
}); });
} }