Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix unsized fields usage in derive(Display) (#432) #440

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

tyranron
Copy link
Collaborator

@tyranron tyranron commented Jan 19, 2025

Resolves #432

Synopsis

See #432 (comment):

use derive_more::Display;

#[derive(Display, Debug)]
#[display("{head}.{tail}")]
struct Struct {
    head: char,
    tail: str,
}

fn main() {
    let dat = [51i32, 3028017];
    let s = unsafe { &*(&raw const dat as *const [i32] as *const Struct) };
    println!("{:?}", s);
    println!("{}", s);
}

The derived Debug impl prints Struct { head: '3', tail: "14" } but the Display impl does not compile.

error[E0277]: the size for values of type `str` cannot be known at compilation time
   --> src/main.rs:3:10
    |
3   | #[derive(Display, Debug)]
    |          ^^^^^^^ doesn't have a size known at compile-time
4   | #[display("{head}.{tail}")]
    |                   ------ required by a bound introduced by this call
    |
    = help: the trait `Sized` is not implemented for `str`
note: required by an implicit `Sized` bound in `derive_more::core::fmt::rt::Argument::<'_>::new_display`
   --> $RUSTUP_HOME/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/fmt/rt.rs:113:24
    |
113 |     pub fn new_display<T: Display>(x: &T) -> Argument<'_> {
    |                        ^ required by the implicit `Sized` requirement on this type parameter in `Argument::<'_>::new_display`
    = note: this error originates in the macro `$crate::format_args` which comes from the expansion of the derive macro `Display` (in Nightly builds, run with -Z macro-backtrace for more info)

The problem is introduced by #381, and its cause is that the FmtAttribute::additional_deref_args() implementation is too aggressive and is enabled for any fmt trait, not just fmt::Pointer.

#[allow(unreachable_code)]
#[automatically_derived]
impl derive_more::core::fmt::Display for Struct2 {
    fn fmt(&self, __derive_more_f: &mut derive_more::core::fmt::Formatter<'_>) -> derive_more::core::fmt::Result {
        let head = &self.head;
        let tail = &self.tail;
        derive_more::core::write!(__derive_more_f, "{head}.{tail}", head = *head, tail = *tail)
    }
}

Solution

Apply FmtAttribute::additional_deref_args() only for fmt::Pointer placeholders.

Checklist

  • Documentation is updated (not required)
  • Tests are added/updated
  • CHANGELOG entry is added

@tyranron tyranron added this to the 2.0.0 milestone Jan 19, 2025
@tyranron tyranron self-assigned this Jan 19, 2025
@tyranron tyranron marked this pull request as ready for review January 19, 2025 17:42
@tyranron tyranron enabled auto-merge (squash) January 19, 2025 17:44
@tyranron tyranron requested a review from JelteF January 19, 2025 17:44
@tyranron
Copy link
Collaborator Author

@JelteF after merging this, we can finally cut the 2.0.0 release! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unsized tail fields in derive(Display)
1 participant