about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2020-01-15 09:57:06 -0800
committerEsteban Küber <esteban@kuber.com.ar>2020-01-16 18:14:26 -0800
commit10a9ea4c2622544d52ecef47fea0404a7ce0ace4 (patch)
treeefa08d91a8cd3f999d0f39741222eb497b20ca04 /src
parentecbc222855c890c3aabe4848e8d8b312debcf0ff (diff)
Do not ICE on malformed suggestion spans
Diffstat (limited to 'src')
-rw-r--r--src/librustc_errors/emitter.rs9
-rw-r--r--src/librustc_errors/lib.rs13
-rw-r--r--src/librustc_span/source_map.rs11
-rw-r--r--src/test/ui/consts/miri_unleashed/mutable_const2.stderr2
4 files changed, 29 insertions, 6 deletions
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index 526b4e2971b..e37496f7299 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 e24e8719133..889c84d6da1 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<SubstitutionPart>, bool)> {
diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs
index fb5fcf4a830..9c7c0f0c8b0 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 655c31763ef..cc124058cfc 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