Skip to content

Commit 12a4952

Browse files
Suggest associated method on deref types
1 parent 0421444 commit 12a4952

File tree

3 files changed

+80
-2
lines changed

3 files changed

+80
-2
lines changed

compiler/rustc_typeck/src/check/method/suggest.rs

+60-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
1616
use rustc_middle::traits::util::supertraits;
1717
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
1818
use rustc_middle::ty::print::with_crate_prefix;
19-
use rustc_middle::ty::ToPolyTraitRef;
2019
use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeVisitable};
20+
use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
2121
use rustc_span::symbol::{kw, sym, Ident};
2222
use rustc_span::Symbol;
2323
use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span};
@@ -30,7 +30,7 @@ use rustc_trait_selection::traits::{
3030
use std::cmp::Ordering;
3131
use std::iter;
3232

33-
use super::probe::{Mode, ProbeScope};
33+
use super::probe::{IsSuggestion, Mode, ProbeScope};
3434
use super::{CandidateSource, MethodError, NoMatchData};
3535

3636
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -1069,6 +1069,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10691069
}
10701070
}
10711071

1072+
self.check_for_deref_method(&mut err, source, rcvr_ty, item_name);
1073+
10721074
return Some(err);
10731075
}
10741076

@@ -1651,6 +1653,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16511653
}
16521654
}
16531655

1656+
fn check_for_deref_method(
1657+
&self,
1658+
err: &mut Diagnostic,
1659+
self_source: SelfSource<'tcx>,
1660+
rcvr_ty: Ty<'tcx>,
1661+
item_name: Ident,
1662+
) {
1663+
let SelfSource::QPath(ty) = self_source else { return; };
1664+
for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
1665+
if let Ok(pick) = self.probe_for_name(
1666+
ty.span,
1667+
Mode::Path,
1668+
item_name,
1669+
IsSuggestion(true),
1670+
deref_ty,
1671+
ty.hir_id,
1672+
ProbeScope::TraitsInScope,
1673+
) {
1674+
if deref_ty.is_suggestable(self.tcx, true)
1675+
// If this method receives `&self`, then the provided
1676+
// argument _should_ coerce, so it's valid to suggest
1677+
// just changing the path.
1678+
&& pick.item.fn_has_self_parameter
1679+
&& let Some(self_ty) =
1680+
self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
1681+
&& self_ty.is_ref()
1682+
{
1683+
let suggested_path = match deref_ty.kind() {
1684+
ty::Bool
1685+
| ty::Char
1686+
| ty::Int(_)
1687+
| ty::Uint(_)
1688+
| ty::Float(_)
1689+
| ty::Adt(_, _)
1690+
| ty::Str
1691+
| ty::Projection(_)
1692+
| ty::Param(_) => format!("{deref_ty}"),
1693+
_ => format!("<{deref_ty}>"),
1694+
};
1695+
err.span_suggestion_verbose(
1696+
ty.span,
1697+
format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1698+
suggested_path,
1699+
Applicability::MaybeIncorrect,
1700+
);
1701+
} else {
1702+
err.span_note(
1703+
ty.span,
1704+
format!("the function `{item_name}` is implemented on `{deref_ty}`"),
1705+
);
1706+
}
1707+
return;
1708+
}
1709+
}
1710+
}
1711+
16541712
/// Print out the type for use in value namespace.
16551713
fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
16561714
match ty.kind() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
fn main() {
2+
let vec = Vec::new();
3+
Vec::contains(&vec, &0);
4+
//~^ ERROR no function or associated item named `contains` found for struct `Vec<_, _>` in the current scope
5+
//~| HELP the function `contains` is implemented on `[_]`
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0599]: no function or associated item named `contains` found for struct `Vec<_, _>` in the current scope
2+
--> $DIR/deref-path-method.rs:3:10
3+
|
4+
LL | Vec::contains(&vec, &0);
5+
| ^^^^^^^^ function or associated item not found in `Vec<_, _>`
6+
|
7+
help: the function `contains` is implemented on `[_]`
8+
|
9+
LL | <[_]>::contains(&vec, &0);
10+
| ~~~~~
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0599`.

0 commit comments

Comments
 (0)