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

Consider subst in prioritising placeholder inherent methods #14555

Closed
wants to merge 1 commit into from

Conversation

HKalbasi
Copy link
Member

Reduces unknown types on self to 18

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 13, 2023
let substs = self.substs_for_method_call(generics, generic_args);
let substs = match subst {
Some(s) => {
// FIXME: here we need the method subst, but result of `lookup_method` incorrectly returns the trait
Copy link
Member

@Veykril Veykril Apr 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably want to look into rustc's probing logic and copy that fully at some point

Comment on lines 952 to 979
#[test]
fn method_resolution_prefer_explicit_bound() {
check_types(
r#"
trait Tr<T> {
fn tr(self) -> T;
}

impl<T> Tr<T> for T {
fn tr(self) -> T {
self
}
}
fn test<T: Tr<i32>>(x: T) { x.tr(); }
//^^^^^^ i32
fn test<T: Tr<i32> + Tr<i64>>(x: T) { let x: i64 = x.tr(); }
//^^^^^^ i64
"#,
);
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this basically #5514?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I was looking at the unknown types for finding regressions of #14470 and when I found out that this is definitely not a regression, it was too late :)

I don't think it needs chalk support, as it is a method resolution thing. The current implementation also handles the Into2 case mentioned in the issue, I will add a test for it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this solves the general issue unfortunately -- Into2 case that's mentioned in the issue is the following (mostly taken from the playground linked in rust-lang/chalk#584), which still fails with this PR. I don't think we can solve this without overhauling chalk, because it needs to prioritize T: Into<i32> bound when proving subobligation chalk produces internally which we don't have control over.

trait Into<T> {
    fn into(self) -> T;
}
impl<T> Into<T> for T {
    fn into(self) -> T { loop {} }
}
trait Into2<T> {
    fn into2(self) -> T;
}
impl<U, T> Into2<T> for U where U: Into<T> {
    fn into2(self) -> T { loop {} }
}

fn test<T: Into<i32>>(t: T) {
    let u = t.into2();
      //^i32
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, you are right. If that issue in chalk becomes solved, our iterate_inherent_trait_methods will become completely unnecessary?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we need it regardless. That function is for prioritizing some traits (principal trait for dyn, trait bounds for placeholder) to search methods from, whereas the chalk issue is for prioritizing where clauses to be considered when solving obligations.

Consider the code below. Even if we could prove both C: Foo and C: Bar (with or without the chalk issue resolved), we need to pick Bar::f when resolving v.f().

trait Foo {
    fn f(self);
}
trait Bar {
    fn f(self);
}

fn test<C: Bar>(v: C) {
    v.f();
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I think what I said above is true, at least that's how rustc is handling things. Since rustc doesn't take expectation into account during method resolution, it does seem to try solving T: Into<?0> rather than T: Into<T> and go into the steps I described above.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems you are correct. So, in the rustc code there is no usage of <i32> part of the Into<i32> until trait solving? And we can prioritize methods of Into<_> and the rest will be handled by trait solver? I also tried method where bounds, but it seems they don't affect resolution, which confirms this. In the function you linked from rustc it is passing trait_refs, but it seems it later only uses the trait id?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eh, so turns out I wasn't fully correct in regards to substitution i.e. <i32> part. assemble_inherent_candidates_from_param() records trait ref as you pointed out, and its substitution seems to be used to instantiate obligations rustc feeds into its trait solver. But I don't think it matters much, because the solver can only prove T: Into<i32> anyway due to prioritization.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, the current approach either should be completely removed, or only plays a small rule in the ideal solution. From that question, I wanted to know that does it worth to keep this as a workaround? It appears to work for the basic case of impl Into<i32>, but it makes our code unnecessarily ugly. So if you think the ideal solution is accessible in near future, we should wait for that and abandon this.

And if we decide to go with this as a workaround, we should check that this behaviour is a subset of the rustc's, and doesn't introduces new false positive type mismatches.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I don't think we should do this. This needs to be fixed in Chalk.

@bors
Copy link
Contributor

bors commented Apr 14, 2023

☔ The latest upstream changes (presumably #14578) made this pull request unmergeable. Please resolve the merge conflicts.

@HKalbasi
Copy link
Member Author

Closing per the discussion. I still think it is an acceptable workaround for an old and high impact problem, but I see the value in complete solutions.

@HKalbasi HKalbasi closed this Apr 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Awaiting review from the assignee but also interested parties.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants