In rust, I want in my impl fmt::Display for MainStruct, to be able to print another struct.
#[derive(Clone, Default)]
pub struct MainStruct {
pub child: Option<ChildStruct>
}
#[derive(Clone, Default)]
pub struct ChildStruct {
pub field: String
}
impl std::fmt::Display for MainStruct {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "MainStruct: child:{}", self.child)
}
}
impl std::fmt::Display for ChildStruct {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "ChildStruct: field:{}", self.field)
}
}
I have tried with the default {} formatter, and with the {:?} formatter, but without any success.
The Problem is that Option<T> has not implemented the Display trait. So you have to get the value out of the option. The easiest to do so is .unwrap(). This however panics if the option is None. (other methods for unpacking are expect, match, …)
If you use .unwrap() the value is moved out of the Option. So the Option would now be invalid as it would not contain anything anymore. The compiler prevents this with an error cannot move out of 'self.child'.
So what you actually want is a reference that does not consume the child. So you want &T or &mut T from the Option. You can do that by using the .as_ref() to convert Option<T> to Option<&T>. Then if you do .unwrap() on that the compiler wont complain anymore as you just copy a &T pointer.
so your code compiles if you change the following:
impl std::fmt::Display for MainStruct {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "MainStruct: child:{}", self.child.as_ref().unwrap())
}
}
Since Option does not implement Display, you have to write some logic yourself to handle two possible cases. The simplest way might be to just match on the Option explicitly:
impl std::fmt::Display for MainStruct {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "MainStruct: child: ")?;
match self.child.as_ref() {
Some(child) => write!(f, "Some({})", child),
None => write!(f, "None"),
}
}
}
Here's the playground with a short test case.
Related
I'm implementing the Debug trait on a trait. I'd like to be able to display the name of the concrete type that implements this particular instance of the trait.
trait Node {
foo: String,
}
impl fmt::Debug for dyn Node {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let name = // get type name of self here
write!(f, "The name: {}", name);
}
}
I've read a number of posts about Any and downcasting and whatnot, but these solutions seem complex.
One possible solution is to add a method to the trait itself: get_name() -> String, and implement it for each struct individually. There has to be a simpler way, though.
We could add a get_name method to Node which returns whatever the name of Self is using std::any::type_name::<Self>().
trait Node {
fn get_name(&self) -> &'static str {
return std::any::type_name::<Self>();
}
}
Inside the Debug implementation we can call self.get_name().
impl fmt::Debug for dyn Node {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let name = self.get_name();
write!(f, "The name: {}", name)
}
}
Printing a dyn Node instance will show the following result:
struct SomeStruct {}
impl Node for SomeStruct {}
fn main() {
let a: Box<dyn Node> = Box::new(SomeStruct {});
println!("{:?}", a)
// The name: playground::SomeStruct
}
Playground
I have some code which returns a trait object of type MyTrait so that it can return one of several different structs. I would like to implement the Display trait for the trait object so that I can print the object, with the details delegated to the various structs as they each need their own custom formatters.
I can achieve this by including a formatting method as part of the MyTrait definition, and then implementing Display for MyTrait and delegating - like this:
trait MyTrait {
fn is_even(&self) -> bool;
fn my_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result;
}
impl fmt::Display for MyTrait {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.my_fmt(f)
}
}
However, I already have the Display trait implemented for each of the structs which implement MyTrait. This means I end up with two methods for each struct which do the same thing - the fmt() method to satisfy the Display trait directly on the struct, and the my_fmt() method which is called by the code above. This seems clumsy and repetitive. Is there a simpler way to do it?
Here's a complete example program which illustrates the point. It's a little longer than I would have liked (it's based on the answer to my previous question Calling functions which return different types with shared trait and pass to other functions), but I couldn't think of a simpler way to illustrate the point. Of course, in this toy example the structs and the fmt functions are very simple; in my real application they are more complex.
use std::fmt;
trait MyTrait {
fn is_even(&self) -> bool;
fn my_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result;
}
struct First {
v: u8,
}
struct Second {
v: Vec<u8>,
}
impl MyTrait for First {
fn is_even(&self) -> bool {
self.v % 2 == 0
}
fn my_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.v)
}
}
impl MyTrait for Second {
fn is_even(&self) -> bool {
self.v[0] % 2 == 0
}
fn my_fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.v[0])
}
}
fn make1() -> First {
First { v: 5 }
}
fn make2() -> Second {
Second { v: vec![2, 3, 5] }
}
// Implement Display for the structs and for MyTrait
impl fmt::Display for First {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.v)
}
}
impl fmt::Display for Second {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.v[0])
}
}
impl fmt::Display for MyTrait {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.my_fmt(f)
}
}
fn requires_mytrait<T: MyTrait + ?Sized>(v: &&T) {
println!("{:?}", v.is_even());
}
fn main() {
for i in 0..2 {
let v1;
let v2;
let v = match i {
0 => {
v1 = make1();
println!("> {}", v1); // Demonstrate that Display
// is implemented directly
// on the type.
&v1 as &MyTrait
}
_ => {
v2 = make2();
println!("> {}", v2); // Demonstrate that Display
// is implemented directly
// on the type.
&v2 as &MyTrait
}
};
requires_mytrait(&v);
println!("{}", v); // Here I print the trait object
}
}
Can anyone suggest a simpler, cleaner way to do this?
You can make Display a supertrait of MyTrait.
trait MyTrait: fmt::Display {
fn is_even(&self) -> bool;
}
This will make trait objects of MyTrait be Display. This only works if you expect all implementors of MyTrait to implement Display, but that was also the case in your previous solution.
It is considered good practice to #[derive(Debug)] for most structs you create to aid in debugging. However, this is not possible if your struct contains a type without Debug, such as traits. But if the trait is under my control, is there something I can do to let users' implementations of said trait show up in the debug message?
I could require that people who implement my trait also implement Debug, but I don't like having to add that arbitrary requirement:
trait MyTrait: Debug { ... }
I could just implement Debug for my trait:
trait MyTrait { ... }
impl Debug for MyTrait {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "MyTrait {{ ... }}")
}
}
This doesn't allow implementations to override Debug - it's almost as if the function is not virtual. How can I make this work?
use std::fmt;
use std::fmt::{ Formatter, Debug };
#[derive(Debug)]
struct A {
a: Box<Data>,
}
trait Data {}
impl Debug for Data {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Data{{ ... }}")
}
}
#[derive(Debug)]
struct B(i32);
impl Data for B {}
fn main() {
let a = A{ a: Box::new(B(42)) };
println!("{:?}", a);
}
Outputs:
A { a: Data{ ... } }
What I want:
A { a: B(42) }
I only want the first output when B does not implement Debug.
You can create your own trait method. Types that wish to have enhanced debugging and implement Debug can delegate:
use std::fmt;
use std::fmt::{ Formatter, Debug };
#[derive(Debug)]
struct Container(Box<Data>);
trait Data {
fn debug_fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Data {{ ... }}")
}
}
impl Debug for Data {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
self.debug_fmt(f)
}
}
#[derive(Debug)]
struct Overrides(i32);
impl Data for Overrides {
fn debug_fmt(&self, f: &mut Formatter) -> fmt::Result {
self.fmt(f)
}
}
#[derive(Debug)]
struct Defaults(i32);
impl Data for Defaults {}
fn main() {
let a = Container(Box::new(Overrides(42)));
println!("{:?}", a);
let a = Container(Box::new(Defaults(42)));
println!("{:?}", a);
}
An alternate solution that requires the unstable specialization feature:
#![feature(specialization)]
use std::fmt;
use std::fmt::{Formatter, Debug};
struct Container<D>(Box<D>) where D: Data;
impl<D> Debug for Container<D>
where D: Data
{
default fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Container(Data {{ ... }})")
}
}
impl<D> Debug for Container<D>
where D: Data + Debug
{
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Container({:?})", self.0)
}
}
trait Data {}
#[derive(Debug)]
struct Overrides(i32);
impl Data for Overrides {}
struct Defaults(i32);
impl Data for Defaults {}
fn main() {
let a = Container(Box::new(Overrides(42)));
println!("{:?}", a);
let a = Container(Box::new(Defaults(42)));
println!("{:?}", a);
}
Note that this places the burden on the container.
I have a design issue, when using something like :
trait MyTrait<K: OtherTrait> { ... }
impl<K: OtherTrait, M: MyTrait<K>> AnyTrait for M { ... }
I cannot implement trait for this trait due to E207 error ("the type parameter K is not constrained by the impl trait, self type, or predicates").
Finding no way to get rid of this error, I apply this not-so-good-looking workaround (verbose and struct with no intrinsic value):
use std::fmt;
use std::marker::PhantomData;
pub trait MyTrait<K: fmt::Display> {
fn get_some_k(&self) -> Option<K>;
}
/* // This is my target impl but results in E207 due to K not constrained
impl<K: fmt::Display, S: MyTrait<K>> fmt::Display for S {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.get_some_k().unwrap())
}
} */
pub struct Ugly<'a, K: fmt::Display, S: 'a + MyTrait<K>>(&'a S, PhantomData<K>);
impl<'a, K: fmt::Display, S: MyTrait<K>> fmt::Display for Ugly<'a, K, S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0.get_some_k().unwrap())
}
}
fn main() { }
I think there should be some nicer way to implement a trait for this kind of parameterized trait.
I did not find good example in std (for instance no Display implementation in traits with associated type like Iterator)?
Here’s an implementation using associated types (which means that you can only implement MyTrait for one K per type):
use std::fmt;
pub trait MyTrait {
type K: fmt::Display;
fn get_some_k(&self) -> Option<Self::K>;
}
impl<S: MyTrait> fmt::Display for S {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.get_some_k().unwrap())
}
}
fn main() { }
However, when clarified like this it becomes clear that this approach won’t work either, because you’re implementing Display for all types that implement MyTrait—types that could have their own Display implementation. This is forbidden, and so you get E0210:
error: type parameter S must be used as the type parameter for some local type (e.g. MyStruct<T>); only traits defined in the current crate can be implemented for a type parameter [E0210]
Wrapping it in something—like your Ugly did—is the only way to allow such an implementation. Or implement a trait in your own crate rather than one in someone else’s (like Display is).
I have a linked-list sort of struct, using Option, Rc, and RefCell.
I'd like to implement fmt::Debug for it, but have run into the lovely "cannot move out of borrowed content" error.
use std::fmt;
use std::rc::{Rc, Weak};
use std::cell::RefCell;
#[derive(Clone, Debug, Ord, Eq, PartialOrd, PartialEq)]
struct NodeId {id: String}
impl NodeId {
pub fn new(s: &str) -> NodeId { NodeId{id: s.to_string()}}
}
struct NodeInfo {
nodeid: NodeId,
prev: Option<Rc<RefCell<NodeInfo>>>,
next: Option<Rc<RefCell<NodeInfo>>>,
}
impl fmt::Debug for NodeInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "NodeInfo( {} {} {} )", self.nodeid.id,
match self.prev { None => "none".to_string(), Some(ref n) => n.borrow().nodeid.id},
match self.next { None => "none".to_string(), Some(ref n) => "some".to_string()},
)
}
}
fn main() {}
Ideally the debug output would be able to show me the ids of the .next and .previous nodes. But Rust is not allowing access to them. The attempt to .borrow() the content of the RefCell causes the error, but I cannot understand why.
Play with it here: http://is.gd/Sah7sT
Does RefCell::borrow() move the contents?
No. Calling it borrow and having it move would be pretty underhanded! ^_^
The problem is that you are trying to move the id out of your borrowed struct. This is a move because String isn't Copy:
n.borrow().nodeid.id
Instead, use clone to leave the current string where it is, and return a brand-new one:
n.borrow().nodeid.id.clone()
To expand on #Shepmaster's answer (which is absolutely correct), you can avoid having to copy the string in this case, by writing the id of the child nodes directly to the formatter.
I've chosen to use a newtype to avoid repetition:
impl fmt::Debug for NodeInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "NodeInfo( {} {:?} {:?} )", self.nodeid.id, ChildNode(&self.prev), ChildNode(&self.next))
}
}
struct ChildNode<'a>(&'a Option<Rc<RefCell<NodeInfo>>>);
impl<'a> fmt::Debug for ChildNode<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self.0 {
Some(ref n) => write!(f, "{}", n.borrow().nodeid.id),
None => write!(f, "None"),
}
}
}