Skip to content

Commit 5456cdd

Browse files
authored
Unrolled build for rust-lang#134539
Rollup merge of rust-lang#134539 - estebank:restrict-non_exhaustive, r=jieyouxu Restrict `#[non_exaustive]` on structs with default field values Do not allow users to apply `#[non_exaustive]` to a struct when they have also used default field values.
2 parents 5f23ef7 + b3cc9b9 commit 5456cdd

File tree

5 files changed

+78
-3
lines changed

5 files changed

+78
-3
lines changed

compiler/rustc_passes/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,10 @@ passes_no_sanitize =
566566
`#[no_sanitize({$attr_str})]` should be applied to {$accepted_kind}
567567
.label = not {$accepted_kind}
568568
569+
passes_non_exaustive_with_default_field_values =
570+
`#[non_exhaustive]` can't be used to annotate items with default field values
571+
.label = this struct has default field values
572+
569573
passes_non_exported_macro_invalid_attrs =
570574
attribute should be applied to function or closure
571575
.label = not a function or closure

compiler/rustc_passes/src/check_attr.rs

+24-3
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
124124
[sym::coverage, ..] => self.check_coverage(attr, span, target),
125125
[sym::optimize, ..] => self.check_optimize(hir_id, attr, span, target),
126126
[sym::no_sanitize, ..] => self.check_no_sanitize(attr, span, target),
127-
[sym::non_exhaustive, ..] => self.check_non_exhaustive(hir_id, attr, span, target),
127+
[sym::non_exhaustive, ..] => self.check_non_exhaustive(hir_id, attr, span, target, item),
128128
[sym::marker, ..] => self.check_marker(hir_id, attr, span, target),
129129
[sym::target_feature, ..] => {
130130
self.check_target_feature(hir_id, attr, span, target, attrs)
@@ -685,9 +685,30 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
685685
}
686686

687687
/// Checks if the `#[non_exhaustive]` attribute on an `item` is valid.
688-
fn check_non_exhaustive(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
688+
fn check_non_exhaustive(
689+
&self,
690+
hir_id: HirId,
691+
attr: &Attribute,
692+
span: Span,
693+
target: Target,
694+
item: Option<ItemLike<'_>>,
695+
) {
689696
match target {
690-
Target::Struct | Target::Enum | Target::Variant => {}
697+
Target::Struct => {
698+
if let Some(ItemLike::Item(hir::Item {
699+
kind: hir::ItemKind::Struct(hir::VariantData::Struct { fields, .. }, _),
700+
..
701+
})) = item
702+
&& !fields.is_empty()
703+
&& fields.iter().any(|f| f.default.is_some())
704+
{
705+
self.dcx().emit_err(errors::NonExhaustiveWithDefaultFieldValues {
706+
attr_span: attr.span,
707+
defn_span: span,
708+
});
709+
}
710+
}
711+
Target::Enum | Target::Variant => {}
691712
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
692713
// `#[non_exhaustive]` attribute with just a lint, because we previously
693714
// erroneously allowed it and some crates used it accidentally, to be compatible

compiler/rustc_passes/src/errors.rs

+9
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,15 @@ pub(crate) struct NonExhaustiveWrongLocation {
119119
pub defn_span: Span,
120120
}
121121

122+
#[derive(Diagnostic)]
123+
#[diag(passes_non_exaustive_with_default_field_values)]
124+
pub(crate) struct NonExhaustiveWithDefaultFieldValues {
125+
#[primary_span]
126+
pub attr_span: Span,
127+
#[label]
128+
pub defn_span: Span,
129+
}
130+
122131
#[derive(Diagnostic)]
123132
#[diag(passes_should_be_applied_to_trait)]
124133
pub(crate) struct AttrShouldBeAppliedToTrait {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#![feature(default_field_values)]
2+
3+
#[derive(Default)]
4+
#[non_exhaustive] //~ ERROR `#[non_exhaustive]` can't be used to annotate items with default field values
5+
struct Foo {
6+
x: i32 = 42 + 3,
7+
}
8+
9+
#[derive(Default)]
10+
enum Bar {
11+
#[non_exhaustive]
12+
#[default]
13+
Baz { //~ ERROR default variant must be exhaustive
14+
x: i32 = 42 + 3,
15+
}
16+
}
17+
18+
fn main () {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error: default variant must be exhaustive
2+
--> $DIR/default-field-values-non_exhaustive.rs:13:5
3+
|
4+
LL | #[non_exhaustive]
5+
| ----------------- declared `#[non_exhaustive]` here
6+
LL | #[default]
7+
LL | Baz {
8+
| ^^^
9+
|
10+
= help: consider a manual implementation of `Default`
11+
12+
error: `#[non_exhaustive]` can't be used to annotate items with default field values
13+
--> $DIR/default-field-values-non_exhaustive.rs:4:1
14+
|
15+
LL | #[non_exhaustive]
16+
| ^^^^^^^^^^^^^^^^^
17+
LL | / struct Foo {
18+
LL | | x: i32 = 42 + 3,
19+
LL | | }
20+
| |_- this struct has default field values
21+
22+
error: aborting due to 2 previous errors
23+

0 commit comments

Comments
 (0)