diff options
| author | Aaron Hill <aa1ronham@gmail.com> | 2020-08-13 15:41:52 -0400 |
|---|---|---|
| committer | Aaron Hill <aa1ronham@gmail.com> | 2020-10-30 20:02:14 -0400 |
| commit | 23018a55d9735afbefb19fcec91db4b53fe917d8 (patch) | |
| tree | bef86dbf8d1e8d184d564c54ba3c47f549060fac /compiler/rustc_errors/src | |
| parent | ffe52882ed79be67344dd6085559e308241e7f60 (diff) | |
| download | rust-23018a55d9735afbefb19fcec91db4b53fe917d8.tar.gz rust-23018a55d9735afbefb19fcec91db4b53fe917d8.zip | |
Implement rustc side of report-future-incompat
Diffstat (limited to 'compiler/rustc_errors/src')
| -rw-r--r-- | compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/diagnostic.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/diagnostic_builder.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/emitter.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/json.rs | 35 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/lib.rs | 111 |
6 files changed, 136 insertions, 39 deletions
diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 265ba59cccb..6f365c07f6d 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -72,6 +72,7 @@ fn annotation_type_for_level(level: Level) -> AnnotationType { Level::Help => AnnotationType::Help, // FIXME(#59346): Not sure how to map these two levels Level::Cancelled | Level::FailureNote => AnnotationType::Error, + Level::Allow => panic!("Should not call with Allow"), } } @@ -143,7 +144,8 @@ impl AnnotateSnippetEmitterWriter { title: Some(Annotation { label: Some(&message), id: code.as_ref().map(|c| match c { - DiagnosticId::Error(val) | DiagnosticId::Lint(val) => val.as_str(), + DiagnosticId::Error(val) + | DiagnosticId::Lint { name: val, has_future_breakage: _ } => val.as_str(), }), annotation_type: annotation_type_for_level(*level), }), diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 91bfc6296b1..decbf03b9de 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -1,10 +1,10 @@ use crate::snippet::Style; -use crate::Applicability; use crate::CodeSuggestion; use crate::Level; use crate::Substitution; use crate::SubstitutionPart; use crate::SuggestionStyle; +use rustc_lint_defs::Applicability; use rustc_span::{MultiSpan, Span, DUMMY_SP}; use std::fmt; @@ -27,7 +27,7 @@ pub struct Diagnostic { #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] pub enum DiagnosticId { Error(String), - Lint(String), + Lint { name: String, has_future_breakage: bool }, } /// For example a note attached to an error. @@ -107,7 +107,14 @@ impl Diagnostic { match self.level { Level::Bug | Level::Fatal | Level::Error | Level::FailureNote => true, - Level::Warning | Level::Note | Level::Help | Level::Cancelled => false, + Level::Warning | Level::Note | Level::Help | Level::Cancelled | Level::Allow => false, + } + } + + pub fn has_future_breakage(&self) -> bool { + match self.code { + Some(DiagnosticId::Lint { has_future_breakage, .. }) => has_future_breakage, + _ => false, } } diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index d1ff6f721c4..56acdf699ef 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -1,5 +1,6 @@ -use crate::{Applicability, Handler, Level, StashKey}; use crate::{Diagnostic, DiagnosticId, DiagnosticStyledString}; +use crate::{Handler, Level, StashKey}; +use rustc_lint_defs::Applicability; use rustc_span::{MultiSpan, Span}; use std::fmt::{self, Debug}; diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 08e9bdf3087..2dc7b7e2da3 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -9,14 +9,15 @@ use Destination::*; +use rustc_lint_defs::FutureBreakage; use rustc_span::source_map::SourceMap; use rustc_span::{MultiSpan, SourceFile, Span}; use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Style, StyledString}; use crate::styled_buffer::StyledBuffer; -use crate::{ - pluralize, CodeSuggestion, Diagnostic, DiagnosticId, Level, SubDiagnostic, SuggestionStyle, -}; +use crate::{CodeSuggestion, Diagnostic, DiagnosticId, Level, SubDiagnostic, SuggestionStyle}; + +use rustc_lint_defs::pluralize; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; @@ -192,6 +193,8 @@ pub trait Emitter { /// other formats can, and will, simply ignore it. fn emit_artifact_notification(&mut self, _path: &Path, _artifact_type: &str) {} + fn emit_future_breakage_report(&mut self, _diags: Vec<(FutureBreakage, Diagnostic)>) {} + /// Checks if should show explanations about "rustc --explain" fn should_show_explain(&self) -> bool { true diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index fbe3588280a..ddffa64f222 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -13,8 +13,9 @@ use rustc_span::source_map::{FilePathMapping, SourceMap}; use crate::emitter::{Emitter, HumanReadableErrorType}; use crate::registry::Registry; -use crate::{Applicability, DiagnosticId}; +use crate::DiagnosticId; use crate::{CodeSuggestion, SubDiagnostic}; +use rustc_lint_defs::{Applicability, FutureBreakage}; use rustc_data_structures::sync::Lrc; use rustc_span::hygiene::ExpnData; @@ -131,6 +132,30 @@ impl Emitter for JsonEmitter { } } + fn emit_future_breakage_report(&mut self, diags: Vec<(FutureBreakage, crate::Diagnostic)>) { + let data: Vec<FutureBreakageItem> = diags + .into_iter() + .map(|(breakage, mut diag)| { + if diag.level == crate::Level::Allow { + diag.level = crate::Level::Warning; + } + FutureBreakageItem { + future_breakage_date: breakage.date, + diagnostic: Diagnostic::from_errors_diagnostic(&diag, self), + } + }) + .collect(); + let result = if self.pretty { + writeln!(&mut self.dst, "{}", as_pretty_json(&data)) + } else { + writeln!(&mut self.dst, "{}", as_json(&data)) + } + .and_then(|_| self.dst.flush()); + if let Err(e) = result { + panic!("failed to print future breakage report: {:?}", e); + } + } + fn source_map(&self) -> Option<&Lrc<SourceMap>> { Some(&self.sm) } @@ -223,6 +248,12 @@ struct ArtifactNotification<'a> { emit: &'a str, } +#[derive(Encodable)] +struct FutureBreakageItem { + future_breakage_date: Option<&'static str>, + diagnostic: Diagnostic, +} + impl Diagnostic { fn from_errors_diagnostic(diag: &crate::Diagnostic, je: &JsonEmitter) -> Diagnostic { let sugg = diag.suggestions.iter().map(|sugg| Diagnostic { @@ -432,7 +463,7 @@ impl DiagnosticCode { s.map(|s| { let s = match s { DiagnosticId::Error(s) => s, - DiagnosticId::Lint(s) => s, + DiagnosticId::Lint { name, has_future_breakage: _ } => name, }; let je_result = je.registry.as_ref().map(|registry| registry.try_find_description(&s)).unwrap(); diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 2ebc4a7e9d9..593e0d92031 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -21,6 +21,8 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::sync::{self, Lock, Lrc}; use rustc_data_structures::AtomicRef; +use rustc_lint_defs::FutureBreakage; +pub use rustc_lint_defs::{pluralize, Applicability}; use rustc_span::source_map::SourceMap; use rustc_span::{Loc, MultiSpan, Span}; @@ -49,30 +51,6 @@ pub type PResult<'a, T> = Result<T, DiagnosticBuilder<'a>>; #[cfg(target_arch = "x86_64")] rustc_data_structures::static_assert_size!(PResult<'_, bool>, 16); -/// Indicates the confidence in the correctness of a suggestion. -/// -/// All suggestions are marked with an `Applicability`. Tools use the applicability of a suggestion -/// to determine whether it should be automatically applied or if the user should be consulted -/// before applying the suggestion. -#[derive(Copy, Clone, Debug, PartialEq, Hash, Encodable, Decodable)] -pub enum Applicability { - /// The suggestion is definitely what the user intended. This suggestion should be - /// automatically applied. - MachineApplicable, - - /// The suggestion may be what the user intended, but it is uncertain. The suggestion should - /// result in valid Rust code if it is applied. - MaybeIncorrect, - - /// The suggestion contains placeholders like `(...)` or `{ /* fields */ }`. The suggestion - /// cannot be applied automatically because it will not result in valid Rust code. The user - /// will need to fill in the placeholders. - HasPlaceholders, - - /// The applicability of the suggestion is unknown. - Unspecified, -} - #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Encodable, Decodable)] pub enum SuggestionStyle { /// Hide the suggested code when displaying this suggestion inline. @@ -321,6 +299,8 @@ struct HandlerInner { /// The warning count, used for a recap upon finishing deduplicated_warn_count: usize, + + future_breakage_diagnostics: Vec<Diagnostic>, } /// A key denoting where from a diagnostic was stashed. @@ -434,6 +414,7 @@ impl Handler { emitted_diagnostic_codes: Default::default(), emitted_diagnostics: Default::default(), stashed_diagnostics: Default::default(), + future_breakage_diagnostics: Vec::new(), }), } } @@ -503,6 +484,17 @@ impl Handler { result } + /// Construct a builder at the `Allow` level at the given `span` and with the `msg`. + pub fn struct_span_allow( + &self, + span: impl Into<MultiSpan>, + msg: &str, + ) -> DiagnosticBuilder<'_> { + let mut result = self.struct_allow(msg); + result.set_span(span); + result + } + /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. /// Also include a code. pub fn struct_span_warn_with_code( @@ -525,6 +517,11 @@ impl Handler { result } + /// Construct a builder at the `Allow` level with the `msg`. + pub fn struct_allow(&self, msg: &str) -> DiagnosticBuilder<'_> { + DiagnosticBuilder::new(self, Level::Allow, msg) + } + /// Construct a builder at the `Error` level at the given `span` and with the `msg`. pub fn struct_span_err(&self, span: impl Into<MultiSpan>, msg: &str) -> DiagnosticBuilder<'_> { let mut result = self.struct_err(msg); @@ -693,6 +690,10 @@ impl Handler { self.inner.borrow_mut().print_error_count(registry) } + pub fn take_future_breakage_diagnostics(&self) -> Vec<Diagnostic> { + std::mem::take(&mut self.inner.borrow_mut().future_breakage_diagnostics) + } + pub fn abort_if_errors(&self) { self.inner.borrow_mut().abort_if_errors() } @@ -723,6 +724,10 @@ impl Handler { self.inner.borrow_mut().emit_artifact_notification(path, artifact_type) } + pub fn emit_future_breakage_report(&self, diags: Vec<(FutureBreakage, Diagnostic)>) { + self.inner.borrow_mut().emitter.emit_future_breakage_report(diags) + } + pub fn delay_as_bug(&self, diagnostic: Diagnostic) { self.inner.borrow_mut().delay_as_bug(diagnostic) } @@ -748,12 +753,23 @@ impl HandlerInner { return; } + if diagnostic.has_future_breakage() { + self.future_breakage_diagnostics.push(diagnostic.clone()); + } + if diagnostic.level == Warning && !self.flags.can_emit_warnings { + if diagnostic.has_future_breakage() { + (*TRACK_DIAGNOSTICS)(diagnostic); + } return; } (*TRACK_DIAGNOSTICS)(diagnostic); + if diagnostic.level == Allow { + return; + } + if let Some(ref code) = diagnostic.code { self.emitted_diagnostic_codes.insert(code.clone()); } @@ -992,6 +1008,7 @@ pub enum Level { Help, Cancelled, FailureNote, + Allow, } impl fmt::Display for Level { @@ -1017,7 +1034,7 @@ impl Level { spec.set_fg(Some(Color::Cyan)).set_intense(true); } FailureNote => {} - Cancelled => unreachable!(), + Allow | Cancelled => unreachable!(), } spec } @@ -1031,6 +1048,7 @@ impl Level { Help => "help", FailureNote => "failure-note", Cancelled => panic!("Shouldn't call on cancelled error"), + Allow => panic!("Shouldn't call on allowed error"), } } @@ -1039,11 +1057,46 @@ impl Level { } } -#[macro_export] -macro_rules! pluralize { - ($x:expr) => { - if $x != 1 { "s" } else { "" } +pub fn add_elided_lifetime_in_path_suggestion( + source_map: &SourceMap, + db: &mut DiagnosticBuilder<'_>, + n: usize, + path_span: Span, + incl_angl_brckt: bool, + insertion_span: Span, + anon_lts: String, +) { + let (replace_span, suggestion) = if incl_angl_brckt { + (insertion_span, anon_lts) + } else { + // When possible, prefer a suggestion that replaces the whole + // `Path<T>` expression with `Path<'_, T>`, rather than inserting `'_, ` + // at a point (which makes for an ugly/confusing label) + if let Ok(snippet) = source_map.span_to_snippet(path_span) { + // But our spans can get out of whack due to macros; if the place we think + // we want to insert `'_` isn't even within the path expression's span, we + // should bail out of making any suggestion rather than panicking on a + // subtract-with-overflow or string-slice-out-out-bounds (!) + // FIXME: can we do better? + if insertion_span.lo().0 < path_span.lo().0 { + return; + } + let insertion_index = (insertion_span.lo().0 - path_span.lo().0) as usize; + if insertion_index > snippet.len() { + return; + } + let (before, after) = snippet.split_at(insertion_index); + (path_span, format!("{}{}{}", before, anon_lts, after)) + } else { + (insertion_span, anon_lts) + } }; + db.span_suggestion( + replace_span, + &format!("indicate the anonymous lifetime{}", pluralize!(n)), + suggestion, + Applicability::MachineApplicable, + ); } // Useful type to use with `Result<>` indicate that an error has already |
