Skip to content

Implementing Multiplication without explicit coersion is Impossible #101571

Open
@WalterSmuts

Description

@WalterSmuts

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-trait-systemArea: Trait systemA-type-systemArea: Type systemC-discussionCategory: Discussion or questions that doesn't represent real issues.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamT-typesRelevant to the types team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions