Confusing `mismatched types`

⚓ Rust    📅 2025-08-11    👤 surdeus    👁️ 5      

surdeus

Playground

pub trait MyFnOnce<Args> {
    type Output;

    fn call_once(self, args: Args) -> Self::Output;
}

impl<A0, R, F: FnOnce(A0) -> R> MyFnOnce<(A0,)> for F {
    type Output = R;

    fn call_once(self, args: (A0,)) -> Self::Output {
        self(args.0)
    }
}

pub struct MyCell<'a, T: for<'b> MyFnOnce<(&'b (),)>> {
    value: <T as MyFnOnce<(&'a (),)>>::Output,
}

impl<'a, T: for<'b> MyFnOnce<(&'b (),)>> MyCell<'a, T> {
    pub fn new(value: <T as MyFnOnce<(&'a (),)>>::Output) -> Self {
        Self { value }
    }

    pub fn map<F: for<'b> MyFnOnce<(<T as MyFnOnce<(&'b (),)>>::Output,)> + 'a>(
        self,
        f: F,
    ) -> MyCell<
        'a,
        for<'b> fn(&'b ()) -> <F as MyFnOnce<(<T as MyFnOnce<(&'b (),)>>::Output,)>>::Output,
    > {
        MyCell::new(f.call_once((self.value,)))
    }
}

fn map_fn(x: &mut i32) -> &mut i32 {
    x
}

#[test]
fn foo() {
    let mut z = 1;

    let a: MyCell<fn(&()) -> &mut i32> = MyCell::new(&mut z);
    let _: MyCell<fn(&()) -> &mut i32> = a.map(map_fn);
}

#[test]
fn bar() {
    let mut z = 1;

    let a: MyCell<fn(&()) -> &mut i32> = MyCell::new(&mut z);
    let _ = a.map(map_fn);
}

   Compiling playground v0.0.1 (/playground)
warning: function `map_fn` is never used
  --> src/lib.rs:35:4
   |
35 | fn map_fn(x: &mut i32) -> &mut i32 {
   |    ^^^^^^
   |
   = note: `#[warn(dead_code)]` on by default

error[E0308]: mismatched types
  --> src/lib.rs:44:42
   |
44 |     let _: MyCell<fn(&()) -> &mut i32> = a.map(map_fn);
   |            ---------------------------   ^^^^^^^^^^^^^ expected `MyCell<'_, fn(&()) -> &mut i32>`, found `MyCell<'_, fn(&()) -> ...>`
   |            |
   |            expected due to this
   |
   = note: expected struct `MyCell<'_, for<'a> fn(&'a ()) -> &'a mut _>`
              found struct `MyCell<'_, for<'b> fn(&'b ()) -> &'b mut _>`
   = help: consider constraining the associated type `<for<'a> fn(&'a mut i32) -> &'a mut i32 {map_fn} as MyFnOnce<(&'b mut i32,)>>::Output` to `&mut i32`
   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html

error[E0308]: mismatched types
  --> src/lib.rs:52:13
   |
52 |     let _ = a.map(map_fn);
   |             ^^^^^^^^^^^^^ one type is more general than the other
   |
   = note: expected struct `MyCell<'_, for<'b> fn(&'b ()) -> &mut _>`
              found struct `MyCell<'_, for<'b> fn(&'b ()) -> &'b mut _>`

For more information about this error, try `rustc --explain E0308`.
warning: `playground` (lib) generated 1 warning
error: could not compile `playground` (lib test) due to 2 previous errors

2 posts - 2 participants

Read full topic

🏷️ Rust_feed