Skip to content

FnPtr blanket impls cause "multiple applicable items in scope" for unrelated types. #109892

Closed
@eddyb

Description

@eddyb

Note: the below reduction originally came from a use num_traits::Float; + 0.0.max(x) in the wild.

I haven't found a way to demonstrate this outside of the "float inference vars + Ord method" combo, but:

trait MyCmp {
    fn cmp(&self) {}
}
impl MyCmp for f32 {}

fn main() {
    0.0.cmp();
}

works on stable (1.68.2) and beta (1.69.0-beta.6), and errors on nightly with:

error[E0034]: multiple applicable items in scope
 --> src/main.rs:7:9
  |
7 |     0.0.cmp();
  |         ^^^ multiple `cmp` found
  |
note: candidate #1 is defined in an impl of the trait `MyCmp` for the type `f32`
 --> src/main.rs:2:5
  |
2 |     fn cmp(&self) {}
  |     ^^^^^^^^^^^^^
  = note: candidate #2 is defined in an impl of the trait `Ord` for the type `F`
note: candidate #3 is defined in the trait `Iterator`
 --> /rustc/3a8a131e9509c478ece1c58fe0ea2d49463d2300/library/core/src/iter/traits/iterator.rs:3533:5
help: disambiguate the method for candidate #1
  |
7 |     MyCmp::cmp(&0.0);
  |     ~~~~~~~~~~~~~~~~
help: disambiguate the method for candidate #2
  |
7 |     Ord::cmp(&0.0);
  |     ~~~~~~~~~~~~~~
help: disambiguate the method for candidate #3
  |
7 |     Iterator::cmp(0.0);
  |     ~~~~~~~~~~~~~~~~~~

Even though it doesn't show the source for candidate #2, I'm almost certain it's this:

#[stable(feature = "fnptr_impls", since = "1.4.0")]
impl<F: FnPtr> Ord for F {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
self.addr().cmp(&other.addr())
}
}

from (cc @lcnr @oli-obk):

On the original PR I left comments like #99531 (comment), trying to rectify the issues with the original approach, but they didn't go anywhere and the version that one in the end is the (arguably) more fragile original one, that uses blanket impls and works around their unwanted interactions.

It's possible in this case all it takes is checking for "float inference vars" and making sure they can never be considered to implement FnPtr, but I'm worried there might be other edge cases lurking in the shadows.

Also, did both of those PRs skip crater? I feel like this shouldn't be that hard to hit in the wild.

Metadata

Metadata

Assignees

Labels

A-trait-systemArea: Trait systemC-bugCategory: This is a bug.P-highHigh priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-nightlyPerformance or correctness regression from stable to nightly.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions