Skip to content

Commit

Permalink
Rollup merge of #120632 - trevyn:issue-109195, r=oli-obk
Browse files Browse the repository at this point in the history
For E0223, suggest associated functions that are similar to the path

e.g. for `String::from::utf8`, suggest `String::from_utf8`

Closes #109195
  • Loading branch information
matthiaskrgr authored Feb 6, 2024
2 parents 8906977 + 0b6af71 commit eae477d
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 0 deletions.
51 changes: 51 additions & 0 deletions compiler/rustc_hir_analysis/src/astconv/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use rustc_errors::{
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_infer::traits::FulfillmentError;
use rustc_middle::query::Key;
use rustc_middle::ty::{self, suggest_constraining_type_param, Ty, TyCtxt, TypeVisitableExt};
use rustc_session::parse::feature_err;
use rustc_span::edit_distance::find_best_match_for_name;
Expand Down Expand Up @@ -859,6 +860,56 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {

self.set_tainted_by_errors(err.emit());
}

/// On ambiguous associated type, look for an associated function whose name matches the
/// extended path and, if found, emit an E0223 error with a structured suggestion.
/// e.g. for `String::from::utf8`, suggest `String::from_utf8` (#109195)
pub(crate) fn maybe_report_similar_assoc_fn(
&self,
span: Span,
qself_ty: Ty<'tcx>,
qself: &hir::Ty<'_>,
) -> Result<(), ErrorGuaranteed> {
let tcx = self.tcx();
if let Some((_, node)) = tcx.hir().parent_iter(qself.hir_id).skip(1).next()
&& let hir::Node::Expr(hir::Expr {
kind:
hir::ExprKind::Path(hir::QPath::TypeRelative(
hir::Ty {
kind:
hir::TyKind::Path(hir::QPath::TypeRelative(
_,
hir::PathSegment { ident: ident2, .. },
)),
..
},
hir::PathSegment { ident: ident3, .. },
)),
..
}) = node
&& let Some(ty_def_id) = qself_ty.ty_def_id()
&& let Ok([inherent_impl]) = tcx.inherent_impls(ty_def_id)
&& 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))
.next()
{
let reported =
struct_span_code_err!(tcx.dcx(), span, E0223, "ambiguous associated type")
.with_span_suggestion_verbose(
ident2.span.to(ident3.span),
format!("there is an associated function with a similar name: `{name}`"),
name,
Applicability::MaybeIncorrect,
)
.emit();
self.set_tainted_by_errors(reported);
Err(reported)
} else {
Ok(())
}
}
}

/// Emits an error regarding forbidden type binding associations
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_hir_analysis/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1373,6 +1373,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
)
.emit() // Already reported in an earlier stage.
} else {
self.maybe_report_similar_assoc_fn(span, qself_ty, qself)?;

let traits: Vec<_> =
self.probe_traits_that_match_assoc_ty(qself_ty, assoc_ident);

Expand Down
20 changes: 20 additions & 0 deletions tests/ui/suggestions/issue-109195.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
fn main() {
String::from::utf8;
//~^ ERROR ambiguous associated type [E0223]
//~| HELP there is an associated function with a similar name: `from_utf8`
String::from::utf8();
//~^ ERROR ambiguous associated type [E0223]
//~| HELP there is an associated function with a similar name: `from_utf8`
String::from::utf16();
//~^ ERROR ambiguous associated type [E0223]
//~| HELP there is an associated function with a similar name: `from_utf16`
String::from::method_that_doesnt_exist();
//~^ ERROR ambiguous associated type [E0223]
//~| HELP if there were a trait named `Example` with associated type `from`
str::from::utf8();
//~^ ERROR ambiguous associated type [E0223]
//~| HELP if there were a trait named `Example` with associated type `from`
str::from::utf8_mut();
//~^ ERROR ambiguous associated type [E0223]
//~| HELP if there were a trait named `Example` with associated type `from`
}
69 changes: 69 additions & 0 deletions tests/ui/suggestions/issue-109195.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
error[E0223]: ambiguous associated type
--> $DIR/issue-109195.rs:2:5
|
LL | String::from::utf8;
| ^^^^^^^^^^^^
|
help: there is an associated function with a similar name: `from_utf8`
|
LL | String::from_utf8;
| ~~~~~~~~~

error[E0223]: ambiguous associated type
--> $DIR/issue-109195.rs:5:5
|
LL | String::from::utf8();
| ^^^^^^^^^^^^
|
help: there is an associated function with a similar name: `from_utf8`
|
LL | String::from_utf8();
| ~~~~~~~~~

error[E0223]: ambiguous associated type
--> $DIR/issue-109195.rs:8:5
|
LL | String::from::utf16();
| ^^^^^^^^^^^^
|
help: there is an associated function with a similar name: `from_utf16`
|
LL | String::from_utf16();
| ~~~~~~~~~~

error[E0223]: ambiguous associated type
--> $DIR/issue-109195.rs:11:5
|
LL | String::from::method_that_doesnt_exist();
| ^^^^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `from` implemented for `String`, you could use the fully-qualified path
|
LL | <String as Example>::from::method_that_doesnt_exist();
| ~~~~~~~~~~~~~~~~~~~~~~~~~

error[E0223]: ambiguous associated type
--> $DIR/issue-109195.rs:14:5
|
LL | str::from::utf8();
| ^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `from` implemented for `str`, you could use the fully-qualified path
|
LL | <str as Example>::from::utf8();
| ~~~~~~~~~~~~~~~~~~~~~~

error[E0223]: ambiguous associated type
--> $DIR/issue-109195.rs:17:5
|
LL | str::from::utf8_mut();
| ^^^^^^^^^
|
help: if there were a trait named `Example` with associated type `from` implemented for `str`, you could use the fully-qualified path
|
LL | <str as Example>::from::utf8_mut();
| ~~~~~~~~~~~~~~~~~~~~~~

error: aborting due to 6 previous errors

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

0 comments on commit eae477d

Please sign in to comment.