Do not ICE on malformed suggestion spans

This commit is contained in:
Esteban Küber 2020-01-15 09:57:06 -08:00
parent ecbc222855
commit 10a9ea4c26
4 changed files with 29 additions and 6 deletions

View file

@ -1475,6 +1475,11 @@ impl EmitterWriter {
Some(ref sm) => sm,
None => return Ok(()),
};
if !suggestion.has_valid_spans(&**sm) {
// 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();
@ -1505,7 +1510,9 @@ impl EmitterWriter {
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());

View file

@ -10,6 +10,7 @@
pub use emitter::ColorConfig;
use log::debug;
use Level::*;
use emitter::{is_case_difference, Emitter, EmitterWriter};
@ -143,6 +144,18 @@ pub struct SubstitutionPart {
}
impl CodeSuggestion {
/// Suggestions coming from macros can have malformed spans. This is a heavy handed approach
/// to avoid ICEs by ignoring the suggestion outright.
pub fn has_valid_spans(&self, cm: &SourceMap) -> bool {
!self.substitutions.iter().any(|subst| {
let invalid = subst.parts.iter().any(|item| cm.is_valid_span(item.span).is_err());
if invalid {
debug!("malformed span in suggestion: {:?}", subst);
}
invalid
})
}
/// Returns the assembled code suggestions, whether they should be shown with an underline
/// and whether the substitution only differs in capitalization.
pub fn splice_lines(&self, cm: &SourceMap) -> Vec<(String, Vec<SubstitutionPart>, bool)> {

View file

@ -473,20 +473,23 @@ impl SourceMap {
lo.line != hi.line
}
pub fn span_to_lines(&self, sp: Span) -> FileLinesResult {
debug!("span_to_lines(sp={:?})", sp);
pub fn is_valid_span(&self, sp: Span) -> Result<(Loc, Loc), SpanLinesError> {
let lo = self.lookup_char_pos(sp.lo());
debug!("span_to_lines: lo={:?}", lo);
let hi = self.lookup_char_pos(sp.hi());
debug!("span_to_lines: hi={:?}", hi);
if lo.file.start_pos != hi.file.start_pos {
return Err(SpanLinesError::DistinctSources(DistinctSources {
begin: (lo.file.name.clone(), lo.file.start_pos),
end: (hi.file.name.clone(), hi.file.start_pos),
}));
}
Ok((lo, hi))
}
pub fn span_to_lines(&self, sp: Span) -> FileLinesResult {
debug!("span_to_lines(sp={:?})", sp);
let (lo, hi) = self.is_valid_span(sp)?;
assert!(hi.line >= lo.line);
let mut lines = Vec::with_capacity(hi.line - lo.line + 1);

View file

@ -10,7 +10,7 @@ error: internal compiler error: mutable allocation in constant
LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:346:17
thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:359:17
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: internal compiler error: unexpected panic