Skip to content

Commit 6d9913d

Browse files
authored
Rollup merge of rust-lang#67880 - lbonn:fix/multi-substs, r=petrochenkov
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. Fixes rust-lang#67690
2 parents 74ca7c7 + 12545c7 commit 6d9913d

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)