Skip to content

Commit 356ff77

Browse files
estebankMark-Simulacrum
authored andcommitted
Do not ICE on malformed suggestion spans
1 parent d97ae99 commit 356ff77

File tree

3 files changed

+28
-5
lines changed

3 files changed

+28
-5
lines changed

src/librustc_errors/emitter.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -1477,6 +1477,11 @@ impl EmitterWriter {
14771477
Some(ref sm) => sm,
14781478
None => return Ok(()),
14791479
};
1480+
if !suggestion.has_valid_spans(&**sm) {
1481+
// Suggestions coming from macros can have malformed spans. This is a heavy handed
1482+
// approach to avoid ICEs by ignoring the suggestion outright.
1483+
return Ok(());
1484+
}
14801485

14811486
let mut buffer = StyledBuffer::new();
14821487

@@ -1507,7 +1512,9 @@ impl EmitterWriter {
15071512
let show_underline = !(parts.len() == 1 && parts[0].snippet.trim() == complete.trim())
15081513
&& complete.lines().count() == 1;
15091514

1510-
let lines = sm.span_to_lines(parts[0].span).unwrap();
1515+
let lines = sm
1516+
.span_to_lines(parts[0].span)
1517+
.expect("span_to_lines failed when emitting suggestion");
15111518

15121519
assert!(!lines.lines.is_empty());
15131520

src/librustc_errors/lib.rs

+13
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
pub use emitter::ColorConfig;
1212

13+
use log::debug;
1314
use Level::*;
1415

1516
use emitter::{is_case_difference, Emitter, EmitterWriter};
@@ -143,6 +144,18 @@ pub struct SubstitutionPart {
143144
}
144145

145146
impl CodeSuggestion {
147+
/// Suggestions coming from macros can have malformed spans. This is a heavy handed approach
148+
/// to avoid ICEs by ignoring the suggestion outright.
149+
pub fn has_valid_spans(&self, cm: &SourceMap) -> bool {
150+
!self.substitutions.iter().any(|subst| {
151+
let invalid = subst.parts.iter().any(|item| cm.is_valid_span(item.span).is_err());
152+
if invalid {
153+
debug!("malformed span in suggestion: {:?}", subst);
154+
}
155+
invalid
156+
})
157+
}
158+
146159
/// Returns the assembled code suggestions, whether they should be shown with an underline
147160
/// and whether the substitution only differs in capitalization.
148161
pub fn splice_lines(&self, cm: &SourceMap) -> Vec<(String, Vec<SubstitutionPart>, bool)> {

src/libsyntax_pos/source_map.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -493,20 +493,23 @@ impl SourceMap {
493493
lo.line != hi.line
494494
}
495495

496-
pub fn span_to_lines(&self, sp: Span) -> FileLinesResult {
497-
debug!("span_to_lines(sp={:?})", sp);
498-
496+
pub fn is_valid_span(&self, sp: Span) -> Result<(Loc, Loc), SpanLinesError> {
499497
let lo = self.lookup_char_pos(sp.lo());
500498
debug!("span_to_lines: lo={:?}", lo);
501499
let hi = self.lookup_char_pos(sp.hi());
502500
debug!("span_to_lines: hi={:?}", hi);
503-
504501
if lo.file.start_pos != hi.file.start_pos {
505502
return Err(SpanLinesError::DistinctSources(DistinctSources {
506503
begin: (lo.file.name.clone(), lo.file.start_pos),
507504
end: (hi.file.name.clone(), hi.file.start_pos),
508505
}));
509506
}
507+
Ok((lo, hi))
508+
}
509+
510+
pub fn span_to_lines(&self, sp: Span) -> FileLinesResult {
511+
debug!("span_to_lines(sp={:?})", sp);
512+
let (lo, hi) = self.is_valid_span(sp)?;
510513
assert!(hi.line >= lo.line);
511514

512515
let mut lines = Vec::with_capacity(hi.line - lo.line + 1);

0 commit comments

Comments
 (0)