Skip to content

Consider exposing formatter in display attribute #201

@dtolnay

Description

@dtolnay

For this sort of code today [#175 (comment)]:

#[error("{code}{}", match .message {
    Some(msg) => format!(" - {}", &msg),
    None => "".to_owned(),
})]
SungrowError { code: u16, message: Option<String> },

one might instead write something like this, without any String allocation:

#[error(formatter, {
    write!(formatter, "{code}")?;
    if let Some(msg) = message {
        write!(formatter, " - {msg}")?;
    }
})]
SungrowError { code: u16, message: Option<String> },

or possibly this:

#[error("{}", |formatter| {
    write!(formatter, "{code}")?;
    if let Some(msg) = message {
        write!(formatter, " - {msg}")?;
    }
})]
SungrowError { code: u16, message: Option<String> },

Unclear whether either of these is that much better than:

#[error("{}", {
    struct Msg<'a>(&'a u16, &'a Option<String>);
    impl Display for Msg<'_> {
        fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
            write!(formatter, "{}", self.0)?;
            if let Some(msg) = self.1 {
                write!(formatter, " - {msg}")?;
            }
            Ok(())
        }
    }
    Msg(.code, .message)
})]
SungrowError { code: u16, message: Option<String> },

or, using an adapter around Fn(&mut fmt::Formatter) -> fmt::Result to trim the boilerplate:

#[error("{}", DisplayFn(|formatter: &mut fmt::Formatter| {
    write!(formatter, "{}", .code)?;
    if let Some(msg) = .message {
        write!(formatter, " - {msg}")?;
    }
    Ok(())
}))]
SungrowError { code: u16, message: Option<String> },
struct DisplayFn<T>(T);

impl<T: Fn(&mut fmt::Formatter) -> fmt::Result> Display for DisplayFn<T> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        (self.0)(formatter)
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions