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

Adding an impl for type defined outside of crate causes every associated method call to be reported as an error #127798

Closed
udoprog opened this issue Jul 16, 2024 · 8 comments · Fixed by #130764
Assignees
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@udoprog
Copy link
Contributor

udoprog commented Jul 16, 2024

Code

/// This is not a valid implementation for the current crate.
impl dyn core::fmt::Display {}

fn foo(values: &[u32]) -> Option<&u32> {
    values.get(0)
}

Current output

As expected, we get an error indicating:


error[E0116]: cannot define inherent `impl` for a type outside of the crate where the type is defined
 --> src/lib.rs:1:1
  |
1 | impl dyn core::fmt::Display {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl for type defined outside of crate.
  |
  = note: define and implement a trait or new type instead

But we also get the following "bonus" error:

error[E0599]: no method named `get` found for reference `&[u32]` in the current scope
 --> src/lib.rs:5:12
  |
5 |     values.get(0)
  |            ^^^
  |
help: there is a method `ge` with a similar name
  |
5 |     values.ge(0)
  |            ~~

Some errors have detailed explanations: E0116, E0599.
For more information about an error, try `rustc --explain E0116`.
error: could not compile `playground` (lib) due to 2 previous errors

If for example we add the impl to the tokio crate, we get:

error: could not compile `tokio` (lib) due to 3370 previous errors; 9 warnings emitted

Desired output

Preferably, the impl for type defined outside of crate being an illegal implementation should not cause other seemingly unrelated errors.

Rust Version

rustc 1.79.0 (129f3b996 2024-06-10)
binary: rustc
commit-hash: 129f3b9964af4d4a709d1383930ade12dfe7c081
commit-date: 2024-06-10
host: x86_64-unknown-linux-gnu
release: 1.79.0
LLVM version: 18.1.7
@udoprog udoprog added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jul 16, 2024
@steffahn
Copy link
Member

This seems to be a regression in 1.78

@steffahn
Copy link
Member

Bisection points to somewhere here

  commit[0] 2024-02-14: Auto merge of #120847 - oli-obk:track_errors9, r=compiler-errors
  commit[1] 2024-02-15: Auto merge of #121125 - ehuss:fix-small-cstr, r=Mark-Simulacrum
  commit[2] 2024-02-15: Auto merge of #121131 - matthiaskrgr:rollup-mo3b8nz, r=matthiaskrgr
  commit[3] 2024-02-15: Auto merge of #116564 - oli-obk:evaluated_static_in_metadata, r=RalfJung,cjgillot
  commit[4] 2024-02-15: Auto merge of #120931 - chenyukang:yukang-cleanup-hashmap, r=michaelwoerister
  commit[5] 2024-02-15: Auto merge of #119863 - tmiasko:will-wake, r=m-ou-se
  commit[6] 2024-02-15: Auto merge of #121142 - GuillaumeGomez:rollup-5qmksjw, r=GuillaumeGomez
  commit[7] 2024-02-15: Auto merge of #119338 - compiler-errors:upcast-plus-autos, r=lcnr
  commit[8] 2024-02-15: Auto merge of #121133 - tmiasko:skip-coroutines, r=cjgillot

That’s almost certainly

cc @oli-obk

@steffahn
Copy link
Member

This change in test output is actually a bad change that was already visible in the tests when #121113 was merged. The function

// Allowed
fn in_impl_Trait_in_return() -> impl IntoIterator<Item = impl IntoIterator> {
    vec![vec![0; 10], vec![12; 7], vec![8; 3]]
+   //~^ ERROR: no function or associated item named `into_vec` found for slice `[_]`
}

should not gain any errors pointing to it. It's even clearly marked as an “Allowed” case in the comments.
(This looks like a clear oversight in review.) [Also cc @compiler-errors.]

@steffahn
Copy link
Member

For context, this issue can easily make a single change in a rust crate cause hundreds of unrelated errors at once, as reported on: https://users.rust-lang.org/t/pub-use-breaks-my-compiler/117983

Those hundreds of unrelated errors can then easily hide the actual problem.


Looking further through the changed tests in #121113, I also think that the following is a bad change:

struct Foo<T: ?Sized>(T);
impl Foo<dyn Send + Sync> {
    fn abc() -> bool { //~ ERROR duplicate definitions with name `abc`
        false
    }
}

impl Foo<dyn Sync + Send> {
    fn abc() -> bool {
        true
    }
}

fn main() {
    assert_eq!(<Foo<dyn Send + Sync>>::abc(), false);
+   //~^ ERROR: multiple applicable items in scope
    assert_eq!(<Foo<dyn Sync + Send>>::abc(), true);
+   //~^ ERROR: multiple applicable items in scope
}

Adding a second definition of abc does not make existing callers wrong, so reporting an error there is just distracting from the actual problem.

@steffahn
Copy link
Member

steffahn commented Sep 23, 2024

This doesn’t just make methods fail, but all inherent associated items, AFAICT. E.g. here’s an associated constant (inspired by the third bad error I’ve noticed #121113 has added to already existing tests).

impl () {}

fn f() {
    let x = i8::MIN;
}

(among the errors:)

error[E0599]: no associated item named `MIN` found for type `i8` in the current scope
 --> src/lib.rs:4:17
  |
4 |     let x = i8::MIN;
  |                 ^^^ associated item not found in `i8`
  |

@compiler-errors
Copy link
Member

I'll look into it. I agree the existing implementation is a bit goofy.

@compiler-errors compiler-errors self-assigned this Sep 23, 2024
@compiler-errors
Copy link
Member

This is two issues:

  1. We act as if no inherent impls exist if we have an invalid inherent impl like impl () {}:
    • I think this is worth fixing and I've got a PR coming up soon.
  2. We continue typechecking if there are overlapping incoherent impls: Adding an impl for type defined outside of crate causes every associated method call to be reported as an error #127798 (comment)
    • I'm not as convinced that this is worth suppressing. While it may cause some confusion, it really is an ambiguity -- if you are concerned with this behavior, I'm happy to keep discussing, and the fix is not very difficult. please file a new bug so we can separate that out, though.

@steffahn
Copy link
Member

I think, the second issue (ambiguity on overlap) is acceptable either way; at least all of the errors also point to the relevant impls anyway; and it’s only affecting the overlapping trait, so no risk of causing hundreds or thousands of error messages suddenly.

I think this is worth fixing and I've got a PR coming up soon.

This is great to hear, thanks for the quick analysis. Otherwise (if it wasn’t so easily fixed) I would have suggested a revert of #121113 as a quick fix, or at least a partial revert, as far as the tcx.ensure().crate_inherent_impls(()) case goes.

@bors bors closed this as completed in 3b45f8f Sep 25, 2024
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Sep 25, 2024
Rollup merge of rust-lang#130764 - compiler-errors:inherent, r=estebank

Separate collection of crate-local inherent impls from error tracking

rust-lang#119895 changed the return type of the `crate_inherent_impls` query from `CrateInherentImpls` to `Result<CrateInherentImpls, ErrorGuaranteed>` to avoid needing to use the non-parallel-friendly `track_errors()` to track if an error was reporting from within the query... This was mostly fine until rust-lang#121113, which stopped halting compilation when we hit an `Err(ErrorGuaranteed)` in the `crate_inherent_impls` query.

Thus we proceed onwards to typeck, and since a return type of `Result<CrateInherentImpls, ErrorGuaranteed>` means that the query can *either* return one of "the list inherent impls" or "error has been reported", later on when we want to assemble method or associated item candidates for inherent impls, we were just treating any `Err(ErrorGuaranteed)` return value as if Rust had no inherent impls defined anywhere at all! This leads to basically every inherent method call failing with an error, lol, which was reported in rust-lang#127798.

This PR changes the `crate_inherent_impls` query to return `(CrateInherentImpls, Result<(), ErrorGuaranteed>)`, i.e. returning the inherent impls collected *and* whether an error was reported in the query itself. It firewalls the latter part of that query into a new `crate_inherent_impls_validity_check` just for the `ensure()` call.

This fixes rust-lang#127798.
flip1995 pushed a commit to flip1995/rust that referenced this issue Oct 3, 2024
Separate collection of crate-local inherent impls from error tracking

rust-lang#119895 changed the return type of the `crate_inherent_impls` query from `CrateInherentImpls` to `Result<CrateInherentImpls, ErrorGuaranteed>` to avoid needing to use the non-parallel-friendly `track_errors()` to track if an error was reporting from within the query... This was mostly fine until rust-lang#121113, which stopped halting compilation when we hit an `Err(ErrorGuaranteed)` in the `crate_inherent_impls` query.

Thus we proceed onwards to typeck, and since a return type of `Result<CrateInherentImpls, ErrorGuaranteed>` means that the query can *either* return one of "the list inherent impls" or "error has been reported", later on when we want to assemble method or associated item candidates for inherent impls, we were just treating any `Err(ErrorGuaranteed)` return value as if Rust had no inherent impls defined anywhere at all! This leads to basically every inherent method call failing with an error, lol, which was reported in rust-lang#127798.

This PR changes the `crate_inherent_impls` query to return `(CrateInherentImpls, Result<(), ErrorGuaranteed>)`, i.e. returning the inherent impls collected *and* whether an error was reported in the query itself. It firewalls the latter part of that query into a new `crate_inherent_impls_validity_check` just for the `ensure()` call.

This fixes rust-lang#127798.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants