Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 22633fe

Browse files
committed
When not finding assoc fn on type, look for builder fn
When we have a resolution error when looking at a fully qualified path on a type, look for all associated functions on inherent impls that return `Self` and mention them to the user. Fix #69512.
1 parent cc705b8 commit 22633fe

File tree

8 files changed

+134
-0
lines changed

8 files changed

+134
-0
lines changed

‎compiler/rustc_hir_typeck/src/method/suggest.rs‎

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,86 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
409409
err.downgrade_to_delayed_bug();
410410
}
411411

412+
if let (ty::Adt(adt_def, _), SelfSource::QPath(_)) = (rcvr_ty.kind(), source) {
413+
// Look at all the associated functions without receivers in the type's inherent impls
414+
// to look for builders that return `Self`, `Option<Self>` or `Result<Self, _>`.
415+
let mut items = self
416+
.tcx
417+
.inherent_impls(adt_def.did())
418+
.iter()
419+
.flat_map(|i| self.tcx.associated_items(i).in_definition_order())
420+
.filter(|item| {
421+
// Only assoc fn with no receivers.
422+
matches!(item.kind, ty::AssocKind::Fn) && !item.fn_has_self_parameter
423+
})
424+
.filter_map(|item| {
425+
// Only assoc fns that return `Self`, `Option<Self>` or `Result<Self, _>`.
426+
let ret_ty = self.tcx.fn_sig(item.def_id).skip_binder().output();
427+
let ret_ty = self.tcx.erase_late_bound_regions(ret_ty);
428+
let ty::Adt(def, args) = ret_ty.kind() else {
429+
return None;
430+
};
431+
// Check for `-> Self`
432+
if self.can_eq(self.param_env, ret_ty, rcvr_ty) {
433+
return Some((item.def_id, ret_ty));
434+
}
435+
// Check for `-> Option<Self>` or `-> Result<Self, _>`
436+
if ![
437+
self.tcx.lang_items().option_type(),
438+
self.tcx.get_diagnostic_item(sym::Result),
439+
]
440+
.contains(&Some(def.did()))
441+
{
442+
return None;
443+
}
444+
let arg = args.get(0)?.expect_ty();
445+
if self.can_eq(self.param_env, rcvr_ty, arg) {
446+
Some((item.def_id, ret_ty))
447+
} else {
448+
None
449+
}
450+
})
451+
.collect::<Vec<_>>();
452+
let post = if items.len() > 5 {
453+
let items_len = items.len();
454+
items.truncate(4);
455+
format!("\nand {} others", items_len - 4)
456+
} else {
457+
String::new()
458+
};
459+
match &items[..] {
460+
[] => {}
461+
[(def_id, ret_ty)] => {
462+
err.span_note(
463+
self.tcx.def_span(def_id),
464+
format!(
465+
"if you're trying to build a new `{rcvr_ty}`, consider using `{}` \
466+
which returns `{ret_ty}`",
467+
self.tcx.def_path_str(def_id),
468+
),
469+
);
470+
}
471+
_ => {
472+
let span: MultiSpan = items
473+
.iter()
474+
.map(|(def_id, _)| self.tcx.def_span(def_id))
475+
.collect::<Vec<Span>>()
476+
.into();
477+
err.span_note(
478+
span,
479+
format!(
480+
"if you're trying to build a new `{rcvr_ty}` consider using one of the \
481+
following associated functions:\n{}{post}",
482+
items
483+
.iter()
484+
.map(|(def_id, _ret_ty)| self.tcx.def_path_str(def_id))
485+
.collect::<Vec<String>>()
486+
.join("\n")
487+
),
488+
);
489+
}
490+
}
491+
};
412492
if tcx.ty_is_opaque_future(rcvr_ty) && item_name.name == sym::poll {
413493
err.help(format!(
414494
"method `poll` found on `Pin<&mut {ty_str}>`, \

‎tests/ui/issues/issue-42880.stderr‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@ error[E0599]: no associated item named `String` found for struct `String` in the
33
|
44
LL | let f = |&Value::String(_)| ();
55
| ^^^^^^ associated item not found in `String`
6+
|
7+
note: if you're trying to build a new `String` consider using one of the following associated functions:
8+
String::new
9+
String::with_capacity
10+
String::from_utf8
11+
String::from_utf16
12+
and 7 others
13+
--> $SRC_DIR/alloc/src/string.rs:LL:COL
614

715
error: aborting due to previous error
816

‎tests/ui/parser/emoji-identifiers.stderr‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ LL | 👀::full_of✨()
7575
| |
7676
| function or associated item not found in `👀`
7777
| help: there is an associated function with a similar name: `full_of_✨`
78+
|
79+
note: if you're trying to build a new `👀`, consider using `👀::full_of_✨` which returns `👀`
80+
--> $DIR/emoji-identifiers.rs:4:5
81+
|
82+
LL | fn full_of_✨() -> 👀 {
83+
| ^^^^^^^^^^^^^^^^^^^^^
7884

7985
error[E0425]: cannot find function `i_like_to_😄_a_lot` in this scope
8086
--> $DIR/emoji-identifiers.rs:13:13
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
use std::net::TcpStream;
2+
3+
fn main() {
4+
let stream = TcpStream::new(); //~ ERROR no function or associated item named `new` found
5+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0599]: no function or associated item named `new` found for struct `TcpStream` in the current scope
2+
--> $DIR/fn-new-doesnt-exist.rs:4:28
3+
|
4+
LL | let stream = TcpStream::new();
5+
| ^^^ function or associated item not found in `TcpStream`
6+
|
7+
note: if you're trying to build a new `TcpStream` consider using one of the following associated functions:
8+
TcpStream::connect
9+
TcpStream::connect_timeout
10+
--> $SRC_DIR/std/src/net/tcp.rs:LL:COL
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0599`.

‎tests/ui/resolve/issue-82865.stderr‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ LL | Box::z
1515
LL | mac!();
1616
| ------ in this macro invocation
1717
|
18+
note: if you're trying to build a new `Box<_, _>` consider using one of the following associated functions:
19+
Box::<T>::new
20+
Box::<T>::new_uninit
21+
Box::<T>::new_zeroed
22+
Box::<T>::try_new
23+
and 18 others
24+
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
1825
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
1926

2027
error: aborting due to 2 previous errors

‎tests/ui/suggestions/deref-path-method.stderr‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ error[E0599]: no function or associated item named `contains` found for struct `
44
LL | Vec::contains(&vec, &0);
55
| ^^^^^^^^ function or associated item not found in `Vec<_, _>`
66
|
7+
note: if you're trying to build a new `Vec<_, _>` consider using one of the following associated functions:
8+
Vec::<T>::new
9+
Vec::<T>::with_capacity
10+
Vec::<T>::from_raw_parts
11+
Vec::<T, A>::new_in
12+
and 2 others
13+
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
714
help: the function `contains` is implemented on `[_]`
815
|
916
LL | <[_]>::contains(&vec, &0);

‎tests/ui/suggestions/issue-109291.stderr‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ LL | println!("Custom backtrace: {}", std::backtrace::Backtrace::forced_capt
66
| |
77
| function or associated item not found in `Backtrace`
88
| help: there is an associated function with a similar name: `force_capture`
9+
|
10+
note: if you're trying to build a new `Backtrace` consider using one of the following associated functions:
11+
Backtrace::capture
12+
Backtrace::force_capture
13+
Backtrace::disabled
14+
Backtrace::create
15+
--> $SRC_DIR/std/src/backtrace.rs:LL:COL
916

1017
error: aborting due to previous error
1118

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /