[Solved] Accepting either a reference or an owned value

I am writing a library, and I want my callers to be able to pass in a Config object, a reference to a Config object, or no config at all, in which case I will initialize from the defaults.

I thought that I should have my factory method take a Borrow<Config>, and the blanket impl<T> Borrow<T> for T and impl<'a, T> Borrow<T> for &'a T would allow the user to pass in a Config or &'a Config.

I am hitting “expected type parameter, found struct”. Reproed in the playground:

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=e051839023fef33ab034a06d959a0348

This error doesn’t make sense to me. I feel like I’m missing something fundamental. All that I can understand is that the compiler can’t prove that T == Config. And I understand that - T is not always going to be Config. But T is always going to be Config when Engine is constructed by from_defaults.

I’m groping in the dark with things I don’t completely understand, but I think the fundamental problem is that the functions inside this impl block have to work for any T: Borrow<Config>, but from_defaults only works for T == Config. I thought up this second impl block that can include functions that only work when T == Config, and it actually compiled.

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=00716a749680d98f91eb874af6345502

Is that the way to solve this?

1 Like

Maybe put a where clause on that method? For that the method will need to be generic, which means it will have to take T2, unrelated to the T from the surrounding block. If it’s a trait, that method won’t be object safe, but if you never want to call it on a dyn Trait, you can still include it in there by adding where Self: Sized.

At the end of the day, you will have to separate the two things, because you say your impl works for all T, when actually it doesn’t.

On the other hand, if config is a struct, I would derive clone on it and then from_defaults can just clone it from a reference.

This is correct and your playground is the solution.

1 Like