Skip to content

method resolution can use yet undefined opaques #131

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

Open
lcnr opened this issue Oct 7, 2024 · 4 comments
Open

method resolution can use yet undefined opaques #131

lcnr opened this issue Oct 7, 2024 · 4 comments
Assignees

Comments

@lcnr
Copy link
Contributor

lcnr commented Oct 7, 2024

to get methods from alias bounds

fn foo<T: Clone>(x: T, choose: bool) -> impl Clone {
    if choose {
        foo(x, false).clone()
    } else {
        x
    }
}

https://rust.godbolt.org/z/vecjoaYzK

People rely on this behavior, see rust-lang/rust#117866, or more specifically, the crater run in rust-lang/rust#120798 (comment)

@lcnr
Copy link
Contributor Author

lcnr commented Oct 7, 2024

to get to nested receivers while computing auto deref steps

use std::ops::Deref;

fn foo(x: Box<u32>, choose: bool) -> impl Deref<Target = u32> {
    if choose {
        let value = foo(x, false).leading_zeros();
        Box::new(value)
    } else {
        x
    }
}

https://rust.godbolt.org/z/6Tf18YnPq

this can then be used ot define the opaque

use std::ops::Deref;
#[derive(Default)]
struct Foo;
impl Foo {
    fn method(self: Box<Foo>) {}
}

fn foo(choose: bool) -> impl Deref<Target = Foo> {
    if choose {
        foo(false).method();
    }

    Default::default()
}

https://rust.godbolt.org/z/1eoed4Tq7

and can very frequently be undesirable

use std::ops::Deref;
struct Foo;
impl Foo {
    fn method(&self) {}
}

struct Bar;
impl Deref for Bar {
    type Target = Foo;
    fn deref(&self) -> &Foo {
        &Foo
    }
}

fn deref_to_foo(choose: bool) -> impl Deref<Target = Foo> {
    if choose {
        deref_to_foo(false).method();
    }

    Bar
}

https://rust.godbolt.org/z/3hYs9TYhv

@lcnr
Copy link
Contributor Author

lcnr commented Oct 7, 2024

to discard candidates for which an item bound does not hold

#[derive(Default)]
struct MyType<T>(T);
impl MyType<u32> {
    fn method(self) {}
}

impl MyType<String> {
    fn method(self) {}
}

fn foo(choose: bool) -> MyType<impl Copy> {
    if choose {
        foo(false).method();
    }

    Default::default()
}

https://rust.godbolt.org/z/MYEEzfvj9

@lcnr
Copy link
Contributor Author

lcnr commented Jan 21, 2025

non-trivial affected tests and additional issues, even with #135445 and https://github.com/lcnr/rust/tree/opaque-type-method-call

  • subtyping, thx boxy
    • tests/ui/impl-trait/call_method_ambiguous.rs
    • tests/ui/impl-trait/call_method_without_import.rs
    • tests/ui/impl-trait/method-resolution2.rs
  • should be ambig?!?!11
    • tests/ui/impl-trait/method-resolution2.rs
  • god knows, sadness and sorrow
    • tests/ui/impl-trait/recursive-parent-trait-method-call.rs

@lcnr
Copy link
Contributor Author

lcnr commented May 6, 2025

current proposed solution

method calls opaque

  • canonicalize_auto_steps_shit: return newly defined opaques
    • only check bad_ty_is_infer in root, store its TyVid in ProbeCtxt
  • fn consider_probe for impl candidate, if self is equal to bad_ty, check via proof tree visitor
    • does there exist a candidate for which
      • all nestedd goals with the opaque as the self-type are "proven" via item bound/blanket impl, i.e. they do not simply force ambiguity
  • SEPARATELY: method selection fail with ambiguity if a candidate constrains the opaque type

@lcnr lcnr self-assigned this May 6, 2025
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

1 participant