None => return Ok(()),
};
+ // Render the replacements for each suggestion
+ let suggestions = suggestion.splice_lines(&**sm);
+
+ if suggestions.is_empty() {
+ // Suggestions coming from macros can have malformed spans. This is a heavy handed
+ // approach to avoid ICEs by ignoring the suggestion outright.
+ return Ok(());
+ }
+
let mut buffer = StyledBuffer::new();
// Render the suggestion message
Some(Style::HeaderMsg),
);
- // Render the replacements for each suggestion
- let suggestions = suggestion.splice_lines(&**sm);
-
let mut row_num = 2;
let mut notice_capitalization = false;
for (complete, parts, only_capitalization) in suggestions.iter().take(MAX_SUGGESTIONS) {
let show_underline = !(parts.len() == 1 && parts[0].snippet.trim() == complete.trim())
&& complete.lines().count() == 1;
- let lines = sm.span_to_lines(parts[0].span).unwrap();
+ let lines = sm
+ .span_to_lines(parts[0].span)
+ .expect("span_to_lines failed when emitting suggestion");
assert!(!lines.lines.is_empty());
// 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 {
.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,
);
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,
);
// 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;
}