errors: AddToDiagnostic::add_to_diagnostic_with
`AddToDiagnostic::add_to_diagnostic_with` is similar to the previous `AddToDiagnostic::add_to_diagnostic` but takes a function that can be used by the caller to modify diagnostic messages originating from the subdiagnostic (such as performing translation eagerly). `add_to_diagnostic` now just calls `add_to_diagnostic_with` with an empty closure. Signed-off-by: David Wood <david.wood@huawei.com>
This commit is contained in:
parent
508d7e6d26
commit
b4ac26289f
11 changed files with 129 additions and 50 deletions
|
@ -1,4 +1,7 @@
|
||||||
use rustc_errors::{fluent, AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgFromDisplay};
|
use rustc_errors::{
|
||||||
|
fluent, AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgFromDisplay,
|
||||||
|
SubdiagnosticMessage,
|
||||||
|
};
|
||||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||||
use rustc_span::{symbol::Ident, Span, Symbol};
|
use rustc_span::{symbol::Ident, Span, Symbol};
|
||||||
|
|
||||||
|
@ -19,7 +22,10 @@ pub struct UseAngleBrackets {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddToDiagnostic for UseAngleBrackets {
|
impl AddToDiagnostic for UseAngleBrackets {
|
||||||
fn add_to_diagnostic(self, diag: &mut Diagnostic) {
|
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||||
|
where
|
||||||
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||||
|
{
|
||||||
diag.multipart_suggestion(
|
diag.multipart_suggestion(
|
||||||
fluent::ast_lowering::use_angle_brackets,
|
fluent::ast_lowering::use_angle_brackets,
|
||||||
vec![(self.open_param, String::from("<")), (self.close_param, String::from(">"))],
|
vec![(self.open_param, String::from("<")), (self.close_param, String::from(">"))],
|
||||||
|
@ -69,7 +75,10 @@ pub enum AssocTyParenthesesSub {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddToDiagnostic for AssocTyParenthesesSub {
|
impl AddToDiagnostic for AssocTyParenthesesSub {
|
||||||
fn add_to_diagnostic(self, diag: &mut Diagnostic) {
|
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||||
|
where
|
||||||
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||||
|
{
|
||||||
match self {
|
match self {
|
||||||
Self::Empty { parentheses_span } => diag.multipart_suggestion(
|
Self::Empty { parentheses_span } => diag.multipart_suggestion(
|
||||||
fluent::ast_lowering::remove_parentheses,
|
fluent::ast_lowering::remove_parentheses,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! Errors emitted by ast_passes.
|
//! Errors emitted by ast_passes.
|
||||||
|
|
||||||
use rustc_errors::{fluent, AddToDiagnostic, Applicability, Diagnostic};
|
use rustc_errors::{fluent, AddToDiagnostic, Applicability, Diagnostic, SubdiagnosticMessage};
|
||||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::{Span, Symbol};
|
||||||
|
|
||||||
|
@ -17,7 +17,10 @@ pub struct ForbiddenLet {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddToDiagnostic for ForbiddenLetReason {
|
impl AddToDiagnostic for ForbiddenLetReason {
|
||||||
fn add_to_diagnostic(self, diag: &mut Diagnostic) {
|
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||||
|
where
|
||||||
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||||
|
{
|
||||||
match self {
|
match self {
|
||||||
Self::GenericForbidden => {}
|
Self::GenericForbidden => {}
|
||||||
Self::NotSupportedOr(span) => {
|
Self::NotSupportedOr(span) => {
|
||||||
|
@ -228,7 +231,10 @@ pub struct ExternBlockSuggestion {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddToDiagnostic for ExternBlockSuggestion {
|
impl AddToDiagnostic for ExternBlockSuggestion {
|
||||||
fn add_to_diagnostic(self, diag: &mut Diagnostic) {
|
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||||
|
where
|
||||||
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||||
|
{
|
||||||
let start_suggestion = if let Some(abi) = self.abi {
|
let start_suggestion = if let Some(abi) = self.abi {
|
||||||
format!("extern \"{}\" {{", abi)
|
format!("extern \"{}\" {{", abi)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -203,9 +203,20 @@ impl IntoDiagnosticArg for ast::token::TokenKind {
|
||||||
/// `#[derive(Subdiagnostic)]` -- see [rustc_macros::Subdiagnostic].
|
/// `#[derive(Subdiagnostic)]` -- see [rustc_macros::Subdiagnostic].
|
||||||
#[cfg_attr(bootstrap, rustc_diagnostic_item = "AddSubdiagnostic")]
|
#[cfg_attr(bootstrap, rustc_diagnostic_item = "AddSubdiagnostic")]
|
||||||
#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "AddToDiagnostic")]
|
#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "AddToDiagnostic")]
|
||||||
pub trait AddToDiagnostic {
|
pub trait AddToDiagnostic
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
/// Add a subdiagnostic to an existing diagnostic.
|
/// Add a subdiagnostic to an existing diagnostic.
|
||||||
fn add_to_diagnostic(self, diag: &mut Diagnostic);
|
fn add_to_diagnostic(self, diag: &mut Diagnostic) {
|
||||||
|
self.add_to_diagnostic_with(diag, |_, m| m);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add a subdiagnostic to an existing diagnostic where `f` is invoked on every message used
|
||||||
|
/// (to optionally perform eager translation).
|
||||||
|
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F)
|
||||||
|
where
|
||||||
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait implemented by lint types. This should not be implemented manually. Instead, use
|
/// Trait implemented by lint types. This should not be implemented manually. Instead, use
|
||||||
|
@ -921,8 +932,8 @@ impl Diagnostic {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a subdiagnostic from a type that implements `Subdiagnostic` - see
|
/// Add a subdiagnostic from a type that implements `Subdiagnostic` (see
|
||||||
/// [rustc_macros::Subdiagnostic].
|
/// [rustc_macros::Subdiagnostic]).
|
||||||
pub fn subdiagnostic(&mut self, subdiagnostic: impl AddToDiagnostic) -> &mut Self {
|
pub fn subdiagnostic(&mut self, subdiagnostic: impl AddToDiagnostic) -> &mut Self {
|
||||||
subdiagnostic.add_to_diagnostic(self);
|
subdiagnostic.add_to_diagnostic(self);
|
||||||
self
|
self
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use hir::GenericParamKind;
|
use hir::GenericParamKind;
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
fluent, AddToDiagnostic, Applicability, DiagnosticMessage, DiagnosticStyledString, MultiSpan,
|
fluent, AddToDiagnostic, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString,
|
||||||
|
MultiSpan, SubdiagnosticMessage,
|
||||||
};
|
};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::{FnRetTy, Ty};
|
use rustc_hir::{FnRetTy, Ty};
|
||||||
|
@ -229,7 +230,10 @@ pub enum RegionOriginNote<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddToDiagnostic for RegionOriginNote<'_> {
|
impl AddToDiagnostic for RegionOriginNote<'_> {
|
||||||
fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
|
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||||
|
where
|
||||||
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||||
|
{
|
||||||
let mut label_or_note = |span, msg: DiagnosticMessage| {
|
let mut label_or_note = |span, msg: DiagnosticMessage| {
|
||||||
let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count();
|
let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count();
|
||||||
let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count();
|
let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count();
|
||||||
|
@ -290,7 +294,10 @@ pub enum LifetimeMismatchLabels {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddToDiagnostic for LifetimeMismatchLabels {
|
impl AddToDiagnostic for LifetimeMismatchLabels {
|
||||||
fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
|
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||||
|
where
|
||||||
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||||
|
{
|
||||||
match self {
|
match self {
|
||||||
LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => {
|
LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => {
|
||||||
diag.span_label(param_span, fluent::infer::declared_different);
|
diag.span_label(param_span, fluent::infer::declared_different);
|
||||||
|
@ -340,7 +347,10 @@ pub struct AddLifetimeParamsSuggestion<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> {
|
impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> {
|
||||||
fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
|
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||||
|
where
|
||||||
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||||
|
{
|
||||||
let mut mk_suggestion = || {
|
let mut mk_suggestion = || {
|
||||||
let (
|
let (
|
||||||
hir::Ty { kind: hir::TyKind::Rptr(lifetime_sub, _), .. },
|
hir::Ty { kind: hir::TyKind::Rptr(lifetime_sub, _), .. },
|
||||||
|
@ -439,7 +449,10 @@ pub struct IntroducesStaticBecauseUnmetLifetimeReq {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddToDiagnostic for IntroducesStaticBecauseUnmetLifetimeReq {
|
impl AddToDiagnostic for IntroducesStaticBecauseUnmetLifetimeReq {
|
||||||
fn add_to_diagnostic(mut self, diag: &mut rustc_errors::Diagnostic) {
|
fn add_to_diagnostic_with<F>(mut self, diag: &mut Diagnostic, _: F)
|
||||||
|
where
|
||||||
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||||
|
{
|
||||||
self.unmet_requirements
|
self.unmet_requirements
|
||||||
.push_span_label(self.binding_span, fluent::infer::msl_introduces_static);
|
.push_span_label(self.binding_span, fluent::infer::msl_introduces_static);
|
||||||
diag.span_note(self.unmet_requirements, fluent::infer::msl_unmet_req);
|
diag.span_note(self.unmet_requirements, fluent::infer::msl_unmet_req);
|
||||||
|
@ -451,7 +464,10 @@ pub struct ImplNote {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddToDiagnostic for ImplNote {
|
impl AddToDiagnostic for ImplNote {
|
||||||
fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
|
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||||
|
where
|
||||||
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||||
|
{
|
||||||
match self.impl_span {
|
match self.impl_span {
|
||||||
Some(span) => diag.span_note(span, fluent::infer::msl_impl_note),
|
Some(span) => diag.span_note(span, fluent::infer::msl_impl_note),
|
||||||
None => diag.note(fluent::infer::msl_impl_note),
|
None => diag.note(fluent::infer::msl_impl_note),
|
||||||
|
@ -466,7 +482,10 @@ pub enum TraitSubdiag {
|
||||||
|
|
||||||
// FIXME(#100717) used in `Vec<TraitSubdiag>` so requires eager translation/list support
|
// FIXME(#100717) used in `Vec<TraitSubdiag>` so requires eager translation/list support
|
||||||
impl AddToDiagnostic for TraitSubdiag {
|
impl AddToDiagnostic for TraitSubdiag {
|
||||||
fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
|
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||||
|
where
|
||||||
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||||
|
{
|
||||||
match self {
|
match self {
|
||||||
TraitSubdiag::Note { span } => {
|
TraitSubdiag::Note { span } => {
|
||||||
diag.span_note(span, "this has an implicit `'static` lifetime requirement");
|
diag.span_note(span, "this has an implicit `'static` lifetime requirement");
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use crate::infer::error_reporting::nice_region_error::find_anon_type;
|
use crate::infer::error_reporting::nice_region_error::find_anon_type;
|
||||||
use rustc_errors::{self, fluent, AddToDiagnostic, IntoDiagnosticArg};
|
use rustc_errors::{
|
||||||
|
self, fluent, AddToDiagnostic, Diagnostic, IntoDiagnosticArg, SubdiagnosticMessage,
|
||||||
|
};
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_span::{symbol::kw, Span};
|
use rustc_span::{symbol::kw, Span};
|
||||||
|
|
||||||
|
@ -159,7 +161,10 @@ impl RegionExplanation<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddToDiagnostic for RegionExplanation<'_> {
|
impl AddToDiagnostic for RegionExplanation<'_> {
|
||||||
fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
|
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||||
|
where
|
||||||
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||||
|
{
|
||||||
if let Some(span) = self.desc.span {
|
if let Some(span) = self.desc.span {
|
||||||
diag.span_note(span, fluent::infer::region_explanation);
|
diag.span_note(span, fluent::infer::region_explanation);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
use rustc_errors::{fluent, AddToDiagnostic, ErrorGuaranteed, Handler, IntoDiagnostic};
|
use rustc_errors::{
|
||||||
|
fluent, AddToDiagnostic, Diagnostic, ErrorGuaranteed, Handler, IntoDiagnostic,
|
||||||
|
SubdiagnosticMessage,
|
||||||
|
};
|
||||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||||
use rustc_session::lint::Level;
|
use rustc_session::lint::Level;
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::{Span, Symbol};
|
||||||
|
@ -23,7 +26,10 @@ pub enum OverruledAttributeSub {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddToDiagnostic for OverruledAttributeSub {
|
impl AddToDiagnostic for OverruledAttributeSub {
|
||||||
fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
|
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||||
|
where
|
||||||
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||||
|
{
|
||||||
match self {
|
match self {
|
||||||
OverruledAttributeSub::DefaultSource { id } => {
|
OverruledAttributeSub::DefaultSource { id } => {
|
||||||
diag.note(fluent::lint::default_source);
|
diag.note(fluent::lint::default_source);
|
||||||
|
@ -88,7 +94,10 @@ pub struct RequestedLevel {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddToDiagnostic for RequestedLevel {
|
impl AddToDiagnostic for RequestedLevel {
|
||||||
fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
|
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||||
|
where
|
||||||
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||||
|
{
|
||||||
diag.note(fluent::lint::requested_level);
|
diag.note(fluent::lint::requested_level);
|
||||||
diag.set_arg(
|
diag.set_arg(
|
||||||
"level",
|
"level",
|
||||||
|
|
|
@ -9,7 +9,7 @@ use diagnostic::{DiagnosticDerive, LintDiagnosticDerive};
|
||||||
pub(crate) use fluent::fluent_messages;
|
pub(crate) use fluent::fluent_messages;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::format_ident;
|
use quote::format_ident;
|
||||||
use subdiagnostic::SubdiagnosticDerive;
|
use subdiagnostic::SubdiagnosticDeriveBuilder;
|
||||||
use synstructure::Structure;
|
use synstructure::Structure;
|
||||||
|
|
||||||
/// Implements `#[derive(Diagnostic)]`, which allows for errors to be specified as a struct,
|
/// Implements `#[derive(Diagnostic)]`, which allows for errors to be specified as a struct,
|
||||||
|
@ -155,5 +155,5 @@ pub fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream {
|
||||||
/// diag.subdiagnostic(RawIdentifierSuggestion { span, applicability, ident });
|
/// diag.subdiagnostic(RawIdentifierSuggestion { span, applicability, ident });
|
||||||
/// ```
|
/// ```
|
||||||
pub fn session_subdiagnostic_derive(s: Structure<'_>) -> TokenStream {
|
pub fn session_subdiagnostic_derive(s: Structure<'_>) -> TokenStream {
|
||||||
SubdiagnosticDerive::new(s).into_tokens()
|
SubdiagnosticDeriveBuilder::new().into_tokens(s)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,19 +15,19 @@ use syn::{spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta
|
||||||
use synstructure::{BindingInfo, Structure, VariantInfo};
|
use synstructure::{BindingInfo, Structure, VariantInfo};
|
||||||
|
|
||||||
/// The central struct for constructing the `add_to_diagnostic` method from an annotated struct.
|
/// The central struct for constructing the `add_to_diagnostic` method from an annotated struct.
|
||||||
pub(crate) struct SubdiagnosticDerive<'a> {
|
pub(crate) struct SubdiagnosticDeriveBuilder {
|
||||||
structure: Structure<'a>,
|
|
||||||
diag: syn::Ident,
|
diag: syn::Ident,
|
||||||
|
f: syn::Ident,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SubdiagnosticDerive<'a> {
|
impl SubdiagnosticDeriveBuilder {
|
||||||
pub(crate) fn new(structure: Structure<'a>) -> Self {
|
pub(crate) fn new() -> Self {
|
||||||
let diag = format_ident!("diag");
|
let diag = format_ident!("diag");
|
||||||
Self { structure, diag }
|
let f = format_ident!("f");
|
||||||
|
Self { diag, f }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn into_tokens(self) -> TokenStream {
|
pub(crate) fn into_tokens<'a>(self, mut structure: Structure<'a>) -> TokenStream {
|
||||||
let SubdiagnosticDerive { mut structure, diag } = self;
|
|
||||||
let implementation = {
|
let implementation = {
|
||||||
let ast = structure.ast();
|
let ast = structure.ast();
|
||||||
let span = ast.span().unwrap();
|
let span = ast.span().unwrap();
|
||||||
|
@ -53,8 +53,8 @@ impl<'a> SubdiagnosticDerive<'a> {
|
||||||
|
|
||||||
structure.bind_with(|_| synstructure::BindStyle::Move);
|
structure.bind_with(|_| synstructure::BindStyle::Move);
|
||||||
let variants_ = structure.each_variant(|variant| {
|
let variants_ = structure.each_variant(|variant| {
|
||||||
let mut builder = SubdiagnosticDeriveBuilder {
|
let mut builder = SubdiagnosticDeriveVariantBuilder {
|
||||||
diag: &diag,
|
parent: &self,
|
||||||
variant,
|
variant,
|
||||||
span,
|
span,
|
||||||
fields: build_field_mapping(variant),
|
fields: build_field_mapping(variant),
|
||||||
|
@ -72,9 +72,17 @@ impl<'a> SubdiagnosticDerive<'a> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let diag = &self.diag;
|
||||||
|
let f = &self.f;
|
||||||
let ret = structure.gen_impl(quote! {
|
let ret = structure.gen_impl(quote! {
|
||||||
gen impl rustc_errors::AddToDiagnostic for @Self {
|
gen impl rustc_errors::AddToDiagnostic for @Self {
|
||||||
fn add_to_diagnostic(self, #diag: &mut rustc_errors::Diagnostic) {
|
fn add_to_diagnostic_with<__F>(self, #diag: &mut rustc_errors::Diagnostic, #f: __F)
|
||||||
|
where
|
||||||
|
__F: Fn(
|
||||||
|
&mut rustc_errors::Diagnostic,
|
||||||
|
rustc_errors::SubdiagnosticMessage
|
||||||
|
) -> rustc_errors::SubdiagnosticMessage,
|
||||||
|
{
|
||||||
use rustc_errors::{Applicability, IntoDiagnosticArg};
|
use rustc_errors::{Applicability, IntoDiagnosticArg};
|
||||||
#implementation
|
#implementation
|
||||||
}
|
}
|
||||||
|
@ -88,9 +96,9 @@ impl<'a> SubdiagnosticDerive<'a> {
|
||||||
/// for the final generated method. This is a separate struct to `SubdiagnosticDerive`
|
/// for the final generated method. This is a separate struct to `SubdiagnosticDerive`
|
||||||
/// only to be able to destructure and split `self.builder` and the `self.structure` up to avoid a
|
/// only to be able to destructure and split `self.builder` and the `self.structure` up to avoid a
|
||||||
/// double mut borrow later on.
|
/// double mut borrow later on.
|
||||||
struct SubdiagnosticDeriveBuilder<'a> {
|
struct SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
||||||
/// The identifier to use for the generated `DiagnosticBuilder` instance.
|
/// The identifier to use for the generated `DiagnosticBuilder` instance.
|
||||||
diag: &'a syn::Ident,
|
parent: &'parent SubdiagnosticDeriveBuilder,
|
||||||
|
|
||||||
/// Info for the current variant (or the type if not an enum).
|
/// Info for the current variant (or the type if not an enum).
|
||||||
variant: &'a VariantInfo<'a>,
|
variant: &'a VariantInfo<'a>,
|
||||||
|
@ -112,7 +120,7 @@ struct SubdiagnosticDeriveBuilder<'a> {
|
||||||
has_suggestion_parts: bool,
|
has_suggestion_parts: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> HasFieldMap for SubdiagnosticDeriveBuilder<'a> {
|
impl<'parent, 'a> HasFieldMap for SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
||||||
fn get_field_binding(&self, field: &String) -> Option<&TokenStream> {
|
fn get_field_binding(&self, field: &String) -> Option<&TokenStream> {
|
||||||
self.fields.get(field)
|
self.fields.get(field)
|
||||||
}
|
}
|
||||||
|
@ -156,7 +164,7 @@ impl<'a> FromIterator<&'a SubdiagnosticKind> for KindsStatistics {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SubdiagnosticDeriveBuilder<'a> {
|
impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
||||||
fn identify_kind(&mut self) -> Result<Vec<(SubdiagnosticKind, Path)>, DiagnosticDeriveError> {
|
fn identify_kind(&mut self) -> Result<Vec<(SubdiagnosticKind, Path)>, DiagnosticDeriveError> {
|
||||||
let mut kind_slugs = vec![];
|
let mut kind_slugs = vec![];
|
||||||
|
|
||||||
|
@ -187,7 +195,7 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> {
|
||||||
let ast = binding.ast();
|
let ast = binding.ast();
|
||||||
assert_eq!(ast.attrs.len(), 0, "field with attribute used as diagnostic arg");
|
assert_eq!(ast.attrs.len(), 0, "field with attribute used as diagnostic arg");
|
||||||
|
|
||||||
let diag = &self.diag;
|
let diag = &self.parent.diag;
|
||||||
let ident = ast.ident.as_ref().unwrap();
|
let ident = ast.ident.as_ref().unwrap();
|
||||||
// strip `r#` prefix, if present
|
// strip `r#` prefix, if present
|
||||||
let ident = format_ident!("{}", ident);
|
let ident = format_ident!("{}", ident);
|
||||||
|
@ -442,11 +450,14 @@ impl<'a> SubdiagnosticDeriveBuilder<'a> {
|
||||||
|
|
||||||
let span_field = self.span_field.value_ref();
|
let span_field = self.span_field.value_ref();
|
||||||
|
|
||||||
let diag = &self.diag;
|
let diag = &self.parent.diag;
|
||||||
|
let f = &self.parent.f;
|
||||||
let mut calls = TokenStream::new();
|
let mut calls = TokenStream::new();
|
||||||
for (kind, slug) in kind_slugs {
|
for (kind, slug) in kind_slugs {
|
||||||
|
let message = format_ident!("__message");
|
||||||
|
calls.extend(quote! { let #message = #f(#diag, rustc_errors::fluent::#slug.into()); });
|
||||||
|
|
||||||
let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind);
|
let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind);
|
||||||
let message = quote! { rustc_errors::fluent::#slug };
|
|
||||||
let call = match kind {
|
let call = match kind {
|
||||||
SubdiagnosticKind::Suggestion { suggestion_kind, applicability, code } => {
|
SubdiagnosticKind::Suggestion { suggestion_kind, applicability, code } => {
|
||||||
let applicability = applicability
|
let applicability = applicability
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustc_errors::AddToDiagnostic;
|
use rustc_errors::{AddToDiagnostic, Diagnostic, SubdiagnosticMessage};
|
||||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||||
use rustc_session::Limit;
|
use rustc_session::Limit;
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::{Span, Symbol};
|
||||||
|
@ -9,7 +9,10 @@ pub struct CycleStack {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddToDiagnostic for CycleStack {
|
impl AddToDiagnostic for CycleStack {
|
||||||
fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
|
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||||
|
where
|
||||||
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||||
|
{
|
||||||
diag.span_note(self.span, &format!("...which requires {}...", self.desc));
|
diag.span_note(self.span, &format!("...which requires {}...", self.desc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ extern crate rustc_span;
|
||||||
|
|
||||||
use rustc_errors::{
|
use rustc_errors::{
|
||||||
AddToDiagnostic, IntoDiagnostic, Diagnostic, DiagnosticBuilder,
|
AddToDiagnostic, IntoDiagnostic, Diagnostic, DiagnosticBuilder,
|
||||||
ErrorGuaranteed, Handler, fluent
|
ErrorGuaranteed, Handler, fluent, SubdiagnosticMessage,
|
||||||
};
|
};
|
||||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
@ -52,7 +52,10 @@ impl<'a> IntoDiagnostic<'a, ErrorGuaranteed> for TranslatableInIntoDiagnostic {
|
||||||
pub struct UntranslatableInAddToDiagnostic;
|
pub struct UntranslatableInAddToDiagnostic;
|
||||||
|
|
||||||
impl AddToDiagnostic for UntranslatableInAddToDiagnostic {
|
impl AddToDiagnostic for UntranslatableInAddToDiagnostic {
|
||||||
fn add_to_diagnostic(self, diag: &mut Diagnostic) {
|
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||||
|
where
|
||||||
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||||
|
{
|
||||||
diag.note("untranslatable diagnostic");
|
diag.note("untranslatable diagnostic");
|
||||||
//~^ ERROR diagnostics should be created using translatable messages
|
//~^ ERROR diagnostics should be created using translatable messages
|
||||||
}
|
}
|
||||||
|
@ -61,7 +64,10 @@ impl AddToDiagnostic for UntranslatableInAddToDiagnostic {
|
||||||
pub struct TranslatableInAddToDiagnostic;
|
pub struct TranslatableInAddToDiagnostic;
|
||||||
|
|
||||||
impl AddToDiagnostic for TranslatableInAddToDiagnostic {
|
impl AddToDiagnostic for TranslatableInAddToDiagnostic {
|
||||||
fn add_to_diagnostic(self, diag: &mut Diagnostic) {
|
fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
|
||||||
|
where
|
||||||
|
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
|
||||||
|
{
|
||||||
diag.note(fluent::compiletest::note);
|
diag.note(fluent::compiletest::note);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,13 @@ LL | #![deny(rustc::untranslatable_diagnostic)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: diagnostics should be created using translatable messages
|
error: diagnostics should be created using translatable messages
|
||||||
--> $DIR/diagnostics.rs:56:14
|
--> $DIR/diagnostics.rs:59:14
|
||||||
|
|
|
|
||||||
LL | diag.note("untranslatable diagnostic");
|
LL | diag.note("untranslatable diagnostic");
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
|
error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
|
||||||
--> $DIR/diagnostics.rs:70:25
|
--> $DIR/diagnostics.rs:76:25
|
||||||
|
|
|
|
||||||
LL | let _diag = handler.struct_err(fluent::compiletest::example);
|
LL | let _diag = handler.struct_err(fluent::compiletest::example);
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
@ -29,13 +29,13 @@ LL | #![deny(rustc::diagnostic_outside_of_impl)]
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
|
error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
|
||||||
--> $DIR/diagnostics.rs:73:25
|
--> $DIR/diagnostics.rs:79:25
|
||||||
|
|
|
|
||||||
LL | let _diag = handler.struct_err("untranslatable diagnostic");
|
LL | let _diag = handler.struct_err("untranslatable diagnostic");
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: diagnostics should be created using translatable messages
|
error: diagnostics should be created using translatable messages
|
||||||
--> $DIR/diagnostics.rs:73:25
|
--> $DIR/diagnostics.rs:79:25
|
||||||
|
|
|
|
||||||
LL | let _diag = handler.struct_err("untranslatable diagnostic");
|
LL | let _diag = handler.struct_err("untranslatable diagnostic");
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue