Some suggestions include overlapping regions. These cause rustfix to fail with an error like:
Could not replace range 22...47 in file -- maybe parts of it were already replaced?
An example that triggers this is the following where multiple trait bounds are to be removed:
pub type MyResult<T, E: std::error::Error + Send + Sync> = Result<T, E>;
This results in the following suggestion:
warning: bounds on generic parameters are not enforced in type aliases
--> src/main.rs:1:25
|
1 | pub type MyResult<T, E: std::error::Error + Send + Sync> = Result<T, E>;
| ^^^^^^^^^^^^^^^^^ ^^^^ ^^^^
|
= note: `#[warn(type_alias_bounds)]` on by default
help: the bound will not be checked when the type alias is used, and should be removed
|
1 - pub type MyResult<T, E: std::error::Error + Send + Sync> = Result<T, E>;
1 + pub type MyResult<T, E> = Result<T, E>;
|
With the suggested JSON:
{
"reason": "compiler-message",
"package_id": "z2 0.1.0 (path+file:///foo)",
"manifest_path": "/foo/Cargo.toml",
"target":
{
"kind":
[
"bin"
],
"crate_types":
[
"bin"
],
"name": "z2",
"src_path": "/foo/src/main.rs",
"edition": "2018",
"doc": true,
"doctest": false,
"test": true
},
"message":
{
"rendered": "warning: bounds on generic parameters are not enforced in type aliases\n --> src/main.rs:1:25\n |\n1 | pub type MyResult<T, E: std::error::Error + Send + Sync> = Result<T, E>;\n | ^^^^^^^^^^^^^^^^^ ^^^^ ^^^^\n |\n = note: `#[warn(type_alias_bounds)]` on by default\nhelp: the bound will not be checked when the type alias is used, and should be removed\n |\n1 - pub type MyResult<T, E: std::error::Error + Send + Sync> = Result<T, E>;\n1 + pub type MyResult<T, E> = Result<T, E>;\n | \n\n",
"children":
[
{
"children":
[],
"code": null,
"level": "note",
"message": "`#[warn(type_alias_bounds)]` on by default",
"rendered": null,
"spans":
[]
},
{
"children":
[],
"code": null,
"level": "help",
"message": "the bound will not be checked when the type alias is used, and should be removed",
"rendered": null,
"spans":
[
{
"byte_end": 41,
"byte_start": 22,
"column_end": 42,
"column_start": 23,
"expansion": null,
"file_name": "src/main.rs",
"is_primary": true,
"label": null,
"line_end": 1,
"line_start": 1,
"suggested_replacement": "",
"suggestion_applicability": "MachineApplicable",
"text":
[
{
"highlight_end": 42,
"highlight_start": 23,
"text": "pub type MyResult<T, E: std::error::Error + Send + Sync> = Result<T, E>;"
}
]
},
{
"byte_end": 48,
"byte_start": 22,
"column_end": 49,
"column_start": 23,
"expansion": null,
"file_name": "src/main.rs",
"is_primary": true,
"label": null,
"line_end": 1,
"line_start": 1,
"suggested_replacement": "",
"suggestion_applicability": "MachineApplicable",
"text":
[
{
"highlight_end": 49,
"highlight_start": 23,
"text": "pub type MyResult<T, E: std::error::Error + Send + Sync> = Result<T, E>;"
}
]
},
{
"byte_end": 55,
"byte_start": 22,
"column_end": 56,
"column_start": 23,
"expansion": null,
"file_name": "src/main.rs",
"is_primary": true,
"label": null,
"line_end": 1,
"line_start": 1,
"suggested_replacement": "",
"suggestion_applicability": "MachineApplicable",
"text":
[
{
"highlight_end": 56,
"highlight_start": 23,
"text": "pub type MyResult<T, E: std::error::Error + Send + Sync> = Result<T, E>;"
}
]
}
]
}
],
"code":
{
"code": "type_alias_bounds",
"explanation": null
},
"level": "warning",
"message": "bounds on generic parameters are not enforced in type aliases",
"spans":
[
{
"byte_end": 41,
"byte_start": 24,
"column_end": 42,
"column_start": 25,
"expansion": null,
"file_name": "src/main.rs",
"is_primary": true,
"label": null,
"line_end": 1,
"line_start": 1,
"suggested_replacement": null,
"suggestion_applicability": null,
"text":
[
{
"highlight_end": 42,
"highlight_start": 25,
"text": "pub type MyResult<T, E: std::error::Error + Send + Sync> = Result<T, E>;"
}
]
},
{
"byte_end": 48,
"byte_start": 44,
"column_end": 49,
"column_start": 45,
"expansion": null,
"file_name": "src/main.rs",
"is_primary": true,
"label": null,
"line_end": 1,
"line_start": 1,
"suggested_replacement": null,
"suggestion_applicability": null,
"text":
[
{
"highlight_end": 49,
"highlight_start": 45,
"text": "pub type MyResult<T, E: std::error::Error + Send + Sync> = Result<T, E>;"
}
]
},
{
"byte_end": 55,
"byte_start": 51,
"column_end": 56,
"column_start": 52,
"expansion": null,
"file_name": "src/main.rs",
"is_primary": true,
"label": null,
"line_end": 1,
"line_start": 1,
"suggested_replacement": null,
"suggestion_applicability": null,
"text":
[
{
"highlight_end": 56,
"highlight_start": 52,
"text": "pub type MyResult<T, E: std::error::Error + Send + Sync> = Result<T, E>;"
}
]
}
]
}
}
This has three overlapping spans that suggest a replacement of an empty string:
I think it might be feasible to support this. At least, the new diff output from rustc is able to handle it, and clicking the "fix" suggestions in my editor is able to handle it (the regions are "smart" and know when the text within it is modified).
Note: This is relatively new behavior introduced by #195.