Skip to content

Commit 9e04a8b

Browse files
Port #[non_exhaustive] to the new attribute parsing infrastructure
Signed-off-by: Jonathan Brouwer <[email protected]>
1 parent 6a35690 commit 9e04a8b

File tree

16 files changed

+91
-43
lines changed

16 files changed

+91
-43
lines changed

compiler/rustc_attr_data_structures/src/attributes.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,9 @@ pub enum AttributeKind {
264264
/// Represents `#[no_mangle]`
265265
NoMangle(Span),
266266

267+
/// Represents `#[non_exhaustive]`
268+
NonExhaustive(Span),
269+
267270
/// Represents `#[optimize(size|speed)]`
268271
Optimize(OptimizeAttr, Span),
269272

compiler/rustc_attr_data_structures/src/encode_cross_crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ impl AttributeKind {
2525
ExportName { .. } => Yes,
2626
Inline(..) => No,
2727
MacroTransparency(..) => Yes,
28+
NonExhaustive(..) => Yes,
2829
Repr(..) => No,
2930
Stability { .. } => Yes,
3031
Cold(..) => No,

compiler/rustc_attr_parsing/src/attributes/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pub(crate) mod inline;
3434
pub(crate) mod lint_helpers;
3535
pub(crate) mod loop_match;
3636
pub(crate) mod must_use;
37+
pub(crate) mod non_exhaustive;
3738
pub(crate) mod repr;
3839
pub(crate) mod semantics;
3940
pub(crate) mod stability;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use rustc_attr_data_structures::AttributeKind;
2+
use rustc_feature::{AttributeTemplate, template};
3+
use rustc_span::{Symbol, sym};
4+
5+
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
6+
use crate::context::{AcceptContext, Stage};
7+
use crate::parser::ArgParser;
8+
9+
pub(crate) struct NonExhaustiveParser;
10+
11+
impl<S: Stage> SingleAttributeParser<S> for NonExhaustiveParser {
12+
const PATH: &[Symbol] = &[sym::non_exhaustive];
13+
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast;
14+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
15+
16+
const TEMPLATE: AttributeTemplate = template!(Word);
17+
18+
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
19+
if let Err(span) = args.no_args() {
20+
cx.expected_no_args(span);
21+
return None;
22+
}
23+
Some(AttributeKind::NonExhaustive(cx.attr_span))
24+
}
25+
}

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
2424
use crate::attributes::lint_helpers::{AsPtrParser, PubTransparentParser};
2525
use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
2626
use crate::attributes::must_use::MustUseParser;
27+
use crate::attributes::non_exhaustive::NonExhaustiveParser;
2728
use crate::attributes::repr::{AlignParser, ReprParser};
2829
use crate::attributes::semantics::MayDangleParser;
2930
use crate::attributes::stability::{
@@ -123,6 +124,7 @@ attribute_parsers!(
123124
Single<MayDangleParser>,
124125
Single<MustUseParser>,
125126
Single<NoMangleParser>,
127+
Single<NonExhaustiveParser>,
126128
Single<OptimizeParser>,
127129
Single<PubTransparentParser>,
128130
Single<RustcForceInlineParser>,

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,9 +1057,11 @@ fn lower_variant<'tcx>(
10571057
fields,
10581058
parent_did.to_def_id(),
10591059
recovered,
1060-
adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, sym::non_exhaustive)
1061-
|| variant_did
1062-
.is_some_and(|variant_did| tcx.has_attr(variant_did, sym::non_exhaustive)),
1060+
adt_kind == AdtKind::Struct
1061+
&& find_attr!(tcx.get_all_attrs(parent_did), AttributeKind::NonExhaustive(..))
1062+
|| variant_did.is_some_and(|variant_did| {
1063+
find_attr!(tcx.get_all_attrs(variant_did), AttributeKind::NonExhaustive(..))
1064+
}),
10631065
)
10641066
}
10651067

compiler/rustc_middle/src/ty/adt.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::ops::Range;
44
use std::str;
55

66
use rustc_abi::{FIRST_VARIANT, ReprOptions, VariantIdx};
7+
use rustc_attr_data_structures::{AttributeKind, find_attr};
78
use rustc_data_structures::fingerprint::Fingerprint;
89
use rustc_data_structures::fx::FxHashMap;
910
use rustc_data_structures::intern::Interned;
@@ -278,7 +279,9 @@ impl AdtDefData {
278279
debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
279280
let mut flags = AdtFlags::NO_ADT_FLAGS;
280281

281-
if kind == AdtKind::Enum && tcx.has_attr(did, sym::non_exhaustive) {
282+
if kind == AdtKind::Enum
283+
&& find_attr!(tcx.get_all_attrs(did), AttributeKind::NonExhaustive(..))
284+
{
282285
debug!("found non-exhaustive variant list for {:?}", did);
283286
flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
284287
}

compiler/rustc_parse/src/validate_attr.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ fn emit_malformed_attribute(
300300
| sym::cold
301301
| sym::naked
302302
| sym::no_mangle
303+
| sym::non_exhaustive
303304
| sym::must_use
304305
| sym::track_caller
305306
) {

compiler/rustc_passes/src/check_attr.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
183183
Attribute::Parsed(AttributeKind::TrackCaller(attr_span)) => {
184184
self.check_track_caller(hir_id, *attr_span, attrs, span, target)
185185
}
186+
Attribute::Parsed(AttributeKind::NonExhaustive(attr_span)) => {
187+
self.check_non_exhaustive(hir_id, *attr_span, span, target, item)
188+
}
186189
Attribute::Parsed(
187190
AttributeKind::BodyStability { .. }
188191
| AttributeKind::ConstStabilityIndirect
@@ -213,7 +216,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
213216
[sym::no_sanitize, ..] => {
214217
self.check_no_sanitize(attr, span, target)
215218
}
216-
[sym::non_exhaustive, ..] => self.check_non_exhaustive(hir_id, attr, span, target, item),
217219
[sym::marker, ..] => self.check_marker(hir_id, attr, span, target),
218220
[sym::target_feature, ..] => {
219221
self.check_target_feature(hir_id, attr, span, target, attrs)
@@ -749,7 +751,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
749751
fn check_non_exhaustive(
750752
&self,
751753
hir_id: HirId,
752-
attr: &Attribute,
754+
attr_span: Span,
753755
span: Span,
754756
target: Target,
755757
item: Option<ItemLike<'_>>,
@@ -764,7 +766,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
764766
&& fields.iter().any(|f| f.default.is_some())
765767
{
766768
self.dcx().emit_err(errors::NonExhaustiveWithDefaultFieldValues {
767-
attr_span: attr.span(),
769+
attr_span,
768770
defn_span: span,
769771
});
770772
}
@@ -775,13 +777,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
775777
// erroneously allowed it and some crates used it accidentally, to be compatible
776778
// with crates depending on them, we can't throw an error here.
777779
Target::Field | Target::Arm | Target::MacroDef => {
778-
self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "non_exhaustive");
780+
self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "non_exhaustive");
779781
}
780782
_ => {
781-
self.dcx().emit_err(errors::NonExhaustiveWrongLocation {
782-
attr_span: attr.span(),
783-
defn_span: span,
784-
});
783+
self.dcx()
784+
.emit_err(errors::NonExhaustiveWrongLocation { attr_span, defn_span: span });
785785
}
786786
}
787787
}

compiler/rustc_resolve/src/diagnostics.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_ast::{
55
self as ast, CRATE_NODE_ID, Crate, ItemKind, MetaItemInner, MetaItemKind, ModKind, NodeId, Path,
66
};
77
use rustc_ast_pretty::pprust;
8-
use rustc_attr_data_structures::{self as attr, Stability};
8+
use rustc_attr_data_structures::{self as attr, AttributeKind, Stability, find_attr};
99
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1010
use rustc_data_structures::unord::{UnordMap, UnordSet};
1111
use rustc_errors::codes::*;
@@ -1998,9 +1998,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
19981998
// Otherwise, point out if the struct has any private fields.
19991999
if let Some(def_id) = res.opt_def_id()
20002000
&& !def_id.is_local()
2001-
&& let Some(attr) = self.tcx.get_attr(def_id, sym::non_exhaustive)
2001+
&& let Some(attr_span) = find_attr!(self.tcx.get_all_attrs(def_id), AttributeKind::NonExhaustive(span) => *span)
20022002
{
2003-
non_exhaustive = Some(attr.span());
2003+
non_exhaustive = Some(attr_span);
20042004
} else if let Some(span) = ctor_fields_span {
20052005
let label = errors::ConstructorPrivateIfAnyFieldPrivate { span };
20062006
err.subdiagnostic(label);

0 commit comments

Comments
 (0)