Skip to content

Commit 12545c7

Browse files
committed
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.
1 parent 760ce94 commit 12545c7

5 files changed

+37
-9
lines changed

src/librustc_errors/emitter.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -1530,7 +1530,7 @@ impl EmitterWriter {
15301530

15311531
// This offset and the ones below need to be signed to account for replacement code
15321532
// that is shorter than the original code.
1533-
let mut offset: isize = 0;
1533+
let mut offsets: Vec<(usize, isize)> = Vec::new();
15341534
// Only show an underline in the suggestions if the suggestion is not the
15351535
// entirety of the code being shown and the displayed code is not multiline.
15361536
if show_underline {
@@ -1550,12 +1550,19 @@ impl EmitterWriter {
15501550
.map(|ch| unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1))
15511551
.sum();
15521552

1553+
let offset: isize = offsets
1554+
.iter()
1555+
.filter_map(
1556+
|(start, v)| if span_start_pos <= *start { None } else { Some(v) },
1557+
)
1558+
.sum();
15531559
let underline_start = (span_start_pos + start) as isize + offset;
15541560
let underline_end = (span_start_pos + start + sub_len) as isize + offset;
1561+
assert!(underline_start >= 0 && underline_end >= 0);
15551562
for p in underline_start..underline_end {
15561563
buffer.putc(
15571564
row_num,
1558-
max_line_num_len + 3 + p as usize,
1565+
((max_line_num_len + 3) as isize + p) as usize,
15591566
'^',
15601567
Style::UnderlinePrimary,
15611568
);
@@ -1565,7 +1572,7 @@ impl EmitterWriter {
15651572
for p in underline_start - 1..underline_start + 1 {
15661573
buffer.putc(
15671574
row_num,
1568-
max_line_num_len + 3 + p as usize,
1575+
((max_line_num_len + 3) as isize + p) as usize,
15691576
'-',
15701577
Style::UnderlineSecondary,
15711578
);
@@ -1582,8 +1589,9 @@ impl EmitterWriter {
15821589
// length of the code to be substituted
15831590
let snippet_len = span_end_pos as isize - span_start_pos as isize;
15841591
// For multiple substitutions, use the position *after* the previous
1585-
// substitutions have happened.
1586-
offset += full_sub_len - snippet_len;
1592+
// substitutions have happened, only when further substitutions are
1593+
// located strictly after.
1594+
offsets.push((span_end_pos, full_sub_len - snippet_len));
15871595
}
15881596
row_num += 1;
15891597
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Regression test for issue #67690
2+
// Rustc endless loop out-of-memory and consequent SIGKILL in generic new type
3+
4+
// check-pass
5+
pub type T<P: Send + Send + Send> = P;
6+
//~^ WARN bounds on generic parameters are not enforced in type aliases
7+
8+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
warning: bounds on generic parameters are not enforced in type aliases
2+
--> $DIR/issue-67690-type-alias-bound-diagnostic-crash.rs:5:15
3+
|
4+
LL | pub type T<P: Send + Send + Send> = P;
5+
| ^^^^ ^^^^ ^^^^
6+
|
7+
= note: `#[warn(type_alias_bounds)]` on by default
8+
help: the bound will not be checked when the type alias is used, and should be removed
9+
|
10+
LL | pub type T<P> = P;
11+
| --
12+

src/test/ui/type/type-alias-bounds.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Test `ignored_generic_bounds` lint warning about bounds in type aliases.
22

3-
// build-pass (FIXME(62277): could be check-pass?)
3+
// check-pass
44
#![allow(dead_code)]
55

66
use std::rc::Rc;

src/test/ui/type/type-alias-bounds.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LL | type SVec<T: Send + Send> = Vec<T>;
88
help: the bound will not be checked when the type alias is used, and should be removed
99
|
1010
LL | type SVec<T> = Vec<T>;
11-
| -- --
11+
| --
1212

1313
warning: where clauses are not enforced in type aliases
1414
--> $DIR/type-alias-bounds.rs:10:21
@@ -30,7 +30,7 @@ LL | type VVec<'b, 'a: 'b + 'b> = (&'b u32, Vec<&'a i32>);
3030
help: the bound will not be checked when the type alias is used, and should be removed
3131
|
3232
LL | type VVec<'b, 'a> = (&'b u32, Vec<&'a i32>);
33-
| -- --
33+
| --
3434

3535
warning: bounds on generic parameters are not enforced in type aliases
3636
--> $DIR/type-alias-bounds.rs:14:18
@@ -41,7 +41,7 @@ LL | type WVec<'b, T: 'b + 'b> = (&'b u32, Vec<T>);
4141
help: the bound will not be checked when the type alias is used, and should be removed
4242
|
4343
LL | type WVec<'b, T> = (&'b u32, Vec<T>);
44-
| -- --
44+
| --
4545

4646
warning: where clauses are not enforced in type aliases
4747
--> $DIR/type-alias-bounds.rs:16:25

0 commit comments

Comments
 (0)