Closed
Description
Code
struct A;
struct B;
struct C;
struct D;
impl A {
fn b(&self) -> B { B }
}
impl B {
fn c(&self) -> C { C }
fn foo(&self) {}
}
impl C {
fn d(&self) -> D { D }
}
impl D {
fn e(&self) {}
}
fn main() {
A.b().c().d().foo();
}
Current output
error[E0599]: no method named `foo` found for struct `D` in the current scope
--> src/main.rs:21:19
|
4 | struct D;
| -------- method `foo` not found for this struct
...
21 | A.b().c().d().foo();
| ^^^ method not found in `D`
Desired output
error[E0599]: no method named `foo` found for struct `D` in the current scope
--> src/main.rs:21:19
|
2 | struct B;
| -------- method `foo` found for this struct
3 | struct C;
4 | struct D;
| -------- method `foo` not found for this struct
...
21 | A.b().c().d().foo();
| ----- ^^^ method not found in `D`
| |
| method `foo` available after this method call
Rationale and extra context
No response
Other cases
No response
Anything else?
Metadata
Metadata
Assignees
Labels
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
iSwapna commentedon Aug 25, 2023
@rustbot claim
iSwapna commentedon Aug 28, 2023
@estebank Hi, I am new to Rust and need some help landing this fix. Would you be the right person to ask questions?
What I have found out so far is that the Diagnostic is generated from here: compiler/rustc_hir_typeck/src/method/suggest.rs:385:22. I think we need to find where in the struct inheritance chain the method appears while walking up the chain from current struct and write out a diagnostic from there. Is that the right way ? If so, is there a compiler pass that will help me walk up the struct chain?
estebank commentedon Aug 28, 2023
Hi @iSwapna! There are two things at play here: typeck which you just found and the HIR (high level intermediate representation) which holds the "hydrated AST", a fancy way of saying "every component bit of code with syntax desugaring applied and access to their type information so far". So what you want to do is look at 468
if let SelfSource::MethodCall(rcvr_expr) = source {
and use thatrcvr_expr
to go up the method chain (the receiver isfoo
infoo.bar()
, if you havefoo.bar().baz()
you'll have aMethodCall(receiver: foo.bar(), path_segment: baz, args: [])
). You can look atrust/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
Line 3731 in 9f48a85
can_eq
we'll be looking at theexpr_ty_adjusted_opt
for each receiver and then callprobe_for_name
with the method name that failed on each of those receivers (like we do innote_derefed_ty_has_method
). Do not hesitate to ask more questions!iSwapna commentedon Sep 5, 2023
@estebank Here is what I have so far:
iSwapna commentedon Sep 5, 2023
I am playing with
err.span_note
in the first instance to understand how to adjust it to generate the correcttype
. But looks like I need to use a different level of diagnostic message to display the first part of expected output:How do I do that?
iSwapna commentedon Sep 11, 2023
Opened a PR as suggested by @oli-obk here: #115229
Auto merge of rust-lang#115229 - iSwapna:issue-115222-fix, r=estebank
Dylan-DPC commentedon Sep 13, 2024
Current output:
So this should be good enough to consider as resolved