std::default::Default trait with Result?

I am implementing std::default::Default for a custom type. Due to the contract in the Default trait the method default() needs to return Self. But I want to be able to return a result with a possible error Result<Self, Error>.

What would be the best way to do this?

impl std::default::Default for MyStruct
{
    fn default() -> Result<Self, Error> {
        // ...
    }
}

Maybe something like try_default?

The Default trait is for infallible default sensible values, and there's no fallible counterpart.

You will need to write the constructor function yourself instead.

3 Likes

If creating a default instance may fail, Default probably isn't the right trait to be using.

Normally you'd add this sort of thing as a normal constructor because then you can give it a descriptive name (e.g. MyStruct::from_env()).

4 Likes

I agree with you but I think it's because Default trait is the only constructor trait in rust, if there is a New or Init trait, and it can be failed when creating a instance, that would be better.

That's because you don't need a trait to construct an object in Rust. If you want to create an object, just define a method or function that returns an instance.

Traits are only useful if you want to use their contract as part of an abstraction (i.e. in generics). So many times I've seen traits declare that all implementors must be constructed using a particular way and it ends up unnecessarily constraining them.

5 Likes

the closest thing you can pull from the standard library is TryFrom<()>:

impl TryFrom<()> for MyStruct {
    type Error = MyError;
    fn try_from(_:()) -> Result<MyStruct, MyError> {
        todo!()
    }
}

let x = MyStruct::try_from(())?;
1 Like