From f8ebc72b4aa138772434039950126f2c7f07a3f4 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 1 Sep 2022 11:40:43 +0100 Subject: errors: add `emit_note`/`create_note` Add `Noted` marker struct that implements `EmissionGuarantee` so that `emit_note` and `create_note` can be implemented for struct diagnostics. Signed-off-by: David Wood --- compiler/rustc_errors/src/diagnostic_builder.rs | 50 +++++++++++++++++++++++++ compiler/rustc_errors/src/lib.rs | 8 +++- 2 files changed, 56 insertions(+), 2 deletions(-) (limited to 'compiler/rustc_errors/src') diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index bbe6435be59..9b41234dcfb 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -255,6 +255,56 @@ impl EmissionGuarantee for () { } } +/// Marker type which enables implementation of `create_note` and `emit_note` functions for +/// note-without-error struct diagnostics. +#[derive(Copy, Clone)] +pub struct Noted; + +impl<'a> DiagnosticBuilder<'a, Noted> { + /// Convenience function for internal use, clients should use one of the + /// `struct_*` methods on [`Handler`]. + pub(crate) fn new_note(handler: &'a Handler, message: impl Into) -> Self { + let diagnostic = Diagnostic::new_with_code(Level::Note, None, message); + Self::new_diagnostic_note(handler, diagnostic) + } + + /// Creates a new `DiagnosticBuilder` with an already constructed + /// diagnostic. + pub(crate) fn new_diagnostic_note(handler: &'a Handler, diagnostic: Diagnostic) -> Self { + debug!("Created new diagnostic"); + Self { + inner: DiagnosticBuilderInner { + state: DiagnosticBuilderState::Emittable(handler), + diagnostic: Box::new(diagnostic), + }, + _marker: PhantomData, + } + } +} + +impl EmissionGuarantee for Noted { + fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { + match db.inner.state { + // First `.emit()` call, the `&Handler` is still available. + DiagnosticBuilderState::Emittable(handler) => { + db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; + handler.emit_diagnostic(&mut db.inner.diagnostic); + } + // `.emit()` was previously called, disallowed from repeating it. + DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} + } + + Noted + } + + fn make_diagnostic_builder( + handler: &Handler, + msg: impl Into, + ) -> DiagnosticBuilder<'_, Self> { + DiagnosticBuilder::new_note(handler, msg) + } +} + impl<'a> DiagnosticBuilder<'a, !> { /// Convenience function for internal use, clients should use one of the /// `struct_*` methods on [`Handler`]. diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 94a493992e5..a7fe280bc20 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -374,7 +374,7 @@ pub use diagnostic::{ AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgFromDisplay, DiagnosticArgValue, DiagnosticId, DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic, }; -pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee}; +pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, Noted}; use std::backtrace::Backtrace; /// A handler deals with errors and other compiler output. @@ -988,7 +988,11 @@ impl Handler { } pub fn has_errors(&self) -> Option { - if self.inner.borrow().has_errors() { Some(ErrorGuaranteed(())) } else { None } + if self.inner.borrow().has_errors() { + Some(ErrorGuaranteed(())) + } else { + None + } } pub fn has_errors_or_lint_errors(&self) -> Option { if self.inner.borrow().has_errors_or_lint_errors() { -- cgit 1.4.1-3-g733a5 From a7aa1850b2de87e31ffa07df6f4d47e0a5f7b01e Mon Sep 17 00:00:00 2001 From: Nathan Stocks Date: Sat, 1 Oct 2022 18:39:02 -0600 Subject: migrate dead.rs to translateable diagnostics --- compiler/rustc_error_messages/locales/en-US/passes.ftl | 6 ++++++ compiler/rustc_errors/src/lib.rs | 6 +----- compiler/rustc_passes/src/dead.rs | 16 +++++----------- compiler/rustc_passes/src/errors.rs | 9 ++++++++- 4 files changed, 20 insertions(+), 17 deletions(-) (limited to 'compiler/rustc_errors/src') diff --git a/compiler/rustc_error_messages/locales/en-US/passes.ftl b/compiler/rustc_error_messages/locales/en-US/passes.ftl index 9499ad56aa9..2308c7b2453 100644 --- a/compiler/rustc_error_messages/locales/en-US/passes.ftl +++ b/compiler/rustc_error_messages/locales/en-US/passes.ftl @@ -558,3 +558,9 @@ passes_incorrect_target = [one] argument *[other] arguments } + +passes_useless_assignment = + useless assignment of {$is_field_assign -> + [true] field + *[false] variable + } of type `{$ty}` to itself diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index a7fe280bc20..277d7166228 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -988,11 +988,7 @@ impl Handler { } pub fn has_errors(&self) -> Option { - if self.inner.borrow().has_errors() { - Some(ErrorGuaranteed(())) - } else { - None - } + if self.inner.borrow().has_errors() { Some(ErrorGuaranteed(())) } else { None } } pub fn has_errors_or_lint_errors(&self) -> Option { if self.inner.borrow().has_errors_or_lint_errors() { diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 08f704da62c..6a97ad3fe86 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -4,7 +4,7 @@ use itertools::Itertools; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::{pluralize, Applicability, DelayDm, MultiSpan}; +use rustc_errors::{pluralize, Applicability, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -18,6 +18,8 @@ use rustc_session::lint; use rustc_span::symbol::{sym, Symbol}; use std::mem; +use crate::errors::UselessAssignment; + // Any local node that may call something in its body block should be // explored. For example, if it's a live Node::Item that is a // function, then we should explore its block to check for codes that @@ -180,19 +182,11 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { && !assign.span.from_expansion() { let is_field_assign = matches!(lhs.kind, hir::ExprKind::Field(..)); - self.tcx.struct_span_lint_hir( + self.tcx.emit_spanned_lint( lint::builtin::DEAD_CODE, assign.hir_id, assign.span, - DelayDm(|| format!( - "useless assignment of {} of type `{}` to itself", - if is_field_assign { "field" } else { "variable" }, - self.typeck_results().expr_ty(lhs), - )), - |lint| { - lint - - }, + UselessAssignment { is_field_assign, ty: self.typeck_results().expr_ty(lhs) } ) } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index bf3350129b0..ba1d4472e34 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -7,7 +7,7 @@ use rustc_ast::Label; use rustc_errors::{error_code, Applicability, ErrorGuaranteed, IntoDiagnostic, MultiSpan}; use rustc_hir::{self as hir, ExprKind, Target}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; -use rustc_middle::ty::MainDefinition; +use rustc_middle::ty::{MainDefinition, Ty}; use rustc_span::{Span, Symbol, DUMMY_SP}; #[derive(LintDiagnostic)] @@ -1265,3 +1265,10 @@ pub struct IncorrectTarget<'a> { pub actual_num: usize, pub at_least: bool, } + +#[derive(LintDiagnostic)] +#[diag(passes::useless_assignment)] +pub struct UselessAssignment<'a> { + pub is_field_assign: bool, + pub ty: Ty<'a>, +} -- cgit 1.4.1-3-g733a5