Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

only find segs chain for missing methods when no available candidates #125080

Merged
merged 1 commit into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 33 additions & 6 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1143,7 +1143,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}

let label_span_not_found = |err: &mut Diag<'_>| {
let mut find_candidate_for_method = false;

let mut label_span_not_found = |err: &mut Diag<'_>| {
if unsatisfied_predicates.is_empty() {
err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
let is_string_or_ref_str = match rcvr_ty.kind() {
Expand Down Expand Up @@ -1219,6 +1221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.note(format!(
"the {item_kind} was found for\n{type_candidates}{additional_types}"
));
find_candidate_for_method = mode == Mode::MethodCall;
}
}
} else {
Expand Down Expand Up @@ -1371,9 +1374,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
}
// If an appropriate error source is not found, check method chain for possible candiates
if unsatisfied_predicates.is_empty()
&& let Mode::MethodCall = mode

if !find_candidate_for_method {
self.lookup_segments_chain_for_no_match_method(
&mut err,
item_name,
item_kind,
source,
no_match_data,
);
}

self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected);
Some(err)
}

/// If an appropriate error source is not found, check method chain for possible candidates
fn lookup_segments_chain_for_no_match_method(
&self,
err: &mut Diag<'_>,
item_name: Ident,
item_kind: &str,
source: SelfSource<'tcx>,
no_match_data: &NoMatchData<'tcx>,
) {
if no_match_data.unsatisfied_predicates.is_empty()
&& let Mode::MethodCall = no_match_data.mode
&& let SelfSource::MethodCall(mut source_expr) = source
{
let mut stack_methods = vec![];
Expand All @@ -1394,6 +1420,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.unwrap_or(Ty::new_misc_error(self.tcx)),
);

// FIXME: `probe_for_name_many` searches for methods in inherent implementations,
// so it may return a candidate that doesn't belong to this `revr_ty`. We need to
// check whether the instantiated type matches the received one.
for _matched_method in self.probe_for_name_many(
Mode::MethodCall,
item_name,
Expand All @@ -1416,8 +1445,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
}
self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected);
Some(err)
}

fn find_likely_intended_associated_item(
Expand Down
19 changes: 19 additions & 0 deletions tests/ui/const-generics/lookup-method.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// https://github.com/rust-lang/rust/issues/124946

struct Builder<const A: bool, const B: bool>;

impl<const A: bool> Builder<A, false> {
fn cast(self) -> Builder<A, true> {
Builder
}
}

impl Builder<true, true> {
fn build(self) {}
}

fn main() {
let b = Builder::<false, false>;
b.cast().build();
//~^ ERROR: no method named `build` found for struct `Builder<false, true>` in the current scope
}
15 changes: 15 additions & 0 deletions tests/ui/const-generics/lookup-method.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error[E0599]: no method named `build` found for struct `Builder<false, true>` in the current scope
--> $DIR/lookup-method.rs:17:14
|
LL | struct Builder<const A: bool, const B: bool>;
| -------------------------------------------- method `build` not found for this struct
...
LL | b.cast().build();
| ^^^^^ method not found in `Builder<false, true>`
|
= note: the method was found for
- `Builder<true, true>`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0599`.
Loading