Is there a reason why this code doesn't work?
trait Foo: 'static {
fn core_functionality(&self);
}
impl Foo {
fn utility_shortcut(&self) {
self.core_functionality();
}
}
// this works
fn f1(foo: &Foo) {
foo.utility_shortcut();
}
fn f2<F: Foo>(foo: F) {
// this doesn't work
// foo.utility_shortcut();
// this works, but requires casting
(&foo as &Foo).utility_shortcut();
}
(play )
I'd like utility_shortcut
function to be callable on &Foo
and on type F
which implements Foo
, and I cannot think of a way how to do it.
(I cannot add utility_shortcut
directly to Foo
trait, because it increases generated code size: it would be added to each Foo
implementation, which is problematic in certain situations).
vitalyd
September 22, 2018, 2:28am
2
impl Foo {
fn utility_shortcut(&self) {
self.core_functionality();
}
}
This makes the method available only on Foo trait objects, and that requires you to coerce to one in f2.
I can see a couple of approaches:
Make utility_shortcut a free function that takes a &Foo trait object.
Create a separate trait, let’s call it FooExt, that contains the util method. Then impl it for Foo and for F: Foo
This is one of those situations where I strongly encourage you to use dyn
to make things clearer: impl dyn Foo {
, fn f1(foo: &dyn Foo)
, etc.
1 Like
This makes the method available only on Foo trait objects, and that requires you to coerce to one in f2.
Still don’t understand why rust doesn’t coerse it automatically. Seems to be safe and obvious thing to me.
Make utility_shortcut a free function that takes a &Foo trait object.
This is somewhat not ergonomic.
Create a separate trait, let’s call it FooExt, that contains the util method. Then impl it for Foo and for F: Foo
Then this FooExt trait could be added to my prelude module and will be available. This is probably what I should do. Thank you!