Skip to content

Commit b202532

Browse files
committed
Auto merge of #75534 - Aaron1011:feature/new-future-breakage, r=pnkfelix
Implement rustc side of report-future-incompat cc #71249 This is an alternative to `@pnkfelix's` initial implementation in https://github.com/pnkfelix/rust/commits/prototype-rustc-side-of-report-future-incompat (mainly because I started working before seeing that branch 😄 ). My approach outputs the entire original `Diagnostic`, in a way that is compatible with incremental compilation. This is not yet integrated with compiletest, but can be used manually by passing `-Z emit-future-incompat-report` to `rustc`. Several changes are made to support this feature: * The `librustc_session/lint` module is moved to a new crate `librustc_lint_defs` (name bikesheddable). This allows accessing lint definitions from `librustc_errors`. * The `Lint` struct is extended with an `Option<FutureBreakage>`. When present, it indicates that we should display a lint in the future-compat report. `FutureBreakage` contains additional information that we may want to display in the report (currently, a `date` field indicating when the crate will stop compiling). * A new variant `rustc_error::Level::Allow` is added. This is used when constructing a diagnostic for a future-breakage lint that is marked as allowed (via `#[allow]` or `--cap-lints`). This allows us to capture any future-breakage diagnostics in one place, while still discarding them before they are passed to the `Emitter`. * `DiagnosticId::Lint` is extended with a `has_future_breakage` field, indicating whether or not the `Lint` has future breakage information (and should therefore show up in the report). * `Session` is given access to the `LintStore` via a new `SessionLintStore` trait (since `librustc_session` cannot directly reference `LintStore` without a cyclic dependency). We use this to turn a string `DiagnosticId::Lint` back into a `Lint`, to retrieve the `FutureBreakage` data. Currently, `FutureBreakage.date` is always set to `None`. However, this could potentially be interpreted by Cargo in the future. I've enabled the future-breakage report for the `ARRAY_INTO_ITER` lint, which can be used to test out this PR. The intent is to use the field to allow Cargo to determine the date of future breakage (as described in [RFC 2834](https://github.com/rust-lang/rfcs/blob/master/text/2834-cargo-report-future-incompat.md)) without needing to parse the diagnostic itself. cc `@pnkfelix`
2 parents 1899c48 + 6db00a2 commit b202532

File tree

28 files changed

+539
-123
lines changed

28 files changed

+539
-123
lines changed

Cargo.lock

+14
Original file line numberDiff line numberDiff line change
@@ -3638,6 +3638,7 @@ dependencies = [
36383638
"annotate-snippets 0.8.0",
36393639
"atty",
36403640
"rustc_data_structures",
3641+
"rustc_lint_defs",
36413642
"rustc_macros",
36423643
"rustc_serialize",
36433644
"rustc_span",
@@ -3830,6 +3831,18 @@ dependencies = [
38303831
"unicode-security",
38313832
]
38323833

3834+
[[package]]
3835+
name = "rustc_lint_defs"
3836+
version = "0.0.0"
3837+
dependencies = [
3838+
"rustc_ast",
3839+
"rustc_data_structures",
3840+
"rustc_macros",
3841+
"rustc_serialize",
3842+
"rustc_span",
3843+
"tracing",
3844+
]
3845+
38333846
[[package]]
38343847
name = "rustc_llvm"
38353848
version = "0.0.0"
@@ -4112,6 +4125,7 @@ dependencies = [
41124125
"rustc_errors",
41134126
"rustc_feature",
41144127
"rustc_fs_util",
4128+
"rustc_lint_defs",
41154129
"rustc_macros",
41164130
"rustc_serialize",
41174131
"rustc_span",

compiler/rustc_ast_lowering/src/path.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
308308
E0726,
309309
"implicit elided lifetime not allowed here"
310310
);
311-
rustc_session::lint::add_elided_lifetime_in_path_suggestion(
312-
&self.sess,
311+
rustc_errors::add_elided_lifetime_in_path_suggestion(
312+
&self.sess.source_map(),
313313
&mut err,
314314
expected_lifetimes,
315315
path_span,

compiler/rustc_errors/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ rustc_serialize = { path = "../rustc_serialize" }
1313
rustc_span = { path = "../rustc_span" }
1414
rustc_macros = { path = "../rustc_macros" }
1515
rustc_data_structures = { path = "../rustc_data_structures" }
16+
rustc_lint_defs = { path = "../rustc_lint_defs" }
1617
unicode-width = "0.1.4"
1718
atty = "0.2"
1819
termcolor = "1.0"

compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ fn annotation_type_for_level(level: Level) -> AnnotationType {
7272
Level::Help => AnnotationType::Help,
7373
// FIXME(#59346): Not sure how to map these two levels
7474
Level::Cancelled | Level::FailureNote => AnnotationType::Error,
75+
Level::Allow => panic!("Should not call with Allow"),
7576
}
7677
}
7778

@@ -143,7 +144,8 @@ impl AnnotateSnippetEmitterWriter {
143144
title: Some(Annotation {
144145
label: Some(&message),
145146
id: code.as_ref().map(|c| match c {
146-
DiagnosticId::Error(val) | DiagnosticId::Lint(val) => val.as_str(),
147+
DiagnosticId::Error(val)
148+
| DiagnosticId::Lint { name: val, has_future_breakage: _ } => val.as_str(),
147149
}),
148150
annotation_type: annotation_type_for_level(*level),
149151
}),

compiler/rustc_errors/src/diagnostic.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use crate::snippet::Style;
2-
use crate::Applicability;
32
use crate::CodeSuggestion;
43
use crate::Level;
54
use crate::Substitution;
65
use crate::SubstitutionPart;
76
use crate::SuggestionStyle;
7+
use rustc_lint_defs::Applicability;
88
use rustc_span::{MultiSpan, Span, DUMMY_SP};
99
use std::fmt;
1010

@@ -27,7 +27,7 @@ pub struct Diagnostic {
2727
#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
2828
pub enum DiagnosticId {
2929
Error(String),
30-
Lint(String),
30+
Lint { name: String, has_future_breakage: bool },
3131
}
3232

3333
/// For example a note attached to an error.
@@ -107,7 +107,14 @@ impl Diagnostic {
107107
match self.level {
108108
Level::Bug | Level::Fatal | Level::Error | Level::FailureNote => true,
109109

110-
Level::Warning | Level::Note | Level::Help | Level::Cancelled => false,
110+
Level::Warning | Level::Note | Level::Help | Level::Cancelled | Level::Allow => false,
111+
}
112+
}
113+
114+
pub fn has_future_breakage(&self) -> bool {
115+
match self.code {
116+
Some(DiagnosticId::Lint { has_future_breakage, .. }) => has_future_breakage,
117+
_ => false,
111118
}
112119
}
113120

compiler/rustc_errors/src/diagnostic_builder.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
use crate::{Applicability, Handler, Level, StashKey};
21
use crate::{Diagnostic, DiagnosticId, DiagnosticStyledString};
2+
use crate::{Handler, Level, StashKey};
3+
use rustc_lint_defs::Applicability;
34

45
use rustc_span::{MultiSpan, Span};
56
use std::fmt::{self, Debug};

compiler/rustc_errors/src/emitter.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@
99
1010
use Destination::*;
1111

12+
use rustc_lint_defs::FutureBreakage;
1213
use rustc_span::source_map::SourceMap;
1314
use rustc_span::{MultiSpan, SourceFile, Span};
1415

1516
use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Style, StyledString};
1617
use crate::styled_buffer::StyledBuffer;
17-
use crate::{
18-
pluralize, CodeSuggestion, Diagnostic, DiagnosticId, Level, SubDiagnostic, SuggestionStyle,
19-
};
18+
use crate::{CodeSuggestion, Diagnostic, DiagnosticId, Level, SubDiagnostic, SuggestionStyle};
19+
20+
use rustc_lint_defs::pluralize;
2021

2122
use rustc_data_structures::fx::FxHashMap;
2223
use rustc_data_structures::sync::Lrc;
@@ -192,6 +193,8 @@ pub trait Emitter {
192193
/// other formats can, and will, simply ignore it.
193194
fn emit_artifact_notification(&mut self, _path: &Path, _artifact_type: &str) {}
194195

196+
fn emit_future_breakage_report(&mut self, _diags: Vec<(FutureBreakage, Diagnostic)>) {}
197+
195198
/// Checks if should show explanations about "rustc --explain"
196199
fn should_show_explain(&self) -> bool {
197200
true

compiler/rustc_errors/src/json.rs

+39-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ use rustc_span::source_map::{FilePathMapping, SourceMap};
1313

1414
use crate::emitter::{Emitter, HumanReadableErrorType};
1515
use crate::registry::Registry;
16-
use crate::{Applicability, DiagnosticId};
16+
use crate::DiagnosticId;
1717
use crate::{CodeSuggestion, SubDiagnostic};
18+
use rustc_lint_defs::{Applicability, FutureBreakage};
1819

1920
use rustc_data_structures::sync::Lrc;
2021
use rustc_span::hygiene::ExpnData;
@@ -131,6 +132,31 @@ impl Emitter for JsonEmitter {
131132
}
132133
}
133134

135+
fn emit_future_breakage_report(&mut self, diags: Vec<(FutureBreakage, crate::Diagnostic)>) {
136+
let data: Vec<FutureBreakageItem> = diags
137+
.into_iter()
138+
.map(|(breakage, mut diag)| {
139+
if diag.level == crate::Level::Allow {
140+
diag.level = crate::Level::Warning;
141+
}
142+
FutureBreakageItem {
143+
future_breakage_date: breakage.date,
144+
diagnostic: Diagnostic::from_errors_diagnostic(&diag, self),
145+
}
146+
})
147+
.collect();
148+
let report = FutureIncompatReport { future_incompat_report: data };
149+
let result = if self.pretty {
150+
writeln!(&mut self.dst, "{}", as_pretty_json(&report))
151+
} else {
152+
writeln!(&mut self.dst, "{}", as_json(&report))
153+
}
154+
.and_then(|_| self.dst.flush());
155+
if let Err(e) = result {
156+
panic!("failed to print future breakage report: {:?}", e);
157+
}
158+
}
159+
134160
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
135161
Some(&self.sm)
136162
}
@@ -223,6 +249,17 @@ struct ArtifactNotification<'a> {
223249
emit: &'a str,
224250
}
225251

252+
#[derive(Encodable)]
253+
struct FutureBreakageItem {
254+
future_breakage_date: Option<&'static str>,
255+
diagnostic: Diagnostic,
256+
}
257+
258+
#[derive(Encodable)]
259+
struct FutureIncompatReport {
260+
future_incompat_report: Vec<FutureBreakageItem>,
261+
}
262+
226263
impl Diagnostic {
227264
fn from_errors_diagnostic(diag: &crate::Diagnostic, je: &JsonEmitter) -> Diagnostic {
228265
let sugg = diag.suggestions.iter().map(|sugg| Diagnostic {
@@ -432,7 +469,7 @@ impl DiagnosticCode {
432469
s.map(|s| {
433470
let s = match s {
434471
DiagnosticId::Error(s) => s,
435-
DiagnosticId::Lint(s) => s,
472+
DiagnosticId::Lint { name, has_future_breakage: _ } => name,
436473
};
437474
let je_result =
438475
je.registry.as_ref().map(|registry| registry.try_find_description(&s)).unwrap();

0 commit comments

Comments
 (0)