How can I handle Option and non-Option types in a function that requires Display?

⚓ Rust    📅 2025-10-30    👤 surdeus    👁️ 6      

surdeus

Warning

This post was published 33 days ago. The information described in this article may have changed.

I have a generic function with a trait bound on Display

fn display_all<T>(items: BTreeMap<T, i32>)
where T: std::fmt::Display

Now I'd like to pass Option and non-Option types to it. But of course, Option doesn't implement Display, so this doesn't work.

let mut non_opt = BTreeMap::new();
non_opt.insert("One", 1);
  
let mut opt = BTreeMap::new();
opt.insert(Some("Two".to_string()), 2);
  
display_all(non_opt);
display_all(opt);

Ideally, a default value should be used if a value is none. I'm unsure wheter the default value should be provided by the caller or the callee, but I'm currently leaning towards the latter. I've tried a wrapper trait, but this also doesn't work: "conflicting implementations of trait DisplayOption for type std::option::Option<_>"

pub trait DisplayOption {
    fn to_string(&self) -> String;
}

impl<T: std::fmt::Display> DisplayOption for T {
    fn to_string(&self) -> String {
        std::string::ToString::to_string(&self)
    }
}

impl<T: std::fmt::Display> DisplayOption for Option<T> {
    fn to_string(&self) -> String {
        match self {
            Some(t) => std::string::ToString::to_string(&t),
            None => "None".to_string(),
        }
    }
}

If I remove the implementation for T the code works. It's just that now I need to implement Display and DisplayOption for the types I want to pass to the function, which creates annoying boilerplate. So I'd like to know if there is a better solution.

What's a good way to proceed here?

9 posts - 4 participants

Read full topic

🏷️ Rust_feed