Skip to content

Commit 8696da0

Browse files
authored
Unrolled build for rust-lang#120632
Rollup merge of rust-lang#120632 - trevyn:issue-109195, r=oli-obk For E0223, suggest associated functions that are similar to the path e.g. for `String::from::utf8`, suggest `String::from_utf8` Closes rust-lang#109195
2 parents 4a2fe44 + 0b6af71 commit 8696da0

File tree

4 files changed

+142
-0
lines changed

4 files changed

+142
-0
lines changed

compiler/rustc_hir_analysis/src/astconv/errors.rs

+51
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use rustc_errors::{
1414
use rustc_hir as hir;
1515
use rustc_hir::def_id::{DefId, LocalDefId};
1616
use rustc_infer::traits::FulfillmentError;
17+
use rustc_middle::query::Key;
1718
use rustc_middle::ty::{self, suggest_constraining_type_param, Ty, TyCtxt, TypeVisitableExt};
1819
use rustc_session::parse::feature_err;
1920
use rustc_span::edit_distance::find_best_match_for_name;
@@ -859,6 +860,56 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
859860

860861
self.set_tainted_by_errors(err.emit());
861862
}
863+
864+
/// On ambiguous associated type, look for an associated function whose name matches the
865+
/// extended path and, if found, emit an E0223 error with a structured suggestion.
866+
/// e.g. for `String::from::utf8`, suggest `String::from_utf8` (#109195)
867+
pub(crate) fn maybe_report_similar_assoc_fn(
868+
&self,
869+
span: Span,
870+
qself_ty: Ty<'tcx>,
871+
qself: &hir::Ty<'_>,
872+
) -> Result<(), ErrorGuaranteed> {
873+
let tcx = self.tcx();
874+
if let Some((_, node)) = tcx.hir().parent_iter(qself.hir_id).skip(1).next()
875+
&& let hir::Node::Expr(hir::Expr {
876+
kind:
877+
hir::ExprKind::Path(hir::QPath::TypeRelative(
878+
hir::Ty {
879+
kind:
880+
hir::TyKind::Path(hir::QPath::TypeRelative(
881+
_,
882+
hir::PathSegment { ident: ident2, .. },
883+
)),
884+
..
885+
},
886+
hir::PathSegment { ident: ident3, .. },
887+
)),
888+
..
889+
}) = node
890+
&& let Some(ty_def_id) = qself_ty.ty_def_id()
891+
&& let Ok([inherent_impl]) = tcx.inherent_impls(ty_def_id)
892+
&& let name = format!("{ident2}_{ident3}")
893+
&& let Some(ty::AssocItem { kind: ty::AssocKind::Fn, .. }) = tcx
894+
.associated_items(inherent_impl)
895+
.filter_by_name_unhygienic(Symbol::intern(&name))
896+
.next()
897+
{
898+
let reported =
899+
struct_span_code_err!(tcx.dcx(), span, E0223, "ambiguous associated type")
900+
.with_span_suggestion_verbose(
901+
ident2.span.to(ident3.span),
902+
format!("there is an associated function with a similar name: `{name}`"),
903+
name,
904+
Applicability::MaybeIncorrect,
905+
)
906+
.emit();
907+
self.set_tainted_by_errors(reported);
908+
Err(reported)
909+
} else {
910+
Ok(())
911+
}
912+
}
862913
}
863914

864915
/// Emits an error regarding forbidden type binding associations

compiler/rustc_hir_analysis/src/astconv/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1373,6 +1373,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
13731373
)
13741374
.emit() // Already reported in an earlier stage.
13751375
} else {
1376+
self.maybe_report_similar_assoc_fn(span, qself_ty, qself)?;
1377+
13761378
let traits: Vec<_> =
13771379
self.probe_traits_that_match_assoc_ty(qself_ty, assoc_ident);
13781380

tests/ui/suggestions/issue-109195.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
fn main() {
2+
String::from::utf8;
3+
//~^ ERROR ambiguous associated type [E0223]
4+
//~| HELP there is an associated function with a similar name: `from_utf8`
5+
String::from::utf8();
6+
//~^ ERROR ambiguous associated type [E0223]
7+
//~| HELP there is an associated function with a similar name: `from_utf8`
8+
String::from::utf16();
9+
//~^ ERROR ambiguous associated type [E0223]
10+
//~| HELP there is an associated function with a similar name: `from_utf16`
11+
String::from::method_that_doesnt_exist();
12+
//~^ ERROR ambiguous associated type [E0223]
13+
//~| HELP if there were a trait named `Example` with associated type `from`
14+
str::from::utf8();
15+
//~^ ERROR ambiguous associated type [E0223]
16+
//~| HELP if there were a trait named `Example` with associated type `from`
17+
str::from::utf8_mut();
18+
//~^ ERROR ambiguous associated type [E0223]
19+
//~| HELP if there were a trait named `Example` with associated type `from`
20+
}
+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
error[E0223]: ambiguous associated type
2+
--> $DIR/issue-109195.rs:2:5
3+
|
4+
LL | String::from::utf8;
5+
| ^^^^^^^^^^^^
6+
|
7+
help: there is an associated function with a similar name: `from_utf8`
8+
|
9+
LL | String::from_utf8;
10+
| ~~~~~~~~~
11+
12+
error[E0223]: ambiguous associated type
13+
--> $DIR/issue-109195.rs:5:5
14+
|
15+
LL | String::from::utf8();
16+
| ^^^^^^^^^^^^
17+
|
18+
help: there is an associated function with a similar name: `from_utf8`
19+
|
20+
LL | String::from_utf8();
21+
| ~~~~~~~~~
22+
23+
error[E0223]: ambiguous associated type
24+
--> $DIR/issue-109195.rs:8:5
25+
|
26+
LL | String::from::utf16();
27+
| ^^^^^^^^^^^^
28+
|
29+
help: there is an associated function with a similar name: `from_utf16`
30+
|
31+
LL | String::from_utf16();
32+
| ~~~~~~~~~~
33+
34+
error[E0223]: ambiguous associated type
35+
--> $DIR/issue-109195.rs:11:5
36+
|
37+
LL | String::from::method_that_doesnt_exist();
38+
| ^^^^^^^^^^^^
39+
|
40+
help: if there were a trait named `Example` with associated type `from` implemented for `String`, you could use the fully-qualified path
41+
|
42+
LL | <String as Example>::from::method_that_doesnt_exist();
43+
| ~~~~~~~~~~~~~~~~~~~~~~~~~
44+
45+
error[E0223]: ambiguous associated type
46+
--> $DIR/issue-109195.rs:14:5
47+
|
48+
LL | str::from::utf8();
49+
| ^^^^^^^^^
50+
|
51+
help: if there were a trait named `Example` with associated type `from` implemented for `str`, you could use the fully-qualified path
52+
|
53+
LL | <str as Example>::from::utf8();
54+
| ~~~~~~~~~~~~~~~~~~~~~~
55+
56+
error[E0223]: ambiguous associated type
57+
--> $DIR/issue-109195.rs:17:5
58+
|
59+
LL | str::from::utf8_mut();
60+
| ^^^^^^^^^
61+
|
62+
help: if there were a trait named `Example` with associated type `from` implemented for `str`, you could use the fully-qualified path
63+
|
64+
LL | <str as Example>::from::utf8_mut();
65+
| ~~~~~~~~~~~~~~~~~~~~~~
66+
67+
error: aborting due to 6 previous errors
68+
69+
For more information about this error, try `rustc --explain E0223`.

0 commit comments

Comments
 (0)