Notifications
Sign Up Sign In
Q&A

How can I define a method on [&mut T] where T: MyTrait?

+5
−0

I'm trying to make a trait method callable on mutable slices of a type implementing that trait (see main). Rust doesn't like me for it.

use core::convert::AsMut;

trait A {
    type B;
    fn f(m: &mut [Self], b: Self::B);
}

impl<B, M: AsMut<[impl A<B=B>]>> M {
    fn f(&mut self, b: B) {
        A::f(self.as_mut(), b)
    }
}

struct C (u64);
impl A for C {
    type B = u8;
    fn f(m: &mut [Self], b: u8) {
        for c in m {
            c.0 += b;
        }
    }
}

fn main() {
    let v = vec![C(1), C(2), C(3), C(4)];
    v.f(5);
    assert_eq!(v, [C(6), C(7), C(8), C(9)]);
}

This gives me errors I don't understand, which is unusual for Rust:

   Compiling playground v0.0.1 (/playground)
error[E0207]: the type parameter `B` is not constrained by the impl trait, self type, or predicates
 --> src/main.rs:8:6
  |
8 | impl<B, M: AsMut<[impl A<B=B>]>> M {
  |      ^ unconstrained type parameter

error[E0207]: the type parameter `impl A<B = B>` is not constrained by the impl trait, self type, or predicates
 --> src/main.rs:8:19
  |
8 | impl<B, M: AsMut<[impl A<B=B>]>> M {
  |                   ^^^^^^^^^^^ unconstrained type parameter

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0207`.
error: could not compile `playground`.

Rewording my code slightly doesn't fix this. Is what I'm trying to do even possible in Rust? If so, how?

Why should this post be closed?

0 comments

1 answer

+3
−0

This error doesn't do a good job at all of highlighting the important thing!

You can't define an inherent impl on a type parameter. You have to make it the impl of some trait. Here's an example: Try it online!

trait A: Sized {
    type B;
    fn f(m: &mut [Self], b: Self::B);
}

trait AsMutExt<Inner: A> {
    fn f(&mut self, b: Inner::B);
}

impl<Inner: A, M: AsMut<[Inner]>> AsMutExt<Inner> for M {
    fn f(&mut self, b: Inner::B) {
        A::f(self.as_mut(), b)
    }
}

#[derive(PartialEq, Debug)]
struct C (u64);
impl A for C {
    type B = u8;
    fn f(m: &mut [Self], b: u8) {
        for c in m {
            c.0 += b as u64;
        }
    }
}

fn main() {
    let mut v = vec![C(1), C(2), C(3), C(4)];
    v.f(5);
    assert_eq!(v, [C(6), C(7), C(8), C(9)]);
}

2 comments

Why does it need to be Sized? ‭wizzwizz4‭ 4 days ago

My bad; AsMutExt doesn't need to be Sized. A does because of the use of Self in a slice in the parameter of f; Rust wants to know how large each element of that slice is in order to support iterating over it, etc. ‭r~~‭ 3 days ago

Sign up to answer this question »