1
Fork 0

Rollup merge of #135865 - zachs18:maybe_report_similar_assoc_fn_more, r=compiler-errors

For E0223, suggest associated functions that are similar to the path, even if the base type has multiple inherent impl blocks.

Currently, the "help: there is an associated function with a similar name `from_utf8`" suggestion for `String::from::utf8` is only given if `String` has exactly one inherent `impl` item. This PR makes the suggestion be emitted even if the base type has multiple inherent `impl` items.

Example:

```rust
struct Foo;
impl Foo {
    fn bar_baz() {}
}
impl Foo {} // load-bearing
fn main() {
    Foo::bar::baz;
}
```

Nightly/stable output:

```rust
error[E0223]: ambiguous associated type
 --> f.rs:7:5
  |
7 |     Foo::bar::baz;
  |     ^^^^^^^^
  |
help: if there were a trait named `Example` with associated type `bar` implemented for `Foo`, you could use the fully-qualified path
  |
7 |     <Foo as Example>::bar::baz;
  |     ~~~~~~~~~~~~~~~~~~~~~

error: aborting due to 1 previous error

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

Output with this PR, or without the load-bearing empty impl on nightly/stable:

```rust
error[E0223]: ambiguous associated type
 --> f.rs:7:5
  |
7 |     Foo::bar::baz;
  |     ^^^^^^^^
  |
help: there is an associated function with a similar name: `bar_baz`
  |
7 |     Foo::bar_baz;
  |          ~~~~~~~

error: aborting due to 1 previous error

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

Ideally, this suggestion would also work for non-ADT types like ~~`str::char::indices`~~ (edit: latest commit makes this work with primitives)  or `<dyn Any>::downcast::mut_unchecked`, but that seemed to be a harder change.

`@rustbot` label +A-diagnostics
This commit is contained in:
Matthias Krüger 2025-01-24 08:08:08 +01:00 committed by GitHub
commit efb8084672
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 200 additions and 96 deletions

View file

@ -9,6 +9,7 @@ use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_middle::bug;
use rustc_middle::ty::fast_reject::{TreatParams, simplify_type};
use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
use rustc_middle::ty::{
self, AdtDef, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt,
@ -998,12 +999,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
)),
..
}) = node
&& let Some(adt_def) = qself_ty.ty_adt_def()
&& let [inherent_impl] = tcx.inherent_impls(adt_def.did())
&& let name = format!("{ident2}_{ident3}")
&& let Some(ty::AssocItem { kind: ty::AssocKind::Fn, .. }) = tcx
.associated_items(inherent_impl)
.filter_by_name_unhygienic(Symbol::intern(&name))
&& let Some(inherent_impls) = qself_ty
.ty_adt_def()
.map(|adt_def| tcx.inherent_impls(adt_def.did()))
.or_else(|| {
simplify_type(tcx, qself_ty, TreatParams::InstantiateWithInfer)
.map(|simple_ty| tcx.incoherent_impls(simple_ty))
})
&& let name = Symbol::intern(&format!("{ident2}_{ident3}"))
&& let Some(ty::AssocItem { kind: ty::AssocKind::Fn, .. }) = inherent_impls
.iter()
.flat_map(|inherent_impl| {
tcx.associated_items(inherent_impl).filter_by_name_unhygienic(name)
})
.next()
{
Err(struct_span_code_err!(self.dcx(), span, E0223, "ambiguous associated type")