Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prefer clauses from the environment #584

Open
flodiebold opened this issue Jul 25, 2020 · 5 comments
Open

Prefer clauses from the environment #584

flodiebold opened this issue Jul 25, 2020 · 5 comments

Comments

@flodiebold
Copy link
Member

flodiebold commented Jul 25, 2020

The following code compiles in rustc:

fn f<T: Into<String>>(u: T) {
    let x = u.into();
    x.as_str();
}

This works even though there are other (blanket) impls that could apply for the into() call. rust-analyzer on the other hand can't resolve the type of x because the T: Into<?> goal is ambiguous. Note that if we have a struct S that impls Into<String> instead of the type parameter T, we get an ambiguity error (see this playground).

This works because rustc eagerly selects clauses from the environment, before looking at other impls. I think the old recursive solver actually handled this, but we removed the code because we didn't have / come up with a test case for it.

(CC rust-lang/rust-analyzer#5514)

@nikomatsakis
Copy link
Contributor

Yeah, the plan for chalk was to try and push a "more pure" approach, where we would consider it ambiguous, but return "guidance", and leave it up to the rust-analyzer to decide when to apply that guidance.

@nikomatsakis
Copy link
Contributor

I would definitely prefer to try this approach (guidance) before anything else, it's great that we can use rust-analyzer to see how well it works.

@flodiebold
Copy link
Member Author

So, would this be something like Guidance::Suggested? And then RA would basically detect when trying to resolve x.as_str that it can't make progress, and apply the suggested guidance?

@ANtlord
Copy link

ANtlord commented Jan 13, 2023

Hello @nikomatsakis, I've done a little investigation on the interation of Rust Analyzer with Chalk to infer types. But it would be great to have a confirmation if I'm following the right way. Rust Analyzer utilizes the unification via InferenceTable::relate. The method does a quick union via Unifier::relate, then returns RelationResult::goals which later is used in Rust Analyzer. At this point Unifier::relate doesn't utilize Environment, which has the data to infer the type of Into. Is this correct?

@Geo25rey
Copy link

@nikomatsakis I disagree with the "more pure"/"guidance" approach. IMHO chalk should try its best to match what ructc would do in this situation. In this case, that would be to eagerly infer that x is a String.

For example, this same principle applies to my use case:

mod some_lib {
    pub fn a_to_b(b_compat: &(impl Into<String> + Clone)) -> impl Into<String> {
        b_compat.clone()
    }
}

fn main() {
    let a = "8";
    let b = some_lib::a_to_b(&a).into(); // this is type String but rust-analyzer says the type is {unknown}
    let c = b.replace("8", "9");
    println!("b = {}, c = {}", b, c);
}

a is correctly inferred, but b and c, which are interpreted as Strings by rustc, are interpreted as {unknown} in chalk.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants