about summary refs log tree commit diff
path: root/compiler/rustc_builtin_macros
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2024-12-06 19:50:55 +0000
committerEsteban Küber <esteban@kuber.com.ar>2024-12-09 21:55:13 +0000
commit2d6e763cc68b2433b9df33da2a80dc4cf4953079 (patch)
tree15e2a09329bafd5af83abeccb807d61ddb60e370 /compiler/rustc_builtin_macros
parent148a77dfde03dba553b2e4f3cf817cd6d105b3e6 (diff)
downloadrust-2d6e763cc68b2433b9df33da2a80dc4cf4953079.tar.gz
rust-2d6e763cc68b2433b9df33da2a80dc4cf4953079.zip
Disallow `#[default] Variant {}` regardless of feature flag
Diffstat (limited to 'compiler/rustc_builtin_macros')
-rw-r--r--compiler/rustc_builtin_macros/messages.ftl2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/default.rs16
-rw-r--r--compiler/rustc_builtin_macros/src/errors.rs1
3 files changed, 16 insertions, 3 deletions
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index c05d44cb452..87d3d288013 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -261,7 +261,7 @@ builtin_macros_non_exhaustive_default = default variant must be exhaustive
 
 builtin_macros_non_generic_pointee = the `#[pointee]` attribute may only be used on generic parameters
 
-builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants
+builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants{$post}
     .help = consider a manual implementation of `Default`
 
 builtin_macros_only_one_argument = {$name} takes 1 argument
diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs
index 12d5587b5db..6b1a6effad7 100644
--- a/compiler/rustc_builtin_macros/src/deriving/default.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/default.rs
@@ -199,10 +199,17 @@ fn extract_default_variant<'a>(
     if cx.ecfg.features.default_field_values()
         && let VariantData::Struct { fields, .. } = &variant.data
         && fields.iter().all(|f| f.default.is_some())
+        // Disallow `#[default] Variant {}`
+        && !fields.is_empty()
     {
         // Allowed
     } else if !matches!(variant.data, VariantData::Unit(..)) {
-        let guar = cx.dcx().emit_err(errors::NonUnitDefault { span: variant.ident.span });
+        let post = if cx.ecfg.features.default_field_values() {
+            " or variants where every field has a default value"
+        } else {
+            ""
+        };
+        let guar = cx.dcx().emit_err(errors::NonUnitDefault { span: variant.ident.span, post });
         return Err(guar);
     }
 
@@ -261,7 +268,12 @@ struct DetectNonVariantDefaultAttr<'a, 'b> {
 impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, 'b> {
     fn visit_attribute(&mut self, attr: &'a rustc_ast::Attribute) {
         if attr.has_name(kw::Default) {
-            self.cx.dcx().emit_err(errors::NonUnitDefault { span: attr.span });
+            let post = if self.cx.ecfg.features.default_field_values() {
+                " or variants where every field has a default value"
+            } else {
+                ""
+            };
+            self.cx.dcx().emit_err(errors::NonUnitDefault { span: attr.span, post });
         }
 
         rustc_ast::visit::walk_attribute(self, attr);
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index f8e65661e52..c9bd3371e55 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -424,6 +424,7 @@ pub(crate) struct MultipleDefaultsSugg {
 pub(crate) struct NonUnitDefault {
     #[primary_span]
     pub(crate) span: Span,
+    pub(crate) post: &'static str,
 }
 
 #[derive(Diagnostic)]