Description
Given the following code: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=0bc82986aeab6421699562569505aa40
trait A<T> {
fn a(&self) -> &T;
}
struct B {}
impl<T> A<B> for T {} // <-- error[E0046]: not all trait items implemented, missing: `a`
The current output is:
(Note: The whitespace in strings is probably not real due to my manual JSON prettification.)
compiler-message json
{
"reason": "compiler-message",
"package_id": "scraps-again 0.1.0 (path+file:///C:/Users/Tamme/Documents/Projekte/scraps-again)",
"manifest_path": "C:\\Users\\Tamme\\Documents\\Projekte\\scraps-again\\Cargo.toml",
"target": {
"kind": [
"lib"
],
"crate_types": [
"lib"
],
"name": "scraps-again",
"src_path": "C:\\Users\\Tamme\\Documents\\Projekte\\scraps-again\\src\\lib.rs",
"edition": "2018",
"doc": true,
"doctest": true,
"test": true
},
"message": {
"rendered": "error[E0046]: not all trait items implemented, missing: `a`\n --> src\\lib.rs: 6: 1\n |\n2 | fn a(&self) -> &T;\n | ------------------ `a` from trait\n...\n6 | impl<T> A<B> for T {}\n | ^^^^^^^^^^^^^^^^^^ missing `a` in implementation\n\n",
"children": [
{
"children": [],
"code": null,
"level": "help",
"message": "implement the missing item: `fn a(&self) -> &T { todo!() }`",
"rendered": null,
"spans": [
{
"byte_end": 71,
"byte_start": 71,
"column_end": 21,
"column_start": 21,
"expansion": null,
"file_name": "src\\lib.rs",
"is_primary": true,
"label": null,
"line_end": 6,
"line_start": 6,
"suggested_replacement": "fn a(&self) -> &T { todo!() }\n",
"suggestion_applicability": "HasPlaceholders",
"text": [
{
"highlight_end": 21,
"highlight_start": 21,
"text": "impl<T> A<B> for T {}"
}
]
}
]
}
],
"code": {
"code": "E0046",
"explanation": "Items are missing in a trait implementation.\n\nErroneous code example:\n\n```compile_fail,E0046\ntrait Foo {\n fn foo();\n }\n\nstruct Bar;\n\nimpl Foo for Bar {}\n // error: not all trait items implemented, missing: `foo`\n```\n\nWhen trying to make some type implement a trait `Foo`, you must, at minimum,\nprovide implementations for all of `Foo`'s required methods (meaning the\nmethods that do not have default implementations), as well as any required\ntrait items like associated types or constants. Example:\n\n```\ntrait Foo {\n fn foo();\n}\n\nstruct Bar;\n\nimpl Foo for Bar {\n fn foo() {} // ok!\n}\n```\n"
},
"level": "error",
"message": "not all trait items implemented, missing: `a`",
"spans": [
{
"byte_end": 69,
"byte_start": 51,
"column_end": 19,
"column_start": 1,
"expansion": null,
"file_name": "src\\lib.rs",
"is_primary": true,
"label": "missing `a` in implementation",
"line_end": 6,
"line_start": 6,
"suggested_replacement": null,
"suggestion_applicability": null,
"text": [
{
"highlight_end": 19,
"highlight_start": 1,
"text": "impl<T> A<B> for T {}"
}
]
},
{
"byte_end": 35,
"byte_start": 17,
"column_end": 23,
"column_start": 5,
"expansion": null,
"file_name": "src\\lib.rs",
"is_primary": false,
"label": "`a` from trait",
"line_end": 2,
"line_start": 2,
"suggested_replacement": null,
"suggestion_applicability": null,
"text": [
{
"highlight_end": 23,
"highlight_start": 5,
"text": " fn a(&self) -> &T;"
}
]
}
]
}
}
(with "suggested_replacement": "fn a(&self) -> &T { todo!() }\n"
and its message being invalid)
Ideally the output should look like:
compiler-message json
{
"reason": "compiler-message",
"package_id": "scraps-again 0.1.0 (path+file:///C:/Users/Tamme/Documents/Projekte/scraps-again)",
"manifest_path": "C:\\Users\\Tamme\\Documents\\Projekte\\scraps-again\\Cargo.toml",
"target": {
"kind": [
"lib"
],
"crate_types": [
"lib"
],
"name": "scraps-again",
"src_path": "C:\\Users\\Tamme\\Documents\\Projekte\\scraps-again\\src\\lib.rs",
"edition": "2018",
"doc": true,
"doctest": true,
"test": true
},
"message": {
"rendered": "error[E0046]: not all trait items implemented, missing: `a`\n --> src\\lib.rs: 6: 1\n |\n2 | fn a(&self) -> &T;\n | ------------------ `a` from trait\n...\n6 | impl<T> A<B> for T {}\n | ^^^^^^^^^^^^^^^^^^ missing `a` in implementation\n\n",
"children": [
{
"children": [],
"code": null,
"level": "help",
"message": "implement the missing item: `fn a(&self) -> &B { todo!() }`",
"rendered": null,
"spans": [
{
"byte_end": 71,
"byte_start": 71,
"column_end": 21,
"column_start": 21,
"expansion": null,
"file_name": "src\\lib.rs",
"is_primary": true,
"label": null,
"line_end": 6,
"line_start": 6,
"suggested_replacement": "fn a(&self) -> &B { todo!() }\n",
"suggestion_applicability": "HasPlaceholders",
"text": [
{
"highlight_end": 21,
"highlight_start": 21,
"text": "impl<T> A<B> for T {}"
}
]
}
]
}
],
"code": {
"code": "E0046",
"explanation": "Items are missing in a trait implementation.\n\nErroneous code example:\n\n```compile_fail,E0046\ntrait Foo {\n fn foo();\n }\n\nstruct Bar;\n\nimpl Foo for Bar {}\n // error: not all trait items implemented, missing: `foo`\n```\n\nWhen trying to make some type implement a trait `Foo`, you must, at minimum,\nprovide implementations for all of `Foo`'s required methods (meaning the\nmethods that do not have default implementations), as well as any required\ntrait items like associated types or constants. Example:\n\n```\ntrait Foo {\n fn foo();\n}\n\nstruct Bar;\n\nimpl Foo for Bar {\n fn foo() {} // ok!\n}\n```\n"
},
"level": "error",
"message": "not all trait items implemented, missing: `a`",
"spans": [
{
"byte_end": 69,
"byte_start": 51,
"column_end": 19,
"column_start": 1,
"expansion": null,
"file_name": "src\\lib.rs",
"is_primary": true,
"label": "missing `a` in implementation",
"line_end": 6,
"line_start": 6,
"suggested_replacement": null,
"suggestion_applicability": null,
"text": [
{
"highlight_end": 19,
"highlight_start": 1,
"text": "impl<T> A<B> for T {}"
}
]
},
{
"byte_end": 35,
"byte_start": 17,
"column_end": 23,
"column_start": 5,
"expansion": null,
"file_name": "src\\lib.rs",
"is_primary": false,
"label": "`a` from trait",
"line_end": 2,
"line_start": 2,
"suggested_replacement": null,
"suggestion_applicability": null,
"text": [
{
"highlight_end": 23,
"highlight_start": 5,
"text": " fn a(&self) -> &T;"
}
]
}
]
}
}
(with "suggested_replacement": "fn a(&self) -> &B { todo!() }\n"
and its message being valid)
This seems like something the compiler could in theory take care of, and it's not always immediately clear to the programmer (that is: me) why exactly there's an error highlighted if there's another T
like in the example above.
That said, the error message resulting from the invalid suggestion already does a fairly decent job of pointing out the fix here, and the suggestion there ("change the output type to match the trait: &B
") is correct.
I first misfiled this as rust-lang/rust-analyzer#10327 after reporting rust-lang/rust-analyzer#10326. If the generic type parameter is expanded to something like dyn 'a + Trait
, it would also need to be parenthesised in some cases.