Skip to content

Commit 5805362

Browse files
committed
only find segs chain for missing methods when no available candidates
1 parent abb9563 commit 5805362

File tree

3 files changed

+67
-10
lines changed

3 files changed

+67
-10
lines changed

compiler/rustc_hir_typeck/src/method/suggest.rs

+33-10
Original file line numberDiff line numberDiff line change
@@ -1150,7 +1150,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11501150
}
11511151
}
11521152

1153-
let label_span_not_found = |err: &mut Diag<'_>| {
1153+
let mut find_candidate_for_method = false;
1154+
1155+
let mut label_span_not_found = |err: &mut Diag<'_>| {
11541156
if unsatisfied_predicates.is_empty() {
11551157
err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
11561158
let is_string_or_ref_str = match rcvr_ty.kind() {
@@ -1226,6 +1228,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12261228
err.note(format!(
12271229
"the {item_kind} was found for\n{type_candidates}{additional_types}"
12281230
));
1231+
find_candidate_for_method = mode == Mode::MethodCall;
12291232
}
12301233
}
12311234
} else {
@@ -1378,15 +1381,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13781381
);
13791382
}
13801383
}
1381-
// If an appropriate error source is not found, check method chain for possible candiates
1382-
if unsatisfied_predicates.is_empty()
1383-
&& let Mode::MethodCall = mode
1384+
1385+
if !find_candidate_for_method {
1386+
self.lookup_segments_chain_for_no_match_method(
1387+
&mut err,
1388+
item_name,
1389+
item_kind,
1390+
source,
1391+
no_match_data,
1392+
);
1393+
}
1394+
1395+
self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected);
1396+
Some(err)
1397+
}
1398+
1399+
/// If an appropriate error source is not found, check method chain for possible candidates
1400+
fn lookup_segments_chain_for_no_match_method(
1401+
&self,
1402+
err: &mut Diag<'_>,
1403+
item_name: Ident,
1404+
item_kind: &str,
1405+
source: SelfSource<'tcx>,
1406+
no_match_data: &NoMatchData<'tcx>,
1407+
) {
1408+
if no_match_data.unsatisfied_predicates.is_empty()
1409+
&& let Mode::MethodCall = no_match_data.mode
13841410
&& let SelfSource::MethodCall(mut source_expr) = source
13851411
{
13861412
let mut stack_methods = vec![];
1387-
while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, method_span) =
1388-
source_expr.kind
1389-
{
1413+
while let hir::ExprKind::MethodCall(_, rcvr_expr, _, method_span) = source_expr.kind {
13901414
// Pop the matching receiver, to align on it's notional span
13911415
if let Some(prev_match) = stack_methods.pop() {
13921416
err.span_label(
@@ -1401,7 +1425,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14011425
.unwrap_or(Ty::new_misc_error(self.tcx)),
14021426
);
14031427

1404-
for _matched_method in self.probe_for_name_many(
1428+
for _ in self.probe_for_name_many(
14051429
Mode::MethodCall,
14061430
item_name,
14071431
None,
@@ -1411,6 +1435,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14111435
ProbeScope::TraitsInScope,
14121436
) {
14131437
// found a match, push to stack
1438+
// FIXME: should check all impl candidates, see issue#124946
14141439
stack_methods.push(rcvr_ty);
14151440
}
14161441
source_expr = rcvr_expr;
@@ -1423,8 +1448,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14231448
);
14241449
}
14251450
}
1426-
self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected);
1427-
Some(err)
14281451
}
14291452

14301453
fn find_likely_intended_associated_item(
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// https://github.com/rust-lang/rust/issues/124946
2+
3+
struct Builder<const A: bool, const B: bool>;
4+
5+
impl<const A: bool> Builder<A, false> {
6+
fn cast(self) -> Builder<A, true> {
7+
Builder
8+
}
9+
}
10+
11+
impl Builder<true, true> {
12+
fn build(self) {}
13+
}
14+
15+
fn main() {
16+
let b = Builder::<false, false>;
17+
b.cast().build();
18+
//~^ ERROR: no method named `build` found for struct `Builder<false, true>` in the current scope
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0599]: no method named `build` found for struct `Builder<false, true>` in the current scope
2+
--> $DIR/lookup-method.rs:17:14
3+
|
4+
LL | struct Builder<const A: bool, const B: bool>;
5+
| -------------------------------------------- method `build` not found for this struct
6+
...
7+
LL | b.cast().build();
8+
| ^^^^^ method not found in `Builder<false, true>`
9+
|
10+
= note: the method was found for
11+
- `Builder<true, true>`
12+
13+
error: aborting due to 1 previous error
14+
15+
For more information about this error, try `rustc --explain E0599`.

0 commit comments

Comments
 (0)