From 10a9ea4c2622544d52ecef47fea0404a7ce0ace4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 15 Jan 2020 09:57:06 -0800 Subject: [PATCH 1/2] Do not ICE on malformed suggestion spans --- src/librustc_errors/emitter.rs | 9 ++++++++- src/librustc_errors/lib.rs | 13 +++++++++++++ src/librustc_span/source_map.rs | 11 +++++++---- .../ui/consts/miri_unleashed/mutable_const2.stderr | 2 +- 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 526b4e2971bef..e37496f729952 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -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()); diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index e24e8719133a9..889c84d6da132 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -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, bool)> { diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs index fb5fcf4a8303b..9c7c0f0c8b0ec 100644 --- a/src/librustc_span/source_map.rs +++ b/src/librustc_span/source_map.rs @@ -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); diff --git a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr index 655c31763ef44..cc124058cfcb8 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr +++ b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr @@ -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 From 03240e1359f68bdddcdb236f3a89f9907b907449 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 16 Jan 2020 18:27:18 -0800 Subject: [PATCH 2/2] review comments --- src/librustc_errors/emitter.rs | 9 ++++---- src/librustc_errors/lib.rs | 21 ++++++++----------- .../miri_unleashed/mutable_const2.stderr | 2 +- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index e37496f729952..b0e0cb611afaf 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -1475,7 +1475,11 @@ impl EmitterWriter { Some(ref sm) => sm, None => return Ok(()), }; - if !suggestion.has_valid_spans(&**sm) { + + // 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(()); @@ -1497,9 +1501,6 @@ impl EmitterWriter { 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) { diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 889c84d6da132..827e9b831f32d 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -144,18 +144,6 @@ 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, bool)> { @@ -187,6 +175,15 @@ impl CodeSuggestion { self.substitutions .iter() + .filter(|subst| { + // Suggestions coming from macros can have malformed spans. This is a heavy + // handed approach to avoid ICEs by ignoring the suggestion outright. + let invalid = subst.parts.iter().any(|item| cm.is_valid_span(item.span).is_err()); + if invalid { + debug!("splice_lines: suggestion contains an invalid span: {:?}", subst); + } + !invalid + }) .cloned() .map(|mut substitution| { // Assumption: all spans are in the same file, and all spans diff --git a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr index cc124058cfcb8..0d7fb845a40ee 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr +++ b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr @@ -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:359:17 +thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:356:17 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace error: internal compiler error: unexpected panic