Trait inference not following multiple levels of indirection

I'm stumped as to why the compiler isn't able to follow the chain of generic impls of my trait Verify in this minimized version of my project.
Any thoughts on why this is one step too far for the compiler's solver? Also, are there clearer alternatives to the let statement (marker #1) for nudging the compiler in the right direction?

Snippet, see Playground:

// *********************************************************  (1)
// NOTE: Uncommenting this line fixes the trait inference
// let other_items: &List<u16, ()> = other_items;


I'm relying on the impl of my trait Verify for Vec to be found through several levels of indirection (ListNontrivial -> List -> Vec).
I suspect it may be a deref-coercion issue... but I'm not sure exactly why.

Adding what I believe is an explicit dereference coercion (marker #1) fixes the issue, but more surprising to me is that removing the seemingly unrelated impl (marker #2, see playground) also fixes the inference.

The compiler error gave me a hint, but it wasn't until 80% through minimizing to get this example that I realized (marker #2) was required to keep the error present.
Seems like it's calling deref on items, when I'd want it to also try deref on other_items to find the solution.

Compiler error:

error[E0277]: the trait bound `List<u16, ()>: Verify<ListNontrivial<u16, ()>>` is not satisfied
  --> src/
66 |         items.verify(other_items);
   |               ------ ^^^^^^^^^^^ the trait `Verify<ListNontrivial<u16, ()>>` is not implemented for `List<u16, ()>`
   |               |
   |               required by a bound introduced by this call
   = help: the trait `Verify` is implemented for `List<T, S>`
note: required for `ListNontrivial<u16, ()>` to implement `Verify`
  --> src/
34 | impl<T, U, S> Verify<U> for ListNontrivial<T, S>
   |               ^^^^^^^^^     ^^^^^^^^^^^^^^^^^^^^
35 | where
36 |     List<T, S>: Verify<U>,
   |                 --------- unsatisfied trait bound introduced here

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` (lib) due to previous error

I personally get stumped why the compiler is solving rather than the isn'ts
Nudging can do, cleaner maybe but not sure about clearer.


and here a bit of added clarity

<_ as Verify<List<_,_>>>::verify(items, other_items);

Fair point on the "is solving" :slight_smile:

Somehow I overlooked &** as a solution. I guess we're dereferencing the reference, calling deref on that, and then taking a reference to that inner deref place (?)

Yes. It's common for recursive definitions like

impl Trait for Box<dyn Trait + '_> {
    fn method(&self) {
//      (*   *    self     ).method()
//      |   |   |      | | |
//      |   |   ` &Box ' | |
//      |   |            | |
//      |   ` Box<dyn _> ' |
//      |                  |
//      `    dyn Trait     '

(And then method autoref slaps a & on the dyn Trait and calls <dyn Trait>::method(&**self).)

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.