`Mismatched type` only in `impl`

The following is a cut-down reproducer for a problem I'm failing to understand:

use rustyline::hint::Hinter;
use rustyline::validate::{ValidationContext, ValidationResult, Validator};
use rustyline::{Completer, Editor, Helper, Highlighter};
use rustyline::history::DefaultHistory;

#[derive(Completer, Helper, Highlighter)]
struct HelperStruct {}

impl Hinter for HelperStruct {
    type Hint = String;

    fn hint(&self, line: &str, pos: usize, ctx: &rustyline::Context<'_>) -> Option<Self::Hint> {
        let _ = (line, pos, ctx);
        None
    }
}

impl Validator for HelperStruct {
    fn validate(&self, ctx: &mut ValidationContext) -> rustyline::Result<ValidationResult> {
        let _ = ctx;
        Ok(ValidationResult::Valid(None))
    }

    fn validate_while_typing(&self) -> bool {
        false
    }
}

struct Ctx<'a, T: Helper> {
    _rl: Editor<HelperStruct, DefaultHistory>,
    _var: Option<&'a T>,
}

impl<'a, T: Helper> Ctx<'a, T> {
    fn build() -> Self {
        let helper = HelperStruct {};

        let mut rl: Editor<HelperStruct, DefaultHistory> = Editor::new().unwrap();
        rl.set_helper(Some(helper));

        Ctx {
            _rl: rl,
            _var: rl.helper(),
        }
    }
}

fn main() {
    // This is Ok
    let helper = HelperStruct {};

    let mut rl: Editor<HelperStruct, DefaultHistory> = Editor::new().unwrap();
    rl.set_helper(Some(helper));

    let _ctx = Ctx {
        _rl: rl,
        _var: rl.helper(),
    };

    // This is NOT OK
    let _ctx: Ctx<HelperStruct> = Ctx::build();
}

The compiler is complaining with:

error[E0308]: mismatched types
  --> src/main.rs:43:19
   |
34 | impl<'a, T: Helper> Ctx<'a, T> {
   |          - expected this type parameter
...
43 |             _var: rl.helper(),
   |                   ^^^^^^^^^^^ expected `Option<&T>`, found `Option<&HelperStruct>`
   |
   = note: expected enum `Option<&T>`
              found enum `Option<&HelperStruct>`

But why? T is a generic with a trait bound on Helper and indeed HelperStruct is implementing the Helper trait.

Also I'm puzzled why the error is only on the impl block while this seems fine on main.

Edit:

It seems it's a lifetime mismatch. Not a failure on the trait resolution.

I have a #[derive(Helper)] on the struct definition so it should be derived already?

The caller (i.e. your main function calling Ctx::build) chooses T, not the callee (your Ctx::build function). If I implement Helper for Foo and say Ctx::<Foo>::build() I wouldn't get a Ctx<Foo>, I'd get a Ctx<HelperStruct>, even though I wanted a Ctx<Foo>. Which is why you can't use a generic argument in your scenario where the callee decides what type T should be. Changing your impl block to impl<'a> Ctx<'a, HelperStruct> would work though.

1 Like

Yes. I had not seen the derived implementation. I edited my comment, which is pretty much what Jofas has mentioned as well.