Prompted by #24626 and #28011, I created PR 36371 to include the type of missing trait items in errors. While working on this it became obvious that there were two ways of presenting the signature of missing methods:
- show a pretty printed or one lined version of the signatures for the missing methods
- show the full span for the method definitions
These two approaches have different problems. For the former, it means reimplementing (or generalizing) the code from rustdoc
's AST pretty printer. The second one as the compiler stands now is deficient for method definitions that span multiple lines, as you’d get only the first line presented to you, and you’re back where we started, with incomplete information to fully implement the missing method.
My proposal is to use the actual code as it exists (if the compiler has access to it), and start supporting multiline spans. This support could be limited to X lines, in order to avoid spitting out hundreds of unnecessary lines, in those cases doing what we’re currently doing, point at the first character of the first line.
My proposal for how this would look like one completed, allowing for composability of multiple multispans sharing lines is as follows:
error[E0046]: not all trait items implemented, missing: `bar`, `bay`
--> file.rs:27:1
|
15 | fn bar();
| --------- `bar` from trait
...
16 | ┌ fn bay<'lifetime,
| â•Ž ^^^ showing off an error
17 | â•Ž TypeParameterA
18 | â•Ž
19 | ╎ ┌ >( a : usize,
| â•Ž â•Ž ----------- error
20 | â•Ž â•Ž b: u8 );
| └╴┼╴╴╴╴^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ some error
| └╴╴╴╴╴╴╴╴╴╴╴╴╴---------------- overlapped errors to show off how it could look like
...
27 | impl X<usize> for A {
| ^ missing `bar`, `bay` in implementation
Other possible ways to present this have been mentioned in the previously mentioned PR:
Right bracketing:
--> missing-impls.rs:11:5
|
11 | fn bay< â•® `bay` from trait
12 | 'lifetime, TypeParameterA |
13 | >( a : usize, |
14 | b: u8 ); â•Ż
Similar to the previous one:
foo(1 + bar(x, <| wrong type
y), <|
z);
Fully enclosing the code (I feel this one as cool as it is, it might be too confusing):
+-------+
v |
foo(1 + bar(x, | wrong type
y), |
^ |
+-+
z);
The other option is to just present the recreated signature from the AST (or even from the actual code, as lifetime information/labels seems to be discarded in the AST), but since there’s already a great way of presenting code and where it comes from, I feel that the presented option is better.
Thoughts?