Skip to content

Commit a4cb55f

Browse files
committed
For E0223, suggest methods that look similar to the path
1 parent bf3c6c5 commit a4cb55f

File tree

3 files changed

+141
-0
lines changed

3 files changed

+141
-0
lines changed

compiler/rustc_hir_analysis/src/astconv/mod.rs

+52
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
2929
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
3030
use rustc_infer::traits::ObligationCause;
3131
use rustc_middle::middle::stability::AllowUnstable;
32+
use rustc_middle::query::Key;
3233
use rustc_middle::ty::{
3334
self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, IsSuggestable, ParamEnv, Ty,
3435
TyCtxt, TypeVisitableExt,
@@ -1373,6 +1374,57 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
13731374
)
13741375
.emit() // Already reported in an earlier stage.
13751376
} else {
1377+
// suggest methods that look similar to the path
1378+
// e.g. for `String::from::utf8`, suggest `String::from_utf8` (#109195)
1379+
for (_, node) in tcx.hir().parent_iter(qself.hir_id) {
1380+
if let hir::Node::Expr(hir::Expr {
1381+
kind:
1382+
hir::ExprKind::Path(hir::QPath::TypeRelative(
1383+
hir::Ty {
1384+
kind:
1385+
hir::TyKind::Path(hir::QPath::TypeRelative(
1386+
_,
1387+
hir::PathSegment { ident: ident2, .. },
1388+
)),
1389+
..
1390+
},
1391+
hir::PathSegment { ident: ident3, .. },
1392+
)),
1393+
..
1394+
}) = node
1395+
{
1396+
let name = format!("{ident2}_{ident3}");
1397+
if if let Some(ty_def_id) = qself_ty.ty_def_id()
1398+
&& let Ok([inherent_impl]) = tcx.inherent_impls(ty_def_id)
1399+
&& let Some(ty::AssocItem { kind: ty::AssocKind::Fn, .. }) = tcx
1400+
.associated_items(inherent_impl)
1401+
.filter_by_name_unhygienic(Symbol::intern(&name))
1402+
.next()
1403+
{
1404+
true
1405+
} else {
1406+
qself_ty.is_str()
1407+
&& ["from_utf8", "from_utf8_mut"].contains(&name.as_str())
1408+
} {
1409+
let reported = struct_span_code_err!(
1410+
tcx.dcx(),
1411+
span,
1412+
E0223,
1413+
"ambiguous associated type"
1414+
)
1415+
.with_span_suggestion_verbose(
1416+
ident2.span.to(ident3.span),
1417+
format!("you might have meant to use `{name}`"),
1418+
name,
1419+
Applicability::MaybeIncorrect,
1420+
)
1421+
.emit();
1422+
self.set_tainted_by_errors(reported);
1423+
return Err(reported);
1424+
}
1425+
}
1426+
}
1427+
13761428
let traits: Vec<_> =
13771429
self.probe_traits_that_match_assoc_ty(qself_ty, assoc_ident);
13781430

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 you might have meant to use `from_utf8`
5+
String::from::utf8();
6+
//~^ ERROR ambiguous associated type [E0223]
7+
//~| HELP you might have meant to use `from_utf8`
8+
String::from::utf16();
9+
//~^ ERROR ambiguous associated type [E0223]
10+
//~| HELP you might have meant to use `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 you might have meant to use `from_utf8`
17+
str::from::utf8_mut();
18+
//~^ ERROR ambiguous associated type [E0223]
19+
//~| HELP you might have meant to use `from_utf8_mut`
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: you might have meant to use `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: you might have meant to use `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: you might have meant to use `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: you might have meant to use `from_utf8`
52+
|
53+
LL | str::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: you might have meant to use `from_utf8_mut`
63+
|
64+
LL | str::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)