Rollup merge of #124218 - Xiretza:subsubdiagnostics, r=davidtwco
Allow nesting subdiagnostics in #[derive(Subdiagnostic)]
This commit is contained in:
commit
6e423e1651
@ -44,7 +44,7 @@ impl Subdiagnostic for InvalidAbiReason {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_: F,
|
||||
_: &F,
|
||||
) {
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
diag.note(self.0);
|
||||
|
@ -382,7 +382,7 @@ impl Subdiagnostic for EmptyLabelManySpans {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_: F,
|
||||
_: &F,
|
||||
) {
|
||||
diag.span_labels(self.0, "");
|
||||
}
|
||||
@ -751,7 +751,7 @@ impl Subdiagnostic for StableFeature {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_: F,
|
||||
_: &F,
|
||||
) {
|
||||
diag.arg("name", self.name);
|
||||
diag.arg("since", self.since);
|
||||
|
@ -601,7 +601,7 @@ impl Subdiagnostic for FormatUnusedArg {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
f: F,
|
||||
f: &F,
|
||||
) {
|
||||
diag.arg("named", self.named);
|
||||
let msg = f(diag, crate::fluent_generated::builtin_macros_format_unused_arg.into());
|
||||
|
@ -177,7 +177,7 @@ pub trait Subdiagnostic
|
||||
{
|
||||
/// Add a subdiagnostic to an existing diagnostic.
|
||||
fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
|
||||
self.add_to_diag_with(diag, |_, m| m);
|
||||
self.add_to_diag_with(diag, &|_, m| m);
|
||||
}
|
||||
|
||||
/// Add a subdiagnostic to an existing diagnostic where `f` is invoked on every message used
|
||||
@ -185,7 +185,7 @@ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
f: F,
|
||||
f: &F,
|
||||
);
|
||||
}
|
||||
|
||||
@ -1197,7 +1197,7 @@ pub fn subdiagnostic(
|
||||
dcx: &crate::DiagCtxt,
|
||||
subdiagnostic: impl Subdiagnostic,
|
||||
) -> &mut Self {
|
||||
subdiagnostic.add_to_diag_with(self, |diag, msg| {
|
||||
subdiagnostic.add_to_diag_with(self, &|diag, msg| {
|
||||
let args = diag.args.iter();
|
||||
let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
|
||||
dcx.eagerly_translate(msg, args)
|
||||
|
@ -227,6 +227,36 @@ fn into_diag_arg(self) -> DiagArgValue {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Id> IntoDiagArg for hir::def::Res<Id> {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Borrowed(self.descr()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for DiagLocation {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::from(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for Backtrace {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::from(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for Level {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::from(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for type_ir::ClosureKind {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
DiagArgValue::Str(self.as_str().into())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DiagSymbolList(Vec<Symbol>);
|
||||
|
||||
@ -244,12 +274,6 @@ fn into_diag_arg(self) -> DiagArgValue {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Id> IntoDiagArg for hir::def::Res<Id> {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::Borrowed(self.descr()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: EmissionGuarantee> Diagnostic<'_, G> for TargetDataLayoutErrors<'_> {
|
||||
fn into_diag(self, dcx: &DiagCtxt, level: Level) -> Diag<'_, G> {
|
||||
match self {
|
||||
@ -302,7 +326,7 @@ impl Subdiagnostic for SingleLabelManySpans {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_: F,
|
||||
_: &F,
|
||||
) {
|
||||
diag.span_labels(self.spans, self.label);
|
||||
}
|
||||
@ -316,24 +340,6 @@ pub struct ExpectedLifetimeParameter {
|
||||
pub count: usize,
|
||||
}
|
||||
|
||||
impl IntoDiagArg for DiagLocation {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::from(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for Backtrace {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::from(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for Level {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
DiagArgValue::Str(Cow::from(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[suggestion(errors_indicate_anonymous_lifetime, code = "{suggestion}", style = "verbose")]
|
||||
pub struct IndicateAnonymousLifetime {
|
||||
@ -343,8 +349,10 @@ pub struct IndicateAnonymousLifetime {
|
||||
pub suggestion: String,
|
||||
}
|
||||
|
||||
impl IntoDiagArg for type_ir::ClosureKind {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
DiagArgValue::Str(self.as_str().into())
|
||||
}
|
||||
#[derive(Subdiagnostic)]
|
||||
pub struct ElidedLifetimeInPathSubdiag {
|
||||
#[subdiagnostic]
|
||||
pub expected: ExpectedLifetimeParameter,
|
||||
#[subdiagnostic]
|
||||
pub indicate: Option<IndicateAnonymousLifetime>,
|
||||
}
|
||||
|
@ -40,8 +40,8 @@
|
||||
SubdiagMessageOp, Subdiagnostic,
|
||||
};
|
||||
pub use diagnostic_impls::{
|
||||
DiagArgFromDisplay, DiagSymbolList, ExpectedLifetimeParameter, IndicateAnonymousLifetime,
|
||||
SingleLabelManySpans,
|
||||
DiagArgFromDisplay, DiagSymbolList, ElidedLifetimeInPathSubdiag, ExpectedLifetimeParameter,
|
||||
IndicateAnonymousLifetime, SingleLabelManySpans,
|
||||
};
|
||||
pub use emitter::ColorConfig;
|
||||
pub use rustc_error_messages::{
|
||||
@ -1911,27 +1911,24 @@ fn can_be_subdiag(&self) -> bool {
|
||||
}
|
||||
|
||||
// FIXME(eddyb) this doesn't belong here AFAICT, should be moved to callsite.
|
||||
pub fn add_elided_lifetime_in_path_suggestion<G: EmissionGuarantee>(
|
||||
pub fn elided_lifetime_in_path_suggestion(
|
||||
source_map: &SourceMap,
|
||||
diag: &mut Diag<'_, G>,
|
||||
n: usize,
|
||||
path_span: Span,
|
||||
incl_angl_brckt: bool,
|
||||
insertion_span: Span,
|
||||
) {
|
||||
diag.subdiagnostic(diag.dcx, ExpectedLifetimeParameter { span: path_span, count: n });
|
||||
if !source_map.is_span_accessible(insertion_span) {
|
||||
) -> ElidedLifetimeInPathSubdiag {
|
||||
let expected = ExpectedLifetimeParameter { span: path_span, count: n };
|
||||
// Do not try to suggest anything if generated by a proc-macro.
|
||||
return;
|
||||
}
|
||||
let indicate = source_map.is_span_accessible(insertion_span).then(|| {
|
||||
let anon_lts = vec!["'_"; n].join(", ");
|
||||
let suggestion =
|
||||
if incl_angl_brckt { format!("<{anon_lts}>") } else { format!("{anon_lts}, ") };
|
||||
|
||||
diag.subdiagnostic(
|
||||
diag.dcx,
|
||||
IndicateAnonymousLifetime { span: insertion_span.shrink_to_hi(), count: n, suggestion },
|
||||
);
|
||||
IndicateAnonymousLifetime { span: insertion_span.shrink_to_hi(), count: n, suggestion }
|
||||
});
|
||||
|
||||
ElidedLifetimeInPathSubdiag { expected, indicate }
|
||||
}
|
||||
|
||||
pub fn report_ambiguity_error<'a, G: EmissionGuarantee>(
|
||||
|
@ -191,7 +191,7 @@ impl Subdiagnostic for TypeMismatchFruTypo {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: F,
|
||||
_f: &F,
|
||||
) {
|
||||
diag.arg("expr", self.expr.as_deref().unwrap_or("NONE"));
|
||||
|
||||
@ -370,7 +370,7 @@ impl Subdiagnostic for RemoveSemiForCoerce {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: F,
|
||||
_f: &F,
|
||||
) {
|
||||
let mut multispan: MultiSpan = self.semi.into();
|
||||
multispan.push_span_label(self.expr, fluent::hir_typeck_remove_semi_for_coerce_expr);
|
||||
@ -546,7 +546,7 @@ impl rustc_errors::Subdiagnostic for CastUnknownPointerSub {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
f: F,
|
||||
f: &F,
|
||||
) {
|
||||
match self {
|
||||
CastUnknownPointerSub::To(span) => {
|
||||
|
@ -239,7 +239,7 @@ impl Subdiagnostic for RegionOriginNote<'_> {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: F,
|
||||
_f: &F,
|
||||
) {
|
||||
let mut label_or_note = |span, msg: DiagMessage| {
|
||||
let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count();
|
||||
@ -304,7 +304,7 @@ impl Subdiagnostic for LifetimeMismatchLabels {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: F,
|
||||
_f: &F,
|
||||
) {
|
||||
match self {
|
||||
LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => {
|
||||
@ -352,7 +352,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: F,
|
||||
_f: &F,
|
||||
) {
|
||||
let mut mk_suggestion = || {
|
||||
let (
|
||||
@ -454,7 +454,7 @@ impl Subdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
mut self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: F,
|
||||
_f: &F,
|
||||
) {
|
||||
self.unmet_requirements
|
||||
.push_span_label(self.binding_span, fluent::infer_msl_introduces_static);
|
||||
@ -773,7 +773,7 @@ impl Subdiagnostic for ConsiderBorrowingParamHelp {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
f: F,
|
||||
f: &F,
|
||||
) {
|
||||
let mut type_param_span: MultiSpan = self.spans.clone().into();
|
||||
for &span in &self.spans {
|
||||
@ -818,7 +818,7 @@ impl Subdiagnostic for DynTraitConstraintSuggestion {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
f: F,
|
||||
f: &F,
|
||||
) {
|
||||
let mut multi_span: MultiSpan = vec![self.span].into();
|
||||
multi_span.push_span_label(self.span, fluent::infer_dtcs_has_lifetime_req_label);
|
||||
@ -865,7 +865,7 @@ impl Subdiagnostic for ReqIntroducedLocations {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
mut self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
f: F,
|
||||
f: &F,
|
||||
) {
|
||||
for sp in self.spans {
|
||||
self.span.push_span_label(sp, fluent::infer_ril_introduced_here);
|
||||
@ -888,7 +888,7 @@ impl Subdiagnostic for MoreTargeted {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: F,
|
||||
_f: &F,
|
||||
) {
|
||||
diag.code(E0772);
|
||||
diag.primary_message(fluent::infer_more_targeted);
|
||||
@ -1293,7 +1293,7 @@ impl Subdiagnostic for SuggestTuplePatternMany {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
f: F,
|
||||
f: &F,
|
||||
) {
|
||||
diag.arg("path", self.path);
|
||||
let message = f(diag, crate::fluent_generated::infer_stp_wrap_many.into());
|
||||
|
@ -163,7 +163,7 @@ impl Subdiagnostic for RegionExplanation<'_> {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
f: F,
|
||||
f: &F,
|
||||
) {
|
||||
diag.arg("pref_kind", self.prefix);
|
||||
diag.arg("suff_kind", self.suffix);
|
||||
|
@ -2,7 +2,7 @@
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
|
||||
use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
|
||||
use rustc_errors::{add_elided_lifetime_in_path_suggestion, Diag};
|
||||
use rustc_errors::{elided_lifetime_in_path_suggestion, Diag};
|
||||
use rustc_errors::{Applicability, SuggestionStyle};
|
||||
use rustc_middle::middle::stability;
|
||||
use rustc_session::lint::BuiltinLintDiag;
|
||||
@ -74,13 +74,15 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
|
||||
diag.span_note(span_def, "the macro is defined here");
|
||||
}
|
||||
BuiltinLintDiag::ElidedLifetimesInPaths(n, path_span, incl_angl_brckt, insertion_span) => {
|
||||
add_elided_lifetime_in_path_suggestion(
|
||||
diag.subdiagnostic(
|
||||
sess.dcx(),
|
||||
elided_lifetime_in_path_suggestion(
|
||||
sess.source_map(),
|
||||
diag,
|
||||
n,
|
||||
path_span,
|
||||
incl_angl_brckt,
|
||||
insertion_span,
|
||||
),
|
||||
);
|
||||
}
|
||||
BuiltinLintDiag::UnknownCrateTypes(span, note, sugg) => {
|
||||
|
@ -27,7 +27,7 @@ impl Subdiagnostic for OverruledAttributeSub {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: F,
|
||||
_f: &F,
|
||||
) {
|
||||
match self {
|
||||
OverruledAttributeSub::DefaultSource { id } => {
|
||||
|
@ -274,7 +274,7 @@ impl<'a, 'b> Subdiagnostic for SuggestChangingAssocTypes<'a, 'b> {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: F,
|
||||
_f: &F,
|
||||
) {
|
||||
// Access to associates types should use `<T as Bound>::Assoc`, which does not need a
|
||||
// bound. Let's see if this type does that.
|
||||
@ -330,7 +330,7 @@ impl Subdiagnostic for BuiltinTypeAliasGenericBoundsSuggestion {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: F,
|
||||
_f: &F,
|
||||
) {
|
||||
diag.multipart_suggestion(
|
||||
fluent::lint_suggestion,
|
||||
@ -451,7 +451,7 @@ impl Subdiagnostic for BuiltinUnpermittedTypeInitSub {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: F,
|
||||
_f: &F,
|
||||
) {
|
||||
let mut err = self.err;
|
||||
loop {
|
||||
@ -506,7 +506,7 @@ impl Subdiagnostic for BuiltinClashingExternSub<'_> {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: F,
|
||||
_f: &F,
|
||||
) {
|
||||
let mut expected_str = DiagStyledString::new();
|
||||
expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false);
|
||||
@ -788,7 +788,7 @@ impl Subdiagnostic for HiddenUnicodeCodepointsDiagLabels {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: F,
|
||||
_f: &F,
|
||||
) {
|
||||
for (c, span) in self.spans {
|
||||
diag.span_label(span, format!("{c:?}"));
|
||||
@ -806,7 +806,7 @@ impl Subdiagnostic for HiddenUnicodeCodepointsDiagSub {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: F,
|
||||
_f: &F,
|
||||
) {
|
||||
match self {
|
||||
HiddenUnicodeCodepointsDiagSub::Escape { spans } => {
|
||||
@ -954,7 +954,7 @@ impl Subdiagnostic for NonBindingLetSub {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: F,
|
||||
_f: &F,
|
||||
) {
|
||||
let can_suggest_binding = self.drop_fn_start_end.is_some() || !self.is_assign_desugar;
|
||||
|
||||
@ -1240,7 +1240,7 @@ impl Subdiagnostic for NonSnakeCaseDiagSub {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: F,
|
||||
_f: &F,
|
||||
) {
|
||||
match self {
|
||||
NonSnakeCaseDiagSub::Label { span } => {
|
||||
@ -1482,7 +1482,7 @@ impl Subdiagnostic for OverflowingBinHexSign {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: F,
|
||||
_f: &F,
|
||||
) {
|
||||
match self {
|
||||
OverflowingBinHexSign::Positive => {
|
||||
|
@ -71,6 +71,7 @@ pub(crate) fn into_tokens(self, mut structure: Structure<'_>) -> TokenStream {
|
||||
span_field: None,
|
||||
applicability: None,
|
||||
has_suggestion_parts: false,
|
||||
has_subdiagnostic: false,
|
||||
is_enum,
|
||||
};
|
||||
builder.into_tokens().unwrap_or_else(|v| v.to_compile_error())
|
||||
@ -90,7 +91,7 @@ pub(crate) fn into_tokens(self, mut structure: Structure<'_>) -> TokenStream {
|
||||
fn add_to_diag_with<__G, __F>(
|
||||
self,
|
||||
#diag: &mut rustc_errors::Diag<'_, __G>,
|
||||
#f: __F
|
||||
#f: &__F
|
||||
) where
|
||||
__G: rustc_errors::EmissionGuarantee,
|
||||
__F: rustc_errors::SubdiagMessageOp<__G>,
|
||||
@ -133,6 +134,10 @@ struct SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
|
||||
/// during finalization if still `false`.
|
||||
has_suggestion_parts: bool,
|
||||
|
||||
/// Set to true when a `#[subdiagnostic]` field is encountered, used to suppress the error
|
||||
/// emitted when no subdiagnostic kinds are specified on the variant itself.
|
||||
has_subdiagnostic: bool,
|
||||
|
||||
/// Set to true when this variant is an enum variant rather than just the body of a struct.
|
||||
is_enum: bool,
|
||||
}
|
||||
@ -373,6 +378,13 @@ fn generate_field_code_inner_path(
|
||||
|
||||
Ok(quote! {})
|
||||
}
|
||||
"subdiagnostic" => {
|
||||
let f = &self.parent.f;
|
||||
let diag = &self.parent.diag;
|
||||
let binding = &info.binding;
|
||||
self.has_subdiagnostic = true;
|
||||
Ok(quote! { #binding.add_to_diag_with(#diag, #f); })
|
||||
}
|
||||
_ => {
|
||||
let mut span_attrs = vec![];
|
||||
if kind_stats.has_multipart_suggestion {
|
||||
@ -480,18 +492,6 @@ fn generate_field_code_inner_list(
|
||||
|
||||
pub(crate) fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveError> {
|
||||
let kind_slugs = self.identify_kind()?;
|
||||
if kind_slugs.is_empty() {
|
||||
if self.is_enum {
|
||||
// It's okay for a variant to not be a subdiagnostic at all..
|
||||
return Ok(quote! {});
|
||||
} else {
|
||||
// ..but structs should always be _something_.
|
||||
throw_span_err!(
|
||||
self.variant.ast().ident.span().unwrap(),
|
||||
"subdiagnostic kind not specified"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
let kind_stats: KindsStatistics =
|
||||
kind_slugs.iter().map(|(kind, _slug, _no_span)| kind).collect();
|
||||
@ -510,6 +510,19 @@ pub(crate) fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveErro
|
||||
.map(|binding| self.generate_field_attr_code(binding, kind_stats))
|
||||
.collect();
|
||||
|
||||
if kind_slugs.is_empty() {
|
||||
if self.is_enum {
|
||||
// It's okay for a variant to not be a subdiagnostic at all..
|
||||
return Ok(quote! {});
|
||||
} else if !self.has_subdiagnostic {
|
||||
// ..but structs should always be _something_.
|
||||
throw_span_err!(
|
||||
self.variant.ast().ident.span().unwrap(),
|
||||
"subdiagnostic kind not specified"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
let span_field = self.span_field.value_ref();
|
||||
|
||||
let diag = &self.parent.diag;
|
||||
|
@ -144,6 +144,7 @@ pub fn extension(attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||
help,
|
||||
note,
|
||||
warning,
|
||||
subdiagnostic,
|
||||
suggestion,
|
||||
suggestion_short,
|
||||
suggestion_hidden,
|
||||
|
@ -423,7 +423,7 @@ impl Subdiagnostic for UnsafeNotInheritedLintNote {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: F,
|
||||
_f: &F,
|
||||
) {
|
||||
diag.span_note(self.signature_span, fluent::mir_build_unsafe_fn_safe_body);
|
||||
let body_start = self.body_span.shrink_to_lo();
|
||||
@ -871,7 +871,7 @@ impl<'tcx> Subdiagnostic for AdtDefinedHere<'tcx> {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: F,
|
||||
_f: &F,
|
||||
) {
|
||||
diag.arg("ty", self.ty);
|
||||
let mut spans = MultiSpan::from(self.adt_def_span);
|
||||
|
@ -1472,7 +1472,7 @@ impl Subdiagnostic for FnTraitMissingParen {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_: F,
|
||||
_: &F,
|
||||
) {
|
||||
diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren);
|
||||
let applicability = if self.machine_applicable {
|
||||
|
@ -1765,7 +1765,7 @@ impl Subdiagnostic for UnusedVariableStringInterp {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: F,
|
||||
_f: &F,
|
||||
) {
|
||||
diag.span_label(self.lit, crate::fluent_generated::passes_maybe_string_interpolation);
|
||||
diag.multipart_suggestion(
|
||||
|
@ -65,7 +65,7 @@ impl<'tcx> Subdiagnostic for Overlap<'tcx> {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_: F,
|
||||
_: &F,
|
||||
) {
|
||||
let Overlap { span, range } = self;
|
||||
|
||||
@ -113,7 +113,7 @@ impl<'tcx> Subdiagnostic for GappedRange<'tcx> {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_: F,
|
||||
_: &F,
|
||||
) {
|
||||
let GappedRange { span, gap, first_range } = self;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use rustc_errors::{codes::*, Applicability, MultiSpan};
|
||||
use rustc_errors::{codes::*, Applicability, ElidedLifetimeInPathSubdiag, MultiSpan};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::{
|
||||
symbol::{Ident, Symbol},
|
||||
@ -907,6 +907,8 @@ pub(crate) struct ExplicitAnonymousLivetimeReportError {
|
||||
pub(crate) struct ImplicitElidedLifetimeNotAllowedHere {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
#[subdiagnostic]
|
||||
pub(crate) subdiag: ElidedLifetimeInPathSubdiag,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
@ -1883,20 +1883,18 @@ fn resolve_elided_lifetimes_in_path(
|
||||
// async fn foo(_: std::cell::Ref<u32>) { ... }
|
||||
LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. }
|
||||
| LifetimeRibKind::AnonymousWarn(_) => {
|
||||
let mut err =
|
||||
self.r.dcx().create_err(errors::ImplicitElidedLifetimeNotAllowedHere {
|
||||
span: path_span,
|
||||
});
|
||||
let sess = self.r.tcx.sess;
|
||||
rustc_errors::add_elided_lifetime_in_path_suggestion(
|
||||
let subdiag = rustc_errors::elided_lifetime_in_path_suggestion(
|
||||
sess.source_map(),
|
||||
&mut err,
|
||||
expected_lifetimes,
|
||||
path_span,
|
||||
!segment.has_generic_args,
|
||||
elided_lifetime_span,
|
||||
);
|
||||
err.emit();
|
||||
self.r.dcx().emit_err(errors::ImplicitElidedLifetimeNotAllowedHere {
|
||||
span: path_span,
|
||||
subdiag,
|
||||
});
|
||||
should_lint = false;
|
||||
|
||||
for id in node_ids {
|
||||
|
@ -104,7 +104,7 @@ impl Subdiagnostic for AdjustSignatureBorrow {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: F,
|
||||
_f: &F,
|
||||
) {
|
||||
match self {
|
||||
AdjustSignatureBorrow::Borrow { to_borrow } => {
|
||||
|
@ -59,7 +59,7 @@ impl Subdiagnostic for UntranslatableInAddtoDiag {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
f: F,
|
||||
f: &F,
|
||||
) {
|
||||
diag.note("untranslatable diagnostic");
|
||||
//~^ ERROR diagnostics should be created using translatable messages
|
||||
@ -72,7 +72,7 @@ impl Subdiagnostic for TranslatableInAddtoDiag {
|
||||
fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
|
||||
self,
|
||||
diag: &mut Diag<'_, G>,
|
||||
f: F,
|
||||
f: &F,
|
||||
) {
|
||||
diag.note(crate::fluent_generated::no_crate_note);
|
||||
}
|
||||
|
@ -827,3 +827,13 @@ struct PrimarySpanOnVec {
|
||||
//~| NOTE there must be exactly one primary span
|
||||
sub: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
struct NestedParent {
|
||||
#[subdiagnostic]
|
||||
single_sub: A,
|
||||
#[subdiagnostic]
|
||||
option_sub: Option<A>,
|
||||
#[subdiagnostic]
|
||||
vec_sub: Vec<A>,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user