Rollup merge of #127818 - oli-obk:ast_validation_simplifications, r=petrochenkov
Various ast validation simplifications Changes pulled out of https://github.com/rust-lang/rust/pull/127524 These are needed to make ast validation a mutable visitor, as we can't keep immutable references to the AST around in that case. But I think they are simplifying things in general and can stand on their own
This commit is contained in:
commit
ab4cc440dd
@ -38,7 +38,7 @@
|
|||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use thin_vec::thin_vec;
|
use thin_vec::thin_vec;
|
||||||
|
|
||||||
use crate::errors;
|
use crate::errors::{self, TildeConstReason};
|
||||||
|
|
||||||
/// Is `self` allowed semantically as the first parameter in an `FnDecl`?
|
/// Is `self` allowed semantically as the first parameter in an `FnDecl`?
|
||||||
enum SelfSemantic {
|
enum SelfSemantic {
|
||||||
@ -46,27 +46,12 @@ enum SelfSemantic {
|
|||||||
No,
|
No,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// What is the context that prevents using `~const`?
|
enum TraitOrTraitImpl {
|
||||||
// FIXME(effects): Consider getting rid of this in favor of `errors::TildeConstReason`, they're
|
|
||||||
// almost identical. This gets rid of an abstraction layer which might be considered bad.
|
|
||||||
enum DisallowTildeConstContext<'a> {
|
|
||||||
TraitObject,
|
|
||||||
Fn(FnKind<'a>),
|
|
||||||
Trait(Span),
|
|
||||||
TraitImpl(Span),
|
|
||||||
Impl(Span),
|
|
||||||
TraitAssocTy(Span),
|
|
||||||
TraitImplAssocTy(Span),
|
|
||||||
InherentAssocTy(Span),
|
|
||||||
Item,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum TraitOrTraitImpl<'a> {
|
|
||||||
Trait { span: Span, constness: Option<Span> },
|
Trait { span: Span, constness: Option<Span> },
|
||||||
TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref: &'a TraitRef },
|
TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref: Span },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TraitOrTraitImpl<'a> {
|
impl TraitOrTraitImpl {
|
||||||
fn constness(&self) -> Option<Span> {
|
fn constness(&self) -> Option<Span> {
|
||||||
match self {
|
match self {
|
||||||
Self::Trait { constness: Some(span), .. }
|
Self::Trait { constness: Some(span), .. }
|
||||||
@ -81,9 +66,9 @@ struct AstValidator<'a> {
|
|||||||
features: &'a Features,
|
features: &'a Features,
|
||||||
|
|
||||||
/// The span of the `extern` in an `extern { ... }` block, if any.
|
/// The span of the `extern` in an `extern { ... }` block, if any.
|
||||||
extern_mod: Option<&'a Item>,
|
extern_mod: Option<Span>,
|
||||||
|
|
||||||
outer_trait_or_trait_impl: Option<TraitOrTraitImpl<'a>>,
|
outer_trait_or_trait_impl: Option<TraitOrTraitImpl>,
|
||||||
|
|
||||||
has_proc_macro_decls: bool,
|
has_proc_macro_decls: bool,
|
||||||
|
|
||||||
@ -92,7 +77,7 @@ struct AstValidator<'a> {
|
|||||||
/// e.g., `impl Iterator<Item = impl Debug>`.
|
/// e.g., `impl Iterator<Item = impl Debug>`.
|
||||||
outer_impl_trait: Option<Span>,
|
outer_impl_trait: Option<Span>,
|
||||||
|
|
||||||
disallow_tilde_const: Option<DisallowTildeConstContext<'a>>,
|
disallow_tilde_const: Option<TildeConstReason>,
|
||||||
|
|
||||||
/// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
|
/// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
|
||||||
/// or `Foo::Bar<impl Trait>`
|
/// or `Foo::Bar<impl Trait>`
|
||||||
@ -115,7 +100,7 @@ fn with_in_trait_impl(
|
|||||||
trait_.map(|(constness, polarity, trait_ref)| TraitOrTraitImpl::TraitImpl {
|
trait_.map(|(constness, polarity, trait_ref)| TraitOrTraitImpl::TraitImpl {
|
||||||
constness,
|
constness,
|
||||||
polarity,
|
polarity,
|
||||||
trait_ref,
|
trait_ref: trait_ref.path.span,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
f(self);
|
f(self);
|
||||||
@ -145,7 +130,7 @@ fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
|
|||||||
|
|
||||||
fn with_tilde_const(
|
fn with_tilde_const(
|
||||||
&mut self,
|
&mut self,
|
||||||
disallowed: Option<DisallowTildeConstContext<'a>>,
|
disallowed: Option<TildeConstReason>,
|
||||||
f: impl FnOnce(&mut Self),
|
f: impl FnOnce(&mut Self),
|
||||||
) {
|
) {
|
||||||
let old = mem::replace(&mut self.disallow_tilde_const, disallowed);
|
let old = mem::replace(&mut self.disallow_tilde_const, disallowed);
|
||||||
@ -224,7 +209,7 @@ fn walk_ty(&mut self, t: &'a Ty) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TyKind::TraitObject(..) => self
|
TyKind::TraitObject(..) => self
|
||||||
.with_tilde_const(Some(DisallowTildeConstContext::TraitObject), |this| {
|
.with_tilde_const(Some(TildeConstReason::TraitObject), |this| {
|
||||||
visit::walk_ty(this, t)
|
visit::walk_ty(this, t)
|
||||||
}),
|
}),
|
||||||
TyKind::Path(qself, path) => {
|
TyKind::Path(qself, path) => {
|
||||||
@ -354,7 +339,7 @@ fn deny_unnamed_field(&self, field: &FieldDef) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrTraitImpl<'a>) {
|
fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrTraitImpl) {
|
||||||
let Const::Yes(span) = constness else {
|
let Const::Yes(span) = constness else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@ -367,7 +352,7 @@ fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrTraitImpl<'
|
|||||||
..
|
..
|
||||||
} = parent
|
} = parent
|
||||||
{
|
{
|
||||||
Some(trait_ref.path.span.shrink_to_lo())
|
Some(trait_ref.shrink_to_lo())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -579,7 +564,7 @@ fn check_foreign_fn_bodyless(&self, ident: Ident, body: Option<&Block>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn current_extern_span(&self) -> Span {
|
fn current_extern_span(&self) -> Span {
|
||||||
self.session.source_map().guess_head_span(self.extern_mod.unwrap().span)
|
self.session.source_map().guess_head_span(self.extern_mod.unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An `fn` in `extern { ... }` cannot have qualifiers, e.g. `async fn`.
|
/// An `fn` in `extern { ... }` cannot have qualifiers, e.g. `async fn`.
|
||||||
@ -980,7 +965,7 @@ fn visit_item(&mut self, item: &'a Item) {
|
|||||||
this.visit_vis(&item.vis);
|
this.visit_vis(&item.vis);
|
||||||
this.visit_ident(item.ident);
|
this.visit_ident(item.ident);
|
||||||
let disallowed = matches!(constness, Const::No)
|
let disallowed = matches!(constness, Const::No)
|
||||||
.then(|| DisallowTildeConstContext::TraitImpl(item.span));
|
.then(|| TildeConstReason::TraitImpl { span: item.span });
|
||||||
this.with_tilde_const(disallowed, |this| this.visit_generics(generics));
|
this.with_tilde_const(disallowed, |this| this.visit_generics(generics));
|
||||||
this.visit_trait_ref(t);
|
this.visit_trait_ref(t);
|
||||||
this.visit_ty(self_ty);
|
this.visit_ty(self_ty);
|
||||||
@ -1035,7 +1020,7 @@ fn visit_item(&mut self, item: &'a Item) {
|
|||||||
this.visit_vis(&item.vis);
|
this.visit_vis(&item.vis);
|
||||||
this.visit_ident(item.ident);
|
this.visit_ident(item.ident);
|
||||||
this.with_tilde_const(
|
this.with_tilde_const(
|
||||||
Some(DisallowTildeConstContext::Impl(item.span)),
|
Some(TildeConstReason::Impl { span: item.span }),
|
||||||
|this| this.visit_generics(generics),
|
|this| this.visit_generics(generics),
|
||||||
);
|
);
|
||||||
this.visit_ty(self_ty);
|
this.visit_ty(self_ty);
|
||||||
@ -1080,7 +1065,7 @@ fn visit_item(&mut self, item: &'a Item) {
|
|||||||
}
|
}
|
||||||
ItemKind::ForeignMod(ForeignMod { abi, safety, .. }) => {
|
ItemKind::ForeignMod(ForeignMod { abi, safety, .. }) => {
|
||||||
self.with_in_extern_mod(*safety, |this| {
|
self.with_in_extern_mod(*safety, |this| {
|
||||||
let old_item = mem::replace(&mut this.extern_mod, Some(item));
|
let old_item = mem::replace(&mut this.extern_mod, Some(item.span));
|
||||||
this.visibility_not_permitted(
|
this.visibility_not_permitted(
|
||||||
&item.vis,
|
&item.vis,
|
||||||
errors::VisibilityNotPermittedNote::IndividualForeignItems,
|
errors::VisibilityNotPermittedNote::IndividualForeignItems,
|
||||||
@ -1154,7 +1139,7 @@ fn visit_item(&mut self, item: &'a Item) {
|
|||||||
this.visit_ident(item.ident);
|
this.visit_ident(item.ident);
|
||||||
let disallowed = is_const_trait
|
let disallowed = is_const_trait
|
||||||
.is_none()
|
.is_none()
|
||||||
.then(|| DisallowTildeConstContext::Trait(item.span));
|
.then(|| TildeConstReason::Trait { span: item.span });
|
||||||
this.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)
|
||||||
@ -1399,40 +1384,8 @@ fn visit_param_bound(&mut self, bound: &'a GenericBound, ctxt: BoundKind) {
|
|||||||
self.dcx().emit_err(errors::ConstBoundTraitObject { span: trait_ref.span });
|
self.dcx().emit_err(errors::ConstBoundTraitObject { span: trait_ref.span });
|
||||||
}
|
}
|
||||||
(_, BoundConstness::Maybe(span), BoundPolarity::Positive)
|
(_, BoundConstness::Maybe(span), BoundPolarity::Positive)
|
||||||
if let Some(reason) = &self.disallow_tilde_const =>
|
if let Some(reason) = self.disallow_tilde_const =>
|
||||||
{
|
{
|
||||||
let reason = match reason {
|
|
||||||
DisallowTildeConstContext::Fn(FnKind::Closure(..)) => {
|
|
||||||
errors::TildeConstReason::Closure
|
|
||||||
}
|
|
||||||
DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => {
|
|
||||||
errors::TildeConstReason::Function { ident: ident.span }
|
|
||||||
}
|
|
||||||
&DisallowTildeConstContext::Trait(span) => {
|
|
||||||
errors::TildeConstReason::Trait { span }
|
|
||||||
}
|
|
||||||
&DisallowTildeConstContext::TraitImpl(span) => {
|
|
||||||
errors::TildeConstReason::TraitImpl { span }
|
|
||||||
}
|
|
||||||
&DisallowTildeConstContext::Impl(span) => {
|
|
||||||
// FIXME(effects): Consider providing a help message or even a structured
|
|
||||||
// suggestion for moving such bounds to the assoc const fns if available.
|
|
||||||
errors::TildeConstReason::Impl { span }
|
|
||||||
}
|
|
||||||
&DisallowTildeConstContext::TraitAssocTy(span) => {
|
|
||||||
errors::TildeConstReason::TraitAssocTy { span }
|
|
||||||
}
|
|
||||||
&DisallowTildeConstContext::TraitImplAssocTy(span) => {
|
|
||||||
errors::TildeConstReason::TraitImplAssocTy { span }
|
|
||||||
}
|
|
||||||
&DisallowTildeConstContext::InherentAssocTy(span) => {
|
|
||||||
errors::TildeConstReason::InherentAssocTy { span }
|
|
||||||
}
|
|
||||||
DisallowTildeConstContext::TraitObject => {
|
|
||||||
errors::TildeConstReason::TraitObject
|
|
||||||
}
|
|
||||||
DisallowTildeConstContext::Item => errors::TildeConstReason::Item,
|
|
||||||
};
|
|
||||||
self.dcx().emit_err(errors::TildeConstDisallowed { span, reason });
|
self.dcx().emit_err(errors::TildeConstDisallowed { span, reason });
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
@ -1569,7 +1522,10 @@ fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) {
|
|||||||
.and_then(TraitOrTraitImpl::constness)
|
.and_then(TraitOrTraitImpl::constness)
|
||||||
.is_some();
|
.is_some();
|
||||||
|
|
||||||
let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk));
|
let disallowed = (!tilde_const_allowed).then(|| match fk {
|
||||||
|
FnKind::Fn(_, ident, _, _, _, _) => TildeConstReason::Function { ident: ident.span },
|
||||||
|
FnKind::Closure(_, _, _) => TildeConstReason::Closure,
|
||||||
|
});
|
||||||
self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
|
self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1664,12 +1620,12 @@ fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
|
|||||||
AssocItemKind::Type(_) => {
|
AssocItemKind::Type(_) => {
|
||||||
let disallowed = (!parent_is_const).then(|| match self.outer_trait_or_trait_impl {
|
let disallowed = (!parent_is_const).then(|| match self.outer_trait_or_trait_impl {
|
||||||
Some(TraitOrTraitImpl::Trait { .. }) => {
|
Some(TraitOrTraitImpl::Trait { .. }) => {
|
||||||
DisallowTildeConstContext::TraitAssocTy(item.span)
|
TildeConstReason::TraitAssocTy { span: item.span }
|
||||||
}
|
}
|
||||||
Some(TraitOrTraitImpl::TraitImpl { .. }) => {
|
Some(TraitOrTraitImpl::TraitImpl { .. }) => {
|
||||||
DisallowTildeConstContext::TraitImplAssocTy(item.span)
|
TildeConstReason::TraitImplAssocTy { span: item.span }
|
||||||
}
|
}
|
||||||
None => DisallowTildeConstContext::InherentAssocTy(item.span),
|
None => TildeConstReason::InherentAssocTy { span: item.span },
|
||||||
});
|
});
|
||||||
self.with_tilde_const(disallowed, |this| {
|
self.with_tilde_const(disallowed, |this| {
|
||||||
this.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt))
|
this.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt))
|
||||||
@ -1852,7 +1808,7 @@ pub fn check_crate(
|
|||||||
outer_trait_or_trait_impl: None,
|
outer_trait_or_trait_impl: None,
|
||||||
has_proc_macro_decls: false,
|
has_proc_macro_decls: false,
|
||||||
outer_impl_trait: None,
|
outer_impl_trait: None,
|
||||||
disallow_tilde_const: Some(DisallowTildeConstContext::Item),
|
disallow_tilde_const: Some(TildeConstReason::Item),
|
||||||
is_impl_trait_banned: false,
|
is_impl_trait_banned: false,
|
||||||
extern_mod_safety: None,
|
extern_mod_safety: None,
|
||||||
lint_buffer: lints,
|
lint_buffer: lints,
|
||||||
|
@ -612,7 +612,7 @@ pub struct TildeConstDisallowed {
|
|||||||
pub reason: TildeConstReason,
|
pub reason: TildeConstReason,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subdiagnostic)]
|
#[derive(Subdiagnostic, Copy, Clone)]
|
||||||
pub enum TildeConstReason {
|
pub enum TildeConstReason {
|
||||||
#[note(ast_passes_closure)]
|
#[note(ast_passes_closure)]
|
||||||
Closure,
|
Closure,
|
||||||
|
Loading…
Reference in New Issue
Block a user