Stream: t-compiler/wg-rls-2.0

Topic: Help debugging a trait issue


Adam Bratschi-Kaye (he) (SP1'17) (May 02 2020 at 23:17, on Zulip):

Hey, I was trying to debug https://github.com/rust-analyzer/rust-analyzer/issues/4132 and seem to have a simple reproduction here:

struct A<T> {
    x: T,
}

trait Constraint {}
impl Constraint for i32 {}

trait MyTrait<T> {
    fn transform(x: T) -> Self;
}
impl<T: Constraint> MyTrait<T> for A<T> {
    fn transform(x: T) -> A<T> {
        A { x }
    }
}

fn main() {
    let a = A::transform(1);
}

In this case rust-analyzer shows the type of a in main as A<{unknown}>, but it's able to infer a: A<i32> if I remove the Constraint trait or specify 1i32. Any tips on how to further debug this?

One thing I've seen so far that I don't understand is that at some point in resolve_obligations_as_possible we try to resolve the obligation

Implements(A<_>: MyTrait<_>)

which should have a unique solution of i32, but the result we're getting is Ambig(Unknown}. Plugging the same program into the chalk repl seems like it should work fine:

?- program
Enter a program; press Ctrl-D when finished
| struct A<T> {}
| trait Constraint {}
| impl Constraint for i32 {}
| trait MyTrait<T> {}
| impl<T> MyTrait<T> for A<T> where T: Constraint {}
|
?- exists<T,U> { A<T>: MyTrait<U> }
Unique; substitution [?0 := Int(I32), ?1 := Int(I32)], lifetime constraints []

Any advice in particular on how to further check what statements are available to chalk and why it can't seem to resolve this obligation?

Florian Diebold (May 03 2020 at 00:02, on Zulip):

to model this in Chalk the way rust-analyzer would, you need to mark the traits #[non_enumerable]. we don't allow open-ended searches of all impls, that's why this doesn't work

Florian Diebold (May 03 2020 at 00:03, on Zulip):

I'm reasonably sure rustc also only does this for integer variables, and the problem is that Chalk doesn't know about integer variables yet

Jonas Schievink (May 03 2020 at 00:14, on Zulip):

This looks like either integer fallback or "inference guessing" (where it eagerly selects the only remaining impl that could apply) at work

Adam Bratschi-Kaye (he) (SP1'17) (May 03 2020 at 09:13, on Zulip):

Thanks @Florian Diebold, that makes sense. If I add the #[non_enumerable] tag then chalk doesn't provide a solution:

struct A<T> {}
#[non_enumerable]
trait Constraint {}
#[non_enumerable]
trait MyTrait<T> {}
impl Constraint for i32 {}
impl<T> MyTrait<T> for A<T> where T: Constraint {}

?- exists<T,U> { A<T>: MyTrait<U> }
Ambiguous; no inference guidance

But now I'm confused as to why it doesn't at least determine that T and U should be the same type. It is able to do that if the implementation for MyTrait on A doesn't have the condition T: Constraint:

struct A<T> {}
#[non_enumerable]
trait Constraint {}
#[non_enumerable]
trait MyTrait<T> {}
impl Constraint for i32 {}
impl<T> MyTrait<T> for A<T> {}

?- exists<T,U> { A<T>: MyTrait<U> }
Unique; for<?U0> { substitution [?0 := ^0.0, ?1 := ^0.0], lifetime constraints [] }
Florian Diebold (May 03 2020 at 09:19, on Zulip):

Hmm I'm not sure, actually, that may require some debugging

Adam Bratschi-Kaye (he) (SP1'17) (May 03 2020 at 09:23, on Zulip):

I'm happy to try looking into it.

Florian Diebold (May 03 2020 at 09:25, on Zulip):

not sure if you were using the recursive solver or the SLG solver there, if it was in the REPL it was probably SLG. Maybe the problem exists in both, but it'll surely require different fixes

Florian Diebold (May 03 2020 at 09:29, on Zulip):

oh, and if you want to look into it: (I don't know how familiar you are with Chalk, so) what I'd do is add a test for it in the Chalk repo, run it with CHALK_DEBUG=2 (I just do that by calling set_env at the beginning of the test), and see what happens. Also probably ask about it over in #wg-traits ;)

Adam Bratschi-Kaye (he) (SP1'17) (May 03 2020 at 11:06, on Zulip):

Thanks for the tips, I'm indeed not familiar with chalk. I was just using the repl by doing cargo run in the chalk repo, so if SLG is the default then that's what I had.

Adam Bratschi-Kaye (he) (SP1'17) (May 05 2020 at 08:06, on Zulip):

Here's the thread in wg-traits: https://rust-lang.zulipchat.com/#narrow/stream/144729-wg-traits/topic/More.20guidance.20for.20an.20ambiguous.20query

Last update: Sep 30 2020 at 16:30UTC