Handle multiple error fix suggestions carefuly
The existing code seems to assume that substitutions spans are disjoint, which is not always the case. In the example: pub trait AAAA {} pub trait B {} pub trait C {} pub type T<P: AAAA + B + C> = P; , we get three substituions starting from ':' and ending respectively at the end of each trait token. With the former offset calculation, this would cause `underline_start` to eventually become negative before being converted to `usize`... The new version may report erroneous results for non perfectly overlapping substitutions but I don't know if such examples exist. Alternatively, we could detect these cases and trim out overlapping substitutions.
This commit is contained in:
parent
760ce94c69
commit
12545c75ff
|
@ -1530,7 +1530,7 @@ impl EmitterWriter {
|
|||
|
||||
// This offset and the ones below need to be signed to account for replacement code
|
||||
// that is shorter than the original code.
|
||||
let mut offset: isize = 0;
|
||||
let mut offsets: Vec<(usize, isize)> = Vec::new();
|
||||
// Only show an underline in the suggestions if the suggestion is not the
|
||||
// entirety of the code being shown and the displayed code is not multiline.
|
||||
if show_underline {
|
||||
|
@ -1550,12 +1550,19 @@ impl EmitterWriter {
|
|||
.map(|ch| unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1))
|
||||
.sum();
|
||||
|
||||
let offset: isize = offsets
|
||||
.iter()
|
||||
.filter_map(
|
||||
|(start, v)| if span_start_pos <= *start { None } else { Some(v) },
|
||||
)
|
||||
.sum();
|
||||
let underline_start = (span_start_pos + start) as isize + offset;
|
||||
let underline_end = (span_start_pos + start + sub_len) as isize + offset;
|
||||
assert!(underline_start >= 0 && underline_end >= 0);
|
||||
for p in underline_start..underline_end {
|
||||
buffer.putc(
|
||||
row_num,
|
||||
max_line_num_len + 3 + p as usize,
|
||||
((max_line_num_len + 3) as isize + p) as usize,
|
||||
'^',
|
||||
Style::UnderlinePrimary,
|
||||
);
|
||||
|
@ -1565,7 +1572,7 @@ impl EmitterWriter {
|
|||
for p in underline_start - 1..underline_start + 1 {
|
||||
buffer.putc(
|
||||
row_num,
|
||||
max_line_num_len + 3 + p as usize,
|
||||
((max_line_num_len + 3) as isize + p) as usize,
|
||||
'-',
|
||||
Style::UnderlineSecondary,
|
||||
);
|
||||
|
@ -1582,8 +1589,9 @@ impl EmitterWriter {
|
|||
// length of the code to be substituted
|
||||
let snippet_len = span_end_pos as isize - span_start_pos as isize;
|
||||
// For multiple substitutions, use the position *after* the previous
|
||||
// substitutions have happened.
|
||||
offset += full_sub_len - snippet_len;
|
||||
// substitutions have happened, only when further substitutions are
|
||||
// located strictly after.
|
||||
offsets.push((span_end_pos, full_sub_len - snippet_len));
|
||||
}
|
||||
row_num += 1;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// Regression test for issue #67690
|
||||
// Rustc endless loop out-of-memory and consequent SIGKILL in generic new type
|
||||
|
||||
// check-pass
|
||||
pub type T<P: Send + Send + Send> = P;
|
||||
//~^ WARN bounds on generic parameters are not enforced in type aliases
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,12 @@
|
|||
warning: bounds on generic parameters are not enforced in type aliases
|
||||
--> $DIR/issue-67690-type-alias-bound-diagnostic-crash.rs:5:15
|
||||
|
|
||||
LL | pub type T<P: Send + Send + Send> = P;
|
||||
| ^^^^ ^^^^ ^^^^
|
||||
|
|
||||
= 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
|
||||
|
|
||||
LL | pub type T<P> = P;
|
||||
| --
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
// Test `ignored_generic_bounds` lint warning about bounds in type aliases.
|
||||
|
||||
// build-pass (FIXME(62277): could be check-pass?)
|
||||
// check-pass
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::rc::Rc;
|
||||
|
|
|
@ -8,7 +8,7 @@ LL | type SVec<T: Send + Send> = Vec<T>;
|
|||
help: the bound will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL | type SVec<T> = Vec<T>;
|
||||
| -- --
|
||||
| --
|
||||
|
||||
warning: where clauses are not enforced in type aliases
|
||||
--> $DIR/type-alias-bounds.rs:10:21
|
||||
|
@ -30,7 +30,7 @@ LL | type VVec<'b, 'a: 'b + 'b> = (&'b u32, Vec<&'a i32>);
|
|||
help: the bound will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL | type VVec<'b, 'a> = (&'b u32, Vec<&'a i32>);
|
||||
| -- --
|
||||
| --
|
||||
|
||||
warning: bounds on generic parameters are not enforced in type aliases
|
||||
--> $DIR/type-alias-bounds.rs:14:18
|
||||
|
@ -41,7 +41,7 @@ LL | type WVec<'b, T: 'b + 'b> = (&'b u32, Vec<T>);
|
|||
help: the bound will not be checked when the type alias is used, and should be removed
|
||||
|
|
||||
LL | type WVec<'b, T> = (&'b u32, Vec<T>);
|
||||
| -- --
|
||||
| --
|
||||
|
||||
warning: where clauses are not enforced in type aliases
|
||||
--> $DIR/type-alias-bounds.rs:16:25
|
||||
|
|
Loading…
Reference in New Issue