1
Fork 0

Change how force-warn lint diagnostics are recorded.

`is_force_warn` is only possible for diagnostics with `Level::Warning`,
but it is currently stored in `Diagnostic::code`, which every diagnostic
has.

This commit:
- removes the boolean `DiagnosticId::Lint::is_force_warn` field;
- adds a `ForceWarning` variant to `Level`.

Benefits:
- The common `Level::Warning` case now has no arguments, replacing
  lots of `Warning(None)` occurrences.
- `rustc_session::lint::Level` and `rustc_errors::Level` are more
  similar, both having `ForceWarning` and `Warning`.
This commit is contained in:
Nicholas Nethercote 2024-01-09 12:28:45 +11:00
parent 06cf881969
commit 0e388f2192
12 changed files with 45 additions and 53 deletions

View file

@ -394,7 +394,7 @@ fn not_testable_error(cx: &ExtCtxt<'_>, attr_sp: Span, item: Option<&ast::Item>)
let level = match item.map(|i| &i.kind) { let level = match item.map(|i| &i.kind) {
// These were a warning before #92959 and need to continue being that to avoid breaking // These were a warning before #92959 and need to continue being that to avoid breaking
// stable user code (#94508). // stable user code (#94508).
Some(ast::ItemKind::MacCall(_)) => Level::Warning(None), Some(ast::ItemKind::MacCall(_)) => Level::Warning,
_ => Level::Error, _ => Level::Error,
}; };
let mut err = DiagnosticBuilder::<()>::new(dcx, level, msg); let mut err = DiagnosticBuilder::<()>::new(dcx, level, msg);

View file

@ -417,7 +417,7 @@ fn report_inline_asm(
} }
let level = match level { let level = match level {
llvm::DiagnosticLevel::Error => Level::Error, llvm::DiagnosticLevel::Error => Level::Error,
llvm::DiagnosticLevel::Warning => Level::Warning(None), llvm::DiagnosticLevel::Warning => Level::Warning,
llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note, llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note,
}; };
cgcx.diag_emitter.inline_asm_error(cookie as u32, msg, level, source); cgcx.diag_emitter.inline_asm_error(cookie as u32, msg, level, source);

View file

@ -1847,14 +1847,9 @@ impl SharedEmitterMain {
dcx.emit_diagnostic(d); dcx.emit_diagnostic(d);
} }
Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => { Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {
let err_level = match level { assert!(matches!(level, Level::Error | Level::Warning | Level::Note));
Level::Error => Level::Error,
Level::Warning(_) => Level::Warning(None),
Level::Note => Level::Note,
_ => bug!("Invalid inline asm diagnostic level"),
};
let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string(); let msg = msg.strip_prefix("error: ").unwrap_or(&msg).to_string();
let mut err = DiagnosticBuilder::<()>::new(sess.dcx(), err_level, msg); let mut err = DiagnosticBuilder::<()>::new(sess.dcx(), level, msg);
// If the cookie is 0 then we don't have span information. // If the cookie is 0 then we don't have span information.
if cookie != 0 { if cookie != 0 {

View file

@ -87,7 +87,7 @@ fn source_string(file: Lrc<SourceFile>, line: &Line) -> String {
fn annotation_type_for_level(level: Level) -> AnnotationType { fn annotation_type_for_level(level: Level) -> AnnotationType {
match level { match level {
Level::Bug | Level::DelayedBug | Level::Fatal | Level::Error => AnnotationType::Error, Level::Bug | Level::DelayedBug | Level::Fatal | Level::Error => AnnotationType::Error,
Level::Warning(_) => AnnotationType::Warning, Level::ForceWarning(_) | Level::Warning => AnnotationType::Warning,
Level::Note | Level::OnceNote => AnnotationType::Note, Level::Note | Level::OnceNote => AnnotationType::Note,
Level::Help | Level::OnceHelp => AnnotationType::Help, Level::Help | Level::OnceHelp => AnnotationType::Help,
// FIXME(#59346): Not sure how to map this level // FIXME(#59346): Not sure how to map this level

View file

@ -152,7 +152,6 @@ pub enum DiagnosticId {
name: String, name: String,
/// Indicates whether this lint should show up in cargo's future breakage report. /// Indicates whether this lint should show up in cargo's future breakage report.
has_future_breakage: bool, has_future_breakage: bool,
is_force_warn: bool,
}, },
} }
@ -248,7 +247,8 @@ impl Diagnostic {
true true
} }
Level::Warning(_) Level::ForceWarning(_)
| Level::Warning
| Level::Note | Level::Note
| Level::OnceNote | Level::OnceNote
| Level::Help | Level::Help
@ -262,7 +262,7 @@ impl Diagnostic {
&mut self, &mut self,
unstable_to_stable: &FxIndexMap<LintExpectationId, LintExpectationId>, unstable_to_stable: &FxIndexMap<LintExpectationId, LintExpectationId>,
) { ) {
if let Level::Expect(expectation_id) | Level::Warning(Some(expectation_id)) = if let Level::Expect(expectation_id) | Level::ForceWarning(Some(expectation_id)) =
&mut self.level &mut self.level
{ {
if expectation_id.is_stable() { if expectation_id.is_stable() {
@ -292,8 +292,11 @@ impl Diagnostic {
} }
pub(crate) fn is_force_warn(&self) -> bool { pub(crate) fn is_force_warn(&self) -> bool {
match self.code { match self.level {
Some(DiagnosticId::Lint { is_force_warn, .. }) => is_force_warn, Level::ForceWarning(_) => {
assert!(self.is_lint);
true
}
_ => false, _ => false,
} }
} }
@ -472,7 +475,7 @@ impl Diagnostic {
/// Add a warning attached to this diagnostic. /// Add a warning attached to this diagnostic.
#[rustc_lint_diagnostics] #[rustc_lint_diagnostics]
pub fn warn(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self { pub fn warn(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self {
self.sub(Level::Warning(None), msg, MultiSpan::new()); self.sub(Level::Warning, msg, MultiSpan::new());
self self
} }
@ -484,7 +487,7 @@ impl Diagnostic {
sp: S, sp: S,
msg: impl Into<SubdiagnosticMessage>, msg: impl Into<SubdiagnosticMessage>,
) -> &mut Self { ) -> &mut Self {
self.sub(Level::Warning(None), msg, sp.into()); self.sub(Level::Warning, msg, sp.into());
self self
} }

View file

@ -198,7 +198,7 @@ impl Emitter for JsonEmitter {
.into_iter() .into_iter()
.map(|mut diag| { .map(|mut diag| {
if diag.level == crate::Level::Allow { if diag.level == crate::Level::Allow {
diag.level = crate::Level::Warning(None); diag.level = crate::Level::Warning;
} }
FutureBreakageItem { FutureBreakageItem {
diagnostic: EmitTyped::Diagnostic(Diagnostic::from_errors_diagnostic( diagnostic: EmitTyped::Diagnostic(Diagnostic::from_errors_diagnostic(

View file

@ -738,7 +738,7 @@ impl DiagCtxt {
#[rustc_lint_diagnostics] #[rustc_lint_diagnostics]
#[track_caller] #[track_caller]
pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> { pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
DiagnosticBuilder::new(self, Warning(None), msg) DiagnosticBuilder::new(self, Warning, msg)
} }
/// Construct a builder at the `Allow` level with the `msg`. /// Construct a builder at the `Allow` level with the `msg`.
@ -1005,7 +1005,7 @@ impl DiagCtxt {
(0, 0) => return, (0, 0) => return,
(0, _) => inner (0, _) => inner
.emitter .emitter
.emit_diagnostic(&Diagnostic::new(Warning(None), DiagnosticMessage::Str(warnings))), .emit_diagnostic(&Diagnostic::new(Warning, DiagnosticMessage::Str(warnings))),
(_, 0) => { (_, 0) => {
inner.emit_diagnostic(Diagnostic::new(Fatal, errors)); inner.emit_diagnostic(Diagnostic::new(Fatal, errors));
} }
@ -1094,7 +1094,7 @@ impl DiagCtxt {
&'a self, &'a self,
warning: impl IntoDiagnostic<'a, ()>, warning: impl IntoDiagnostic<'a, ()>,
) -> DiagnosticBuilder<'a, ()> { ) -> DiagnosticBuilder<'a, ()> {
warning.into_diagnostic(self, Warning(None)) warning.into_diagnostic(self, Warning)
} }
#[track_caller] #[track_caller]
@ -1304,10 +1304,7 @@ impl DiagCtxtInner {
self.fulfilled_expectations.insert(expectation_id.normalize()); self.fulfilled_expectations.insert(expectation_id.normalize());
} }
if matches!(diagnostic.level, Warning(_)) if diagnostic.level == Warning && !self.flags.can_emit_warnings {
&& !self.flags.can_emit_warnings
&& !diagnostic.is_force_warn()
{
if diagnostic.has_future_breakage() { if diagnostic.has_future_breakage() {
(*TRACK_DIAGNOSTIC)(diagnostic, &mut |_| {}); (*TRACK_DIAGNOSTIC)(diagnostic, &mut |_| {});
} }
@ -1359,7 +1356,7 @@ impl DiagCtxtInner {
self.emitter.emit_diagnostic(&diagnostic); self.emitter.emit_diagnostic(&diagnostic);
if diagnostic.is_error() { if diagnostic.is_error() {
self.deduplicated_err_count += 1; self.deduplicated_err_count += 1;
} else if let Warning(_) = diagnostic.level { } else if matches!(diagnostic.level, ForceWarning(_) | Warning) {
self.deduplicated_warn_count += 1; self.deduplicated_warn_count += 1;
} }
} }
@ -1562,14 +1559,17 @@ pub enum Level {
/// Its `EmissionGuarantee` is `ErrorGuaranteed`. /// Its `EmissionGuarantee` is `ErrorGuaranteed`.
Error, Error,
/// A `force-warn` lint warning about the code being compiled. Does not prevent compilation
/// from finishing.
///
/// The [`LintExpectationId`] is used for expected lint diagnostics. In all other cases this
/// should be `None`.
ForceWarning(Option<LintExpectationId>),
/// A warning about the code being compiled. Does not prevent compilation from finishing. /// A warning about the code being compiled. Does not prevent compilation from finishing.
/// ///
/// This [`LintExpectationId`] is used for expected lint diagnostics, which should
/// also emit a warning due to the `force-warn` flag. In all other cases this should
/// be `None`.
///
/// Its `EmissionGuarantee` is `()`. /// Its `EmissionGuarantee` is `()`.
Warning(Option<LintExpectationId>), Warning,
/// A message giving additional context. Rare, because notes are more commonly attached to other /// A message giving additional context. Rare, because notes are more commonly attached to other
/// diagnostics such as errors. /// diagnostics such as errors.
@ -1622,7 +1622,7 @@ impl Level {
Bug | DelayedBug | Fatal | Error => { Bug | DelayedBug | Fatal | Error => {
spec.set_fg(Some(Color::Red)).set_intense(true); spec.set_fg(Some(Color::Red)).set_intense(true);
} }
Warning(_) => { ForceWarning(_) | Warning => {
spec.set_fg(Some(Color::Yellow)).set_intense(cfg!(windows)); spec.set_fg(Some(Color::Yellow)).set_intense(cfg!(windows));
} }
Note | OnceNote => { Note | OnceNote => {
@ -1641,7 +1641,7 @@ impl Level {
match self { match self {
Bug | DelayedBug => "error: internal compiler error", Bug | DelayedBug => "error: internal compiler error",
Fatal | Error => "error", Fatal | Error => "error",
Warning(_) => "warning", ForceWarning(_) | Warning => "warning",
Note | OnceNote => "note", Note | OnceNote => "note",
Help | OnceHelp => "help", Help | OnceHelp => "help",
FailureNote => "failure-note", FailureNote => "failure-note",
@ -1655,7 +1655,7 @@ impl Level {
pub fn get_expectation_id(&self) -> Option<LintExpectationId> { pub fn get_expectation_id(&self) -> Option<LintExpectationId> {
match self { match self {
Expect(id) | Warning(Some(id)) => Some(*id), Expect(id) | ForceWarning(Some(id)) => Some(*id),
_ => None, _ => None,
} }
} }

View file

@ -380,7 +380,7 @@ impl ToInternal<rustc_errors::Level> for Level {
fn to_internal(self) -> rustc_errors::Level { fn to_internal(self) -> rustc_errors::Level {
match self { match self {
Level::Error => rustc_errors::Level::Error, Level::Error => rustc_errors::Level::Error,
Level::Warning => rustc_errors::Level::Warning(None), Level::Warning => rustc_errors::Level::Warning,
Level::Note => rustc_errors::Level::Note, Level::Note => rustc_errors::Level::Note,
Level::Help => rustc_errors::Level::Help, Level::Help => rustc_errors::Level::Help,
_ => unreachable!("unknown proc_macro::Level variant: {:?}", self), _ => unreachable!("unknown proc_macro::Level variant: {:?}", self),

View file

@ -312,8 +312,9 @@ pub fn struct_lint_level(
// create a `DiagnosticBuilder` and continue as we would for warnings. // create a `DiagnosticBuilder` and continue as we would for warnings.
rustc_errors::Level::Expect(expect_id) rustc_errors::Level::Expect(expect_id)
} }
Level::ForceWarn(Some(expect_id)) => rustc_errors::Level::Warning(Some(expect_id)), Level::ForceWarn(Some(expect_id)) => rustc_errors::Level::ForceWarning(Some(expect_id)),
Level::Warn | Level::ForceWarn(None) => rustc_errors::Level::Warning(None), Level::ForceWarn(None) => rustc_errors::Level::ForceWarning(None),
Level::Warn => rustc_errors::Level::Warning,
Level::Deny | Level::Forbid => rustc_errors::Level::Error, Level::Deny | Level::Forbid => rustc_errors::Level::Error,
}; };
let mut err = DiagnosticBuilder::new(sess.dcx(), err_level, ""); let mut err = DiagnosticBuilder::new(sess.dcx(), err_level, "");
@ -350,22 +351,19 @@ pub fn struct_lint_level(
// suppressed the lint due to macros. // suppressed the lint due to macros.
err.primary_message(msg); err.primary_message(msg);
let name = lint.name_lower();
err.code(DiagnosticId::Lint { name, has_future_breakage });
// Lint diagnostics that are covered by the expect level will not be emitted outside // Lint diagnostics that are covered by the expect level will not be emitted outside
// the compiler. It is therefore not necessary to add any information for the user. // the compiler. It is therefore not necessary to add any information for the user.
// This will therefore directly call the decorate function which will in turn emit // This will therefore directly call the decorate function which will in turn emit
// the `Diagnostic`. // the `Diagnostic`.
if let Level::Expect(_) = level { if let Level::Expect(_) = level {
let name = lint.name_lower();
err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn: false });
decorate(&mut err); decorate(&mut err);
err.emit(); err.emit();
return; return;
} }
let name = lint.name_lower();
let is_force_warn = matches!(level, Level::ForceWarn(_));
err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn });
if let Some(future_incompatible) = future_incompatible { if let Some(future_incompatible) = future_incompatible {
let explanation = match future_incompatible.reason { let explanation = match future_incompatible.reason {
FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps

View file

@ -143,11 +143,7 @@ pub fn feature_warn_issue(
// Decorate this as a future-incompatibility lint as in rustc_middle::lint::struct_lint_level // Decorate this as a future-incompatibility lint as in rustc_middle::lint::struct_lint_level
let lint = UNSTABLE_SYNTAX_PRE_EXPANSION; let lint = UNSTABLE_SYNTAX_PRE_EXPANSION;
let future_incompatible = lint.future_incompatible.as_ref().unwrap(); let future_incompatible = lint.future_incompatible.as_ref().unwrap();
err.code(DiagnosticId::Lint { err.code(DiagnosticId::Lint { name: lint.name_lower(), has_future_breakage: false });
name: lint.name_lower(),
has_future_breakage: false,
is_force_warn: false,
});
err.warn(lint.desc); err.warn(lint.desc);
err.note(format!("for more information, see {}", future_incompatible.reference)); err.note(format!("for more information, see {}", future_incompatible.reference));

View file

@ -455,7 +455,7 @@ pub fn report_msg<'tcx>(
let sess = machine.tcx.sess; let sess = machine.tcx.sess;
let level = match diag_level { let level = match diag_level {
DiagLevel::Error => Level::Error, DiagLevel::Error => Level::Error,
DiagLevel::Warning => Level::Warning(None), DiagLevel::Warning => Level::Warning,
DiagLevel::Note => Level::Note, DiagLevel::Note => Level::Note,
}; };
let mut err = DiagnosticBuilder::<()>::new(sess.dcx(), level, title); let mut err = DiagnosticBuilder::<()>::new(sess.dcx(), level, title);

View file

@ -446,7 +446,7 @@ mod tests {
Some(ignore_list), Some(ignore_list),
); );
let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1)));
let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning(None), Some(span)); let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span));
emitter.emit_diagnostic(&non_fatal_diagnostic); emitter.emit_diagnostic(&non_fatal_diagnostic);
assert_eq!(num_emitted_errors.load(Ordering::Acquire), 0); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 0);
assert_eq!(can_reset_errors.load(Ordering::Acquire), true); assert_eq!(can_reset_errors.load(Ordering::Acquire), true);
@ -470,7 +470,7 @@ mod tests {
None, None,
); );
let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1)));
let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning(None), Some(span)); let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span));
emitter.emit_diagnostic(&non_fatal_diagnostic); emitter.emit_diagnostic(&non_fatal_diagnostic);
assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1);
assert_eq!(can_reset_errors.load(Ordering::Acquire), false); assert_eq!(can_reset_errors.load(Ordering::Acquire), false);
@ -507,8 +507,8 @@ mod tests {
); );
let bar_span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let bar_span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1)));
let foo_span = MultiSpan::from_span(mk_sp(BytePos(21), BytePos(22))); let foo_span = MultiSpan::from_span(mk_sp(BytePos(21), BytePos(22)));
let bar_diagnostic = build_diagnostic(DiagnosticLevel::Warning(None), Some(bar_span)); let bar_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(bar_span));
let foo_diagnostic = build_diagnostic(DiagnosticLevel::Warning(None), Some(foo_span)); let foo_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(foo_span));
let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, None); let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, None);
emitter.emit_diagnostic(&bar_diagnostic); emitter.emit_diagnostic(&bar_diagnostic);
emitter.emit_diagnostic(&foo_diagnostic); emitter.emit_diagnostic(&foo_diagnostic);