Skip to content

Commit 983875f

Browse files
authored
Allow using enum-level attributes for non-Display formatting traits as default (#495, #142)
## Synopsis Allow using enum level attributes for non-`Display` formatting traits as default. This behavior was already [documented](https://docs.rs/derive_more/latest/derive_more/derive.Display.html#shared-enum-format), but did not compile yet due to a too eager validation. ## Solution Remove overly zealous validation of input. ```rust #[derive(LowerHex)] #[lower_hex("default")] enum Enum { UsesDefault, // will format as `default` #[lower_hex("custom")] Custom, // will format as `custom` } ```
1 parent 2d3805b commit 983875f

File tree

5 files changed

+85
-10
lines changed

5 files changed

+85
-10
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
6060
- Dependency on unstable `feature(error_generic_member_access)` in `Error` derive when
6161
using `Backtrace` on a non-nightly toolchain.
6262
([#513](https://github.com/JelteF/derive_more/pull/513))
63+
- Broken support for `#[<display-trait>("default formatting")]` attribute without `{_variant}`
64+
being used as default for enum variants without explicit formatting.
65+
([#495](https://github.com/JelteF/derive_more/pull/495))
6366

6467
## 2.0.1 - 2025-02-03
6568

impl/src/fmt/display.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -260,15 +260,27 @@ fn expand_enum(
260260

261261
if attrs.common.fmt.is_none()
262262
&& variant.fields.is_empty()
263-
&& attr_name != "display"
264-
{
265-
return Err(syn::Error::new(
266-
e.variants.span(),
267-
format!(
268-
"implicit formatting of unit enum variant is supported only for `Display` \
269-
macro, use `#[{attr_name}(\"...\")]` to explicitly specify the formatting",
270-
),
271-
));
263+
&& attr_name != "display" {
264+
let container_fmt = container_attrs.common.fmt.as_ref();
265+
if container_fmt.is_none() {
266+
return Err(syn::Error::new(
267+
e.variants.span(),
268+
format!(
269+
"implicit formatting of unit enum variant is supported only for \
270+
`Display` macro, use `#[{attr_name}(\"...\")]` to explicitly specify \
271+
the formatting on every variant or the enum",
272+
),
273+
));
274+
} else if container_fmt.is_some_and(|fmt| fmt.contains_arg("_variant")) {
275+
return Err(syn::Error::new_spanned(
276+
variant,
277+
format!(
278+
"implicit formatting of unit enum variant is supported only for \
279+
`Display` macro, use `#[{attr_name}(\"...\")]` to explicitly specify \
280+
the formatting on every variant when using `{{_variant}}`",
281+
),
282+
));
283+
}
272284
}
273285

274286
if let Some(rename_all) = container_attrs.rename_all {

tests/compile_fail/display/non_display_implicit_enum_unit_variant.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,10 @@ enum Enum {
33
UnitVariant,
44
}
55

6+
#[derive(derive_more::Display, derive_more::UpperHex)]
7+
#[upper_hex("default with {_variant}")]
8+
enum EnumWithVariantInFmt {
9+
UnitVariant,
10+
}
11+
612
fn main() {}
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1-
error: implicit formatting of unit enum variant is supported only for `Display` macro, use `#[upper_hex("...")]` to explicitly specify the formatting
1+
error: implicit formatting of unit enum variant is supported only for `Display` macro, use `#[upper_hex("...")]` to explicitly specify the formatting on every variant or the enum
22
--> tests/compile_fail/display/non_display_implicit_enum_unit_variant.rs:3:5
33
|
44
3 | UnitVariant,
55
| ^^^^^^^^^^^
6+
7+
error: implicit formatting of unit enum variant is supported only for `Display` macro, use `#[upper_hex("...")]` to explicitly specify the formatting on every variant when using `{_variant}`
8+
--> tests/compile_fail/display/non_display_implicit_enum_unit_variant.rs:9:5
9+
|
10+
9 | UnitVariant,
11+
| ^^^^^^^^^^^

tests/display.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -992,6 +992,54 @@ mod enums {
992992
}
993993
}
994994
}
995+
996+
mod default {
997+
use super::*;
998+
999+
#[derive(
1000+
Binary, Display, LowerExp, LowerHex, Octal, Pointer, UpperExp, UpperHex
1001+
)]
1002+
#[binary("Binary")]
1003+
#[display("Display")]
1004+
#[lower_exp("LowerExp")]
1005+
#[lower_hex("LowerHex")]
1006+
#[octal("Octal")]
1007+
#[pointer("Pointer")]
1008+
#[upper_exp("UpperExp")]
1009+
#[upper_hex("UpperHex")]
1010+
enum Unit {
1011+
A,
1012+
#[binary("Binary Custom")]
1013+
#[display("Display Custom")]
1014+
#[lower_exp("LowerExp Custom")]
1015+
#[lower_hex("LowerHex Custom")]
1016+
#[octal("Octal Custom")]
1017+
#[pointer("Pointer Custom")]
1018+
#[upper_exp("UpperExp Custom")]
1019+
#[upper_hex("UpperHex Custom")]
1020+
B,
1021+
}
1022+
1023+
#[test]
1024+
fn assert() {
1025+
assert_eq!(format!("{:b}", Unit::A), "Binary");
1026+
assert_eq!(format!("{:b}", Unit::B), "Binary Custom");
1027+
assert_eq!(Unit::A.to_string(), "Display");
1028+
assert_eq!(Unit::B.to_string(), "Display Custom");
1029+
assert_eq!(format!("{:e}", Unit::A), "LowerExp");
1030+
assert_eq!(format!("{:e}", Unit::B), "LowerExp Custom");
1031+
assert_eq!(format!("{:x}", Unit::A), "LowerHex");
1032+
assert_eq!(format!("{:x}", Unit::B), "LowerHex Custom");
1033+
assert_eq!(format!("{:o}", Unit::A), "Octal");
1034+
assert_eq!(format!("{:o}", Unit::B), "Octal Custom");
1035+
assert_eq!(format!("{:p}", Unit::A), "Pointer");
1036+
assert_eq!(format!("{:p}", Unit::B), "Pointer Custom");
1037+
assert_eq!(format!("{:E}", Unit::A), "UpperExp");
1038+
assert_eq!(format!("{:E}", Unit::B), "UpperExp Custom");
1039+
assert_eq!(format!("{:X}", Unit::A), "UpperHex");
1040+
assert_eq!(format!("{:X}", Unit::B), "UpperHex Custom");
1041+
}
1042+
}
9951043
}
9961044

9971045
mod single_field_variant {

0 commit comments

Comments
 (0)