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

Call to function broken by unrelated constraint on generic function containing the call #125274

Open
tonyelewis opened this issue May 19, 2024 · 1 comment
Labels
C-bug Category: This is a bug. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged.

Comments

@tonyelewis
Copy link

I'm a bit new to Rust; sorry if the following is just my misunderstanding.

I tried this code (play):

pub trait MyTrait {
}

// Implement `MyTrait` for `&String`
impl<'a> MyTrait for &'a String {
}

// Function taking a reference to some `T` for which `&T` implements `MyTrait`
//
// So, eg, passing a `&String` (implying `T=String`) is valid
pub fn call_me<T>(_: &T) where for<'a> &'a T: MyTrait {}

// Sure enough, calling `call_me()` with a `&String` works (here in a function generic over some `U`)
pub fn call_compiles<U>() {
   call_me(&String::new());
}

// Do exactly the same (but coincidentally in a function that constrains `U` such that `&U` implements `MyTrait`
//
// This does not compile.
pub fn call_does_not_compile<U>() where for<'b> &'b U: MyTrait {
   call_me(&String::new()); // <---- ****** THIS CALL FAILS ******
}

// It can be made to work by explicitly telling it that matching `&T` to &String implies T=String
pub fn call_can_be_made_to_work<U>() where for<'b> &'b U: MyTrait {
   call_me::<String>(&String::new());
}

I expected to see the compiler accept this code. Instead, I get this error:

error[E0308]: mismatched types
  --> src/lib.rs:22:10
   |
21 | pub fn call_does_not_compile<U>() where for<'b> &'b U: MyTrait {
   |                              - expected this type parameter
22 |     call_me(&String::new()); // <---- ****** THIS CALL FAILS ******
   |     ------- ^^^^^^^^^^^^^^ expected `&U`, found `&String`
   |     |
   |     arguments to this function are incorrect
   |
   = note: expected reference `&U`
              found reference `&String`
note: function defined here
  --> src/lib.rs:11:8
   |
11 | pub fn call_me<T>(_: &T) where for<'a> &'a T: MyTrait {}
   |        ^^^^^^^    -----

For more information about this error, try `rustc --explain E0308`.

The Playground shows this happening on nightly too.

The error message suggests it thinks call_me() should be passed a &U, but &U has nothing to do with call_me() or the &String it's being passed.

Thank you very much for all work on Rust.

@tonyelewis tonyelewis added the C-bug Category: This is a bug. label May 19, 2024
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label May 19, 2024
@lucasscharenbroch
Copy link

It looks like the String candidate is winnowed out during trait solving.
candidate_should_be_dropped_in_favor_of keeps U (a ParamCandidate) and scraps String (an ImplCandidate).

match (&other.candidate, &victim.candidate) {
    /* ... */
    (
        ParamCandidate(ref other_cand),
        ImplCandidate(..)
        | /* ... */
    ) => {
        // We have a where clause so don't go around looking
        // for impls. Arbitrarily give param candidates priority
        // over projection and object candidates.
        //
        // Global bounds from the where clause should be ignored
        // here (see issue #50825).
        DropVictim::drop_if(!is_global(other_cand))
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. needs-triage This issue may need triage. Remove it if it has been sufficiently triaged.
Projects
None yet
Development

No branches or pull requests

3 participants