Skip to content

Commit 50d96c7

Browse files
committed
Refactor AST validator
1 parent 8eb7a14 commit 50d96c7

File tree

1 file changed

+52
-53
lines changed

1 file changed

+52
-53
lines changed

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 52 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -46,27 +46,33 @@ enum DisallowTildeConstContext<'a> {
4646
Item,
4747
}
4848

49+
enum TraitOrImpl<'a> {
50+
Trait { span: Span, constness: Option<Span> },
51+
Impl { trait_: Option<(Const, ImplPolarity, &'a TraitRef)> },
52+
}
53+
54+
impl<'a> TraitOrImpl<'a> {
55+
fn constness(&self) -> Option<Span> {
56+
match self {
57+
Self::Trait { constness: Some(span), .. }
58+
| Self::Impl { trait_: Some((Const::Yes(span), ..)) } => Some(*span),
59+
_ => None,
60+
}
61+
}
62+
63+
fn is_trait_or_trait_impl(&self) -> bool {
64+
matches!(self, Self::Trait { .. } | Self::Impl { trait_: Some(_) })
65+
}
66+
}
67+
4968
struct AstValidator<'a> {
5069
session: &'a Session,
5170
features: &'a Features,
5271

5372
/// The span of the `extern` in an `extern { ... }` block, if any.
5473
extern_mod: Option<&'a Item>,
5574

56-
/// Are we inside a trait impl?
57-
///
58-
/// If so, this is the trait ref together with its polarity.
59-
in_trait_impl: Option<(ImplPolarity, &'a TraitRef)>,
60-
61-
/// Are we inside a const trait defn or impl?
62-
///
63-
/// If so, this is the span of the constness.
64-
in_const_trait_or_impl: Option<Span>,
65-
66-
/// Are we inside a trait?
67-
///
68-
/// If so, this is the span of the trait.
69-
in_trait: Option<Span>,
75+
outer_trait_or_impl: Option<TraitOrImpl<'a>>,
7076

7177
has_proc_macro_decls: bool,
7278

@@ -87,31 +93,24 @@ struct AstValidator<'a> {
8793
impl<'a> AstValidator<'a> {
8894
fn with_in_trait_impl(
8995
&mut self,
90-
trait_ref: Option<(Const, ImplPolarity, &'a TraitRef)>,
96+
trait_: Option<(Const, ImplPolarity, &'a TraitRef)>,
9197
f: impl FnOnce(&mut Self),
9298
) {
9399
let old = mem::replace(
94-
&mut self.in_trait_impl,
95-
trait_ref.map(|(_, polarity, trait_ref)| (polarity, trait_ref)),
96-
);
97-
let old_const = mem::replace(
98-
&mut self.in_const_trait_or_impl,
99-
match trait_ref {
100-
Some((Const::Yes(span), ..)) => Some(span),
101-
_ => None,
102-
},
100+
&mut self.outer_trait_or_impl,
101+
trait_.map(|trait_| TraitOrImpl::Impl { trait_: Some(trait_) }),
103102
);
104103
f(self);
105-
self.in_trait_impl = old;
106-
self.in_const_trait_or_impl = old_const;
104+
self.outer_trait_or_impl = old;
107105
}
108106

109-
fn with_in_trait(&mut self, span: Span, is_const: Option<Span>, f: impl FnOnce(&mut Self)) {
110-
let old = mem::replace(&mut self.in_const_trait_or_impl, is_const);
111-
let old_trait = mem::replace(&mut self.in_trait, Some(span));
107+
fn with_in_trait(&mut self, span: Span, constness: Option<Span>, f: impl FnOnce(&mut Self)) {
108+
let old = mem::replace(
109+
&mut self.outer_trait_or_impl,
110+
Some(TraitOrImpl::Trait { span, constness }),
111+
);
112112
f(self);
113-
self.in_const_trait_or_impl = old;
114-
self.in_trait = old_trait;
113+
self.outer_trait_or_impl = old;
115114
}
116115

117116
fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
@@ -307,36 +306,36 @@ impl<'a> AstValidator<'a> {
307306
}
308307
}
309308

310-
fn check_trait_fn_not_const(&self, constness: Const) {
309+
fn check_trait_fn_not_const(&self, constness: Const, trait_or_impl: &TraitOrImpl<'a>) {
311310
let Const::Yes(span) = constness else {
312311
return;
313312
};
314313

315-
let make_impl_const_sugg = if self.in_const_trait_or_impl.is_none()
316-
&& let Some((ImplPolarity::Positive, trait_ref)) = self.in_trait_impl
317-
&& self.features.const_trait_impl
314+
let make_impl_const_sugg = if self.features.const_trait_impl
315+
&& let TraitOrImpl::Impl { trait_: Some(trait_) } = trait_or_impl
316+
&& let (Const::No, ImplPolarity::Positive, trait_ref) = trait_
318317
{
319318
Some(trait_ref.path.span.shrink_to_lo())
320319
} else {
321320
None
322321
};
323322

324-
let make_trait_const_sugg = if self.in_const_trait_or_impl.is_none()
325-
&& let Some(trait_) = self.in_trait
326-
&& self.features.const_trait_impl
323+
let make_trait_const_sugg = if self.features.const_trait_impl
324+
&& let TraitOrImpl::Trait { span, constness: None } = trait_or_impl
327325
{
328-
Some(trait_.shrink_to_lo())
326+
Some(span.shrink_to_lo())
329327
} else {
330328
None
331329
};
332330

331+
let parent_constness = trait_or_impl.constness();
333332
self.dcx().emit_err(errors::TraitFnConst {
334333
span,
335-
in_impl: self.in_trait_impl.is_some(),
336-
const_context_label: self.in_const_trait_or_impl,
334+
in_impl: matches!(trait_or_impl, TraitOrImpl::Impl { .. }),
335+
const_context_label: parent_constness,
337336
remove_const_sugg: (
338337
self.session.source_map().span_extend_while(span, |c| c == ' ').unwrap_or(span),
339-
match self.in_const_trait_or_impl {
338+
match parent_constness {
340339
Some(_) => rustc_errors::Applicability::MachineApplicable,
341340
None => rustc_errors::Applicability::MaybeIncorrect,
342341
},
@@ -1391,10 +1390,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
13911390
});
13921391
}
13931392

1394-
let tilde_const_allowed = matches!(
1395-
fk.header(),
1396-
Some(FnHeader { constness: ast::Const::Yes(_), .. })
1397-
) || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)) if self.in_const_trait_or_impl.is_some());
1393+
let tilde_const_allowed =
1394+
matches!(fk.header(), Some(FnHeader { constness: ast::Const::Yes(_), .. }))
1395+
|| matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)))
1396+
&& self.outer_trait_or_impl.as_ref().and_then(TraitOrImpl::constness).is_some();
13981397

13991398
let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk));
14001399
self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
@@ -1405,7 +1404,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14051404
self.check_nomangle_item_asciionly(item.ident, item.span);
14061405
}
14071406

1408-
if ctxt == AssocCtxt::Trait || self.in_trait_impl.is_none() {
1407+
if self.outer_trait_or_impl.as_ref().is_some_and(TraitOrImpl::is_trait_or_trait_impl) {
14091408
self.check_defaultness(item.span, item.kind.defaultness());
14101409
}
14111410

@@ -1453,10 +1452,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14531452
);
14541453
}
14551454

1456-
if ctxt == AssocCtxt::Trait || self.in_trait_impl.is_some() {
1455+
if let Some(trait_or_impl) = &self.outer_trait_or_impl
1456+
&& trait_or_impl.is_trait_or_trait_impl()
1457+
{
14571458
self.visibility_not_permitted(&item.vis, errors::VisibilityNotPermittedNote::TraitImpl);
14581459
if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
1459-
self.check_trait_fn_not_const(sig.header.constness);
1460+
self.check_trait_fn_not_const(sig.header.constness, trait_or_impl);
14601461
}
14611462
}
14621463

@@ -1466,7 +1467,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14661467

14671468
match &item.kind {
14681469
AssocItemKind::Fn(box Fn { sig, generics, body, .. })
1469-
if self.in_const_trait_or_impl.is_some()
1470+
if self.outer_trait_or_impl.as_ref().and_then(TraitOrImpl::constness).is_some()
14701471
|| ctxt == AssocCtxt::Trait
14711472
|| matches!(sig.header.constness, Const::Yes(_)) =>
14721473
{
@@ -1598,9 +1599,7 @@ pub fn check_crate(
15981599
session,
15991600
features,
16001601
extern_mod: None,
1601-
in_trait_impl: None,
1602-
in_const_trait_or_impl: None,
1603-
in_trait: None,
1602+
outer_trait_or_impl: None,
16041603
has_proc_macro_decls: false,
16051604
outer_impl_trait: None,
16061605
disallow_tilde_const: Some(DisallowTildeConstContext::Item),

0 commit comments

Comments
 (0)