Skip to content

Commit abf3a48

Browse files
committed
Expose FeatureGateSubdiagnostic struct instead of applying it opaquely
1 parent 45fe740 commit abf3a48

File tree

9 files changed

+65
-61
lines changed

9 files changed

+65
-61
lines changed

compiler/rustc_ast_lowering/src/errors.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use rustc_errors::codes::*;
22
use rustc_errors::{Diag, DiagArgFromDisplay, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic};
33
use rustc_macros::{Diagnostic, Subdiagnostic};
4+
use rustc_session::errors::FeatureGateSubdiagnostic;
45
use rustc_span::symbol::Ident;
56
use rustc_span::{Span, Symbol};
67

@@ -386,12 +387,16 @@ pub(crate) enum BadReturnTypeNotation {
386387
#[primary_span]
387388
#[suggestion(code = "()", applicability = "maybe-incorrect")]
388389
span: Span,
390+
#[subdiagnostic]
391+
subdiag: Option<FeatureGateSubdiagnostic>,
389392
},
390393
#[diag(ast_lowering_bad_return_type_notation_output)]
391394
Output {
392395
#[primary_span]
393396
#[suggestion(code = "", applicability = "maybe-incorrect")]
394397
span: Span,
398+
#[subdiagnostic]
399+
subdiag: Option<FeatureGateSubdiagnostic>,
395400
},
396401
#[diag(ast_lowering_bad_return_type_notation_needs_dots)]
397402
NeedsDots {

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ use rustc_index::{Idx, IndexSlice, IndexVec};
6363
use rustc_macros::extension;
6464
use rustc_middle::span_bug;
6565
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
66-
use rustc_session::parse::{add_feature_diagnostics, feature_err};
66+
use rustc_session::parse::{feature_err, get_feature_diagnostics};
6767
use rustc_span::symbol::{kw, sym, Ident, Symbol};
6868
use rustc_span::{DesugaringKind, Span, DUMMY_SP};
6969
use smallvec::{smallvec, SmallVec};
@@ -1009,29 +1009,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
10091009
if let Some(first_char) = constraint.ident.as_str().chars().next()
10101010
&& first_char.is_ascii_lowercase()
10111011
{
1012-
let mut err = if !data.inputs.is_empty() {
1013-
self.dcx().create_err(errors::BadReturnTypeNotation::Inputs {
1012+
let subdiag = if !self.tcx.features().return_type_notation
1013+
&& self.tcx.sess.is_nightly_build()
1014+
{
1015+
Some(get_feature_diagnostics(&self.tcx.sess, sym::return_type_notation))
1016+
} else {
1017+
None
1018+
};
1019+
1020+
let err = if !data.inputs.is_empty() {
1021+
errors::BadReturnTypeNotation::Inputs {
10141022
span: data.inputs_span,
1015-
})
1023+
subdiag,
1024+
}
10161025
} else if let FnRetTy::Ty(ty) = &data.output {
1017-
self.dcx().create_err(errors::BadReturnTypeNotation::Output {
1026+
errors::BadReturnTypeNotation::Output {
10181027
span: data.inputs_span.shrink_to_hi().to(ty.span),
1019-
})
1028+
subdiag,
1029+
}
10201030
} else {
1021-
self.dcx().create_err(errors::BadReturnTypeNotation::NeedsDots {
1022-
span: data.inputs_span,
1023-
})
1031+
errors::BadReturnTypeNotation::NeedsDots { span: data.inputs_span }
10241032
};
1025-
if !self.tcx.features().return_type_notation
1026-
&& self.tcx.sess.is_nightly_build()
1027-
{
1028-
add_feature_diagnostics(
1029-
&mut err,
1030-
&self.tcx.sess,
1031-
sym::return_type_notation,
1032-
);
1033-
}
1034-
err.emit();
1033+
self.dcx().create_err(err).emit();
1034+
10351035
GenericArgsCtor {
10361036
args: Default::default(),
10371037
constraints: &[],

compiler/rustc_hir_analysis/src/check/mod.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -311,28 +311,28 @@ fn default_body_is_unstable(
311311
None => none_note = true,
312312
};
313313

314-
let mut err = tcx.dcx().create_err(errors::MissingTraitItemUnstable {
315-
span: impl_span,
316-
some_note,
317-
none_note,
318-
missing_item_name,
319-
feature,
320-
reason: reason_str,
321-
});
322-
323314
let inject_span = item_did
324315
.as_local()
325316
.and_then(|id| tcx.crate_level_attribute_injection_span(tcx.local_def_id_to_hir_id(id)));
326-
rustc_session::parse::add_feature_diagnostics_for_issue(
327-
&mut err,
317+
let subdiag = rustc_session::parse::get_feature_diagnostics_for_issue(
328318
&tcx.sess,
329319
feature,
330320
rustc_feature::GateIssue::Library(issue),
331321
false,
332322
inject_span,
333323
);
334324

335-
err.emit();
325+
tcx.dcx()
326+
.create_err(errors::MissingTraitItemUnstable {
327+
span: impl_span,
328+
some_note,
329+
none_note,
330+
missing_item_name,
331+
feature,
332+
reason: reason_str,
333+
subdiag,
334+
})
335+
.emit();
336336
}
337337

338338
/// Re-sugar `ty::GenericPredicates` in a way suitable to be used in structured suggestions.

compiler/rustc_hir_analysis/src/errors.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_errors::{
66
};
77
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
88
use rustc_middle::ty::Ty;
9+
use rustc_session::errors::FeatureGateSubdiagnostic;
910
use rustc_span::symbol::Ident;
1011
use rustc_span::{Span, Symbol};
1112

@@ -987,6 +988,8 @@ pub(crate) struct MissingTraitItemUnstable {
987988
pub some_note: bool,
988989
#[note(hir_analysis_none_note)]
989990
pub none_note: bool,
991+
#[subdiagnostic]
992+
pub subdiag: FeatureGateSubdiagnostic,
990993
pub missing_item_name: Symbol,
991994
pub feature: Symbol,
992995
pub reason: String,

compiler/rustc_lint/src/levels.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,14 +1042,13 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
10421042
lint.primary_message(fluent::lint_unknown_gated_lint);
10431043
lint.arg("name", lint_id.lint.name_lower());
10441044
lint.note(fluent::lint_note);
1045-
rustc_session::parse::add_feature_diagnostics_for_issue(
1046-
lint,
1045+
lint.subdiagnostic(rustc_session::parse::get_feature_diagnostics_for_issue(
10471046
&self.sess,
10481047
feature,
10491048
GateIssue::Language,
10501049
lint_from_cli,
10511050
None,
1052-
);
1051+
));
10531052
});
10541053
}
10551054

compiler/rustc_lint/src/lints.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,11 +242,10 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> {
242242
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
243243
diag.primary_message(fluent::lint_ungated_async_fn_track_caller);
244244
diag.span_label(self.label, fluent::lint_label);
245-
rustc_session::parse::add_feature_diagnostics(
246-
diag,
245+
diag.subdiagnostic(rustc_session::parse::get_feature_diagnostics(
247246
self.session,
248247
sym::async_fn_track_caller,
249-
);
248+
));
250249
}
251250
}
252251

compiler/rustc_session/src/errors.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,19 @@ use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
1414
use crate::config::CrateType;
1515
use crate::parse::ParseSess;
1616

17+
// FIXME: factor into separate structs to avoid dynamic DiagMessage field
1718
pub(crate) struct FeatureGateError {
1819
pub(crate) span: MultiSpan,
1920
pub(crate) explain: DiagMessage,
21+
pub(crate) subdiag: FeatureGateSubdiagnostic,
2022
}
2123

2224
impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for FeatureGateError {
2325
#[track_caller]
2426
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
25-
Diag::new(dcx, level, self.explain).with_span(self.span).with_code(E0658)
27+
let mut diag = Diag::new(dcx, level, self.explain).with_span(self.span).with_code(E0658);
28+
diag.subdiagnostic(self.subdiag);
29+
diag
2630
}
2731
}
2832

compiler/rustc_session/src/parse.rs

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
99
use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc};
1010
use rustc_errors::emitter::{stderr_destination, HumanEmitter, SilentEmitter};
1111
use rustc_errors::{
12-
fallback_fluent_bundle, ColorConfig, Diag, DiagCtxt, DiagCtxtHandle, DiagMessage,
13-
EmissionGuarantee, MultiSpan, StashKey,
12+
fallback_fluent_bundle, ColorConfig, Diag, DiagCtxt, DiagCtxtHandle, DiagMessage, MultiSpan,
13+
StashKey,
1414
};
1515
use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures};
1616
use rustc_span::edition::Edition;
@@ -111,9 +111,9 @@ pub fn feature_err_issue(
111111
}
112112
}
113113

114-
let mut err = sess.dcx().create_err(FeatureGateError { span, explain: explain.into() });
115-
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false, None);
116-
err
114+
let subdiag = get_feature_diagnostics_for_issue(sess, feature, issue, false, None);
115+
116+
sess.dcx().create_err(FeatureGateError { span, explain: explain.into(), subdiag })
117117
}
118118

119119
/// Construct a future incompatibility diagnostic for a feature gate.
@@ -141,7 +141,7 @@ pub fn feature_warn_issue(
141141
explain: &'static str,
142142
) {
143143
let mut err = sess.dcx().struct_span_warn(span, explain);
144-
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false, None);
144+
err.subdiagnostic(get_feature_diagnostics_for_issue(sess, feature, issue, false, None));
145145

146146
// Decorate this as a future-incompatibility lint as in rustc_middle::lint::lint_level
147147
let lint = UNSTABLE_SYNTAX_PRE_EXPANSION;
@@ -154,29 +154,23 @@ pub fn feature_warn_issue(
154154
err.stash(span, StashKey::EarlySyntaxWarning);
155155
}
156156

157-
/// Adds the diagnostics for a feature to an existing error.
158-
pub fn add_feature_diagnostics<G: EmissionGuarantee>(
159-
err: &mut Diag<'_, G>,
160-
sess: &Session,
161-
feature: Symbol,
162-
) {
163-
add_feature_diagnostics_for_issue(err, sess, feature, GateIssue::Language, false, None);
157+
/// Returns the subdiagnostics for a feature gate error.
158+
pub fn get_feature_diagnostics(sess: &Session, feature: Symbol) -> FeatureGateSubdiagnostic {
159+
get_feature_diagnostics_for_issue(sess, feature, GateIssue::Language, false, None)
164160
}
165161

166-
/// Adds the diagnostics for a feature to an existing error.
162+
/// Returns the subdiagnostics for a feature gate error.
167163
///
168164
/// This variant allows you to control whether it is a library or language feature.
169165
/// Almost always, you want to use this for a language feature. If so, prefer
170-
/// `add_feature_diagnostics`.
171-
#[allow(rustc::diagnostic_outside_of_impl)] // FIXME
172-
pub fn add_feature_diagnostics_for_issue<G: EmissionGuarantee>(
173-
err: &mut Diag<'_, G>,
166+
/// [`get_feature_diagnostics`].
167+
pub fn get_feature_diagnostics_for_issue(
174168
sess: &Session,
175169
feature: Symbol,
176170
issue: GateIssue,
177171
feature_from_cli: bool,
178172
inject_span: Option<Span>,
179-
) {
173+
) -> FeatureGateSubdiagnostic {
180174
let issue = find_feature_issue(feature, issue).map(|n| FeatureDiagnosticForIssue { n });
181175

182176
// #23973: do not suggest `#![feature(...)]` if we are in beta/stable
@@ -202,7 +196,7 @@ pub fn add_feature_diagnostics_for_issue<G: EmissionGuarantee>(
202196
(None, None)
203197
};
204198

205-
err.subdiagnostic(FeatureGateSubdiagnostic { issue, upgrade_compiler, enable_feature });
199+
FeatureGateSubdiagnostic { issue, upgrade_compiler, enable_feature }
206200
}
207201

208202
/// Info about a parsing session.

compiler/rustc_session/src/session.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ use crate::config::{
4141
InstrumentCoverage, OptLevel, OutFileName, OutputType, RemapPathScopeComponents,
4242
SwitchWithOptPath,
4343
};
44-
use crate::parse::{add_feature_diagnostics, ParseSess};
44+
use crate::parse::{get_feature_diagnostics, ParseSess};
4545
use crate::search_paths::{PathKind, SearchPath};
4646
use crate::{errors, filesearch, lint};
4747

@@ -300,13 +300,13 @@ impl Session {
300300
}
301301

302302
#[track_caller]
303+
#[allow(rustc::diagnostic_outside_of_impl)]
303304
pub fn create_feature_err<'a>(&'a self, err: impl Diagnostic<'a>, feature: Symbol) -> Diag<'a> {
304305
let mut err = self.dcx().create_err(err);
305306
if err.code.is_none() {
306-
#[allow(rustc::diagnostic_outside_of_impl)]
307307
err.code(E0658);
308308
}
309-
add_feature_diagnostics(&mut err, self, feature);
309+
err.subdiagnostic(get_feature_diagnostics(self, feature));
310310
err
311311
}
312312

0 commit comments

Comments
 (0)