]> git.proxmox.com Git - rustc.git/blobdiff - src/librustc_errors/lib.rs
New upstream version 1.44.1+dfsg1
[rustc.git] / src / librustc_errors / lib.rs
index f0e388a597b408ff554449d657ecc0c20e70bbb9..151241fdb0b5f6cd5d85b3d44df0bcebd2e1ba8a 100644 (file)
@@ -194,7 +194,12 @@ impl CodeSuggestion {
                 let bounding_span = Span::with_root_ctxt(lo, hi);
                 // The different spans might belong to different contexts, if so ignore suggestion.
                 let lines = sm.span_to_lines(bounding_span).ok()?;
-                assert!(!lines.lines.is_empty());
+                assert!(!lines.lines.is_empty() || bounding_span.is_dummy());
+
+                // We can't splice anything if the source is unavailable.
+                if !sm.ensure_source_file_source_present(lines.file.clone()) {
+                    return None;
+                }
 
                 // To build up the result, we do this for each span:
                 // - push the line segment trailing the previous span
@@ -208,8 +213,8 @@ impl CodeSuggestion {
                 let sf = &lines.file;
                 let mut prev_hi = sm.lookup_char_pos(bounding_span.lo());
                 prev_hi.col = CharPos::from_usize(0);
-
-                let mut prev_line = sf.get_line(lines.lines[0].line_index);
+                let mut prev_line =
+                    lines.lines.get(0).and_then(|line0| sf.get_line(line0.line_index));
                 let mut buf = String::new();
 
                 for part in &substitution.parts {
@@ -226,7 +231,10 @@ impl CodeSuggestion {
                             }
                         }
                         if let Some(cur_line) = sf.get_line(cur_lo.line - 1) {
-                            let end = std::cmp::min(cur_line.len(), cur_lo.col.to_usize());
+                            let end = match cur_line.char_indices().nth(cur_lo.col.to_usize()) {
+                                Some((i, _)) => i,
+                                None => cur_line.len(),
+                            };
                             buf.push_str(&cur_line[..end]);
                         }
                     }
@@ -307,6 +315,9 @@ struct HandlerInner {
     /// The stashed diagnostics count towards the total error count.
     /// When `.abort_if_errors()` is called, these are also emitted.
     stashed_diagnostics: FxIndexMap<(Span, StashKey), Diagnostic>,
+
+    /// The warning count, used for a recap upon finishing
+    deduplicated_warn_count: usize,
 }
 
 /// A key denoting where from a diagnostic was stashed.
@@ -409,6 +420,7 @@ impl Handler {
                 flags,
                 err_count: 0,
                 deduplicated_err_count: 0,
+                deduplicated_warn_count: 0,
                 emitter,
                 delayed_span_bugs: Vec::new(),
                 taught_diagnostics: Default::default(),
@@ -420,7 +432,7 @@ impl Handler {
     }
 
     // This is here to not allow mutation of flags;
-    // as of this writing it's only used in tests in librustc.
+    // as of this writing it's only used in tests in librustc_middle.
     pub fn can_emit_warnings(&self) -> bool {
         self.flags.can_emit_warnings
     }
@@ -434,6 +446,7 @@ impl Handler {
         let mut inner = self.inner.borrow_mut();
         inner.err_count = 0;
         inner.deduplicated_err_count = 0;
+        inner.deduplicated_warn_count = 0;
 
         // actually free the underlying memory (which `clear` would not do)
         inner.delayed_span_bugs = Default::default();
@@ -740,6 +753,8 @@ impl HandlerInner {
             self.emitter.emit_diagnostic(diagnostic);
             if diagnostic.is_error() {
                 self.deduplicated_err_count += 1;
+            } else if diagnostic.level == Warning {
+                self.deduplicated_warn_count += 1;
             }
         }
         if diagnostic.is_error() {
@@ -758,8 +773,13 @@ impl HandlerInner {
     fn print_error_count(&mut self, registry: &Registry) {
         self.emit_stashed_diagnostics();
 
-        let s = match self.deduplicated_err_count {
-            0 => return,
+        let warnings = match self.deduplicated_warn_count {
+            0 => String::new(),
+            1 => "1 warning emitted".to_string(),
+            count => format!("{} warnings emitted", count),
+        };
+        let errors = match self.deduplicated_err_count {
+            0 => String::new(),
             1 => "aborting due to previous error".to_string(),
             count => format!("aborting due to {} previous errors", count),
         };
@@ -767,7 +787,16 @@ impl HandlerInner {
             return;
         }
 
-        let _ = self.fatal(&s);
+        match (errors.len(), warnings.len()) {
+            (0, 0) => return,
+            (0, _) => self.emit_diagnostic(&Diagnostic::new(Level::Warning, &warnings)),
+            (_, 0) => {
+                let _ = self.fatal(&errors);
+            }
+            (_, _) => {
+                let _ = self.fatal(&format!("{}; {}", &errors, &warnings));
+            }
+        }
 
         let can_show_explain = self.emitter.should_show_explain();
         let are_there_diagnostics = !self.emitted_diagnostic_codes.is_empty();
@@ -797,13 +826,13 @@ impl HandlerInner {
                     ));
                     self.failure(&format!(
                         "For more information about an error, try \
-                                           `rustc --explain {}`.",
+                         `rustc --explain {}`.",
                         &error_codes[0]
                     ));
                 } else {
                     self.failure(&format!(
                         "For more information about this error, try \
-                                           `rustc --explain {}`.",
+                         `rustc --explain {}`.",
                         &error_codes[0]
                     ));
                 }