Description
I want to implement multiplication on a struct that works with all permutations of owned, shared, and mutable references.
use std::ops::Mul;
struct Foo;
impl Mul for &Foo {
type Output = Foo;
fn mul(self, _rhs: Self) -> Self::Output {
unimplemented!()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
let ref_mut_foo: &mut Foo = &mut Foo;
let ref_foo: &Foo = &Foo;
let owned_foo: Foo = Foo;
let _ = ref_foo * ref_foo;
let _ = ref_foo * ref_mut_foo;
let _ = ref_foo * &owned_foo;
let _ = ref_mut_foo * ref_foo;
let _ = ref_mut_foo * ref_mut_foo;
let _ = ref_mut_foo * &owned_foo;
let _ = &owned_foo * ref_foo;
let _ = &owned_foo * ref_mut_foo;
let _ = &owned_foo * &owned_foo;
}
}
I expected to have to implement std::ops::Mul
for my Foo
struct. I realised that means we're consuming the Foo
struct so instead I implemented it on &Foo
. This works for the &
and owned structs although I have to add an explicit &
operator to to the owned struct. This seems fair since Rust doesn't do automatic reference coercion and using the &
operator should be quite natural for consumers of my struct. Unfortunately this does NOT work for &mut Foo
. I was under the impression that rust does automatic coersion from &mut T
to &T
.
I also tried implementing the std::ops::Mul
trait on &mut Foo
but you end up with borrowing issues.
To be clear using as &Foo
coercion works. Just wondering why it's necessary? Is there a way around this to get the semantics I want?
Meta
rustc --version --verbose
rustc 1.65.0-nightly (eaadb8947 2022-08-27)
binary: rustc
commit-hash: eaadb8947b850a025404082f6297766c4680a42a
commit-date: 2022-08-27
host: x86_64-unknown-linux-gnu
release: 1.65.0-nightly
LLVM version: 15.0.0