Skip to content

Commit 8ac7d7c

Browse files
committed
Expose FeatureGateSubdiagnostic struct instead of applying it opaquely
1 parent 7dbc04d commit 8ac7d7c

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 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
@@ -62,7 +62,7 @@ use rustc_index::{Idx, IndexSlice, IndexVec};
6262
use rustc_macros::extension;
6363
use rustc_middle::span_bug;
6464
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
65-
use rustc_session::parse::{add_feature_diagnostics, feature_err};
65+
use rustc_session::parse::{feature_err, get_feature_diagnostics};
6666
use rustc_span::symbol::{kw, sym, Ident, Symbol};
6767
use rustc_span::{DesugaringKind, Span, DUMMY_SP};
6868
use smallvec::{smallvec, SmallVec};
@@ -1010,29 +1010,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
10101010
if let Some(first_char) = constraint.ident.as_str().chars().next()
10111011
&& first_char.is_ascii_lowercase()
10121012
{
1013-
let mut err = if !data.inputs.is_empty() {
1014-
self.dcx().create_err(errors::BadReturnTypeNotation::Inputs {
1013+
let subdiag = if !self.tcx.features().return_type_notation
1014+
&& self.tcx.sess.is_nightly_build()
1015+
{
1016+
Some(get_feature_diagnostics(&self.tcx.sess, sym::return_type_notation))
1017+
} else {
1018+
None
1019+
};
1020+
1021+
let err = if !data.inputs.is_empty() {
1022+
errors::BadReturnTypeNotation::Inputs {
10151023
span: data.inputs_span,
1016-
})
1024+
subdiag,
1025+
}
10171026
} else if let FnRetTy::Ty(ty) = &data.output {
1018-
self.dcx().create_err(errors::BadReturnTypeNotation::Output {
1027+
errors::BadReturnTypeNotation::Output {
10191028
span: data.inputs_span.shrink_to_hi().to(ty.span),
1020-
})
1029+
subdiag,
1030+
}
10211031
} else {
1022-
self.dcx().create_err(errors::BadReturnTypeNotation::NeedsDots {
1023-
span: data.inputs_span,
1024-
})
1032+
errors::BadReturnTypeNotation::NeedsDots { span: data.inputs_span }
10251033
};
1026-
if !self.tcx.features().return_type_notation
1027-
&& self.tcx.sess.is_nightly_build()
1028-
{
1029-
add_feature_diagnostics(
1030-
&mut err,
1031-
&self.tcx.sess,
1032-
sym::return_type_notation,
1033-
);
1034-
}
1035-
err.emit();
1034+
self.dcx().create_err(err).emit();
1035+
10361036
GenericArgsCtor {
10371037
args: Default::default(),
10381038
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
@@ -40,7 +40,7 @@ use crate::config::{
4040
self, CoverageLevel, CrateType, ErrorOutputType, FunctionReturn, Input, InstrumentCoverage,
4141
OptLevel, OutFileName, OutputType, RemapPathScopeComponents, SwitchWithOptPath,
4242
};
43-
use crate::parse::{add_feature_diagnostics, ParseSess};
43+
use crate::parse::{get_feature_diagnostics, ParseSess};
4444
use crate::search_paths::{PathKind, SearchPath};
4545
use crate::{errors, filesearch, lint};
4646

@@ -299,13 +299,13 @@ impl Session {
299299
}
300300

301301
#[track_caller]
302+
#[allow(rustc::diagnostic_outside_of_impl)]
302303
pub fn create_feature_err<'a>(&'a self, err: impl Diagnostic<'a>, feature: Symbol) -> Diag<'a> {
303304
let mut err = self.dcx().create_err(err);
304305
if err.code.is_none() {
305-
#[allow(rustc::diagnostic_outside_of_impl)]
306306
err.code(E0658);
307307
}
308-
add_feature_diagnostics(&mut err, self, feature);
308+
err.subdiagnostic(get_feature_diagnostics(self, feature));
309309
err
310310
}
311311

0 commit comments

Comments
 (0)