Skip to content

Commit d0ae2db

Browse files
committed
Expose FeatureGateSubdiagnostic struct instead of applying it opaquely
1 parent a65be18 commit d0ae2db

File tree

10 files changed

+83
-72
lines changed

10 files changed

+83
-72
lines changed

compiler/rustc_ast_lowering/src/errors.rs

+5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use rustc_errors::{
22
codes::*, Diag, DiagArgFromDisplay, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic,
33
};
44
use rustc_macros::{Diagnostic, Subdiagnostic};
5+
use rustc_session::errors::FeatureGateSubdiagnostic;
56
use rustc_span::{symbol::Ident, Span, Symbol};
67

78
#[derive(Diagnostic)]
@@ -384,12 +385,16 @@ pub enum BadReturnTypeNotation {
384385
#[primary_span]
385386
#[suggestion(code = "()", applicability = "maybe-incorrect")]
386387
span: Span,
388+
#[subdiagnostic]
389+
subdiag: Option<FeatureGateSubdiagnostic>,
387390
},
388391
#[diag(ast_lowering_bad_return_type_notation_output)]
389392
Output {
390393
#[primary_span]
391394
#[suggestion(code = "", applicability = "maybe-incorrect")]
392395
span: Span,
396+
#[subdiagnostic]
397+
subdiag: Option<FeatureGateSubdiagnostic>,
393398
},
394399
}
395400

compiler/rustc_ast_lowering/src/lib.rs

+18-16
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};
@@ -1005,27 +1005,29 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
10051005
} else if let Some(first_char) = constraint.ident.as_str().chars().next()
10061006
&& first_char.is_ascii_lowercase()
10071007
{
1008-
let mut err = if !data.inputs.is_empty() {
1009-
self.dcx().create_err(errors::BadReturnTypeNotation::Inputs {
1008+
let subdiag = if !self.tcx.features().return_type_notation
1009+
&& self.tcx.sess.is_nightly_build()
1010+
{
1011+
Some(get_feature_diagnostics(&self.tcx.sess, sym::return_type_notation))
1012+
} else {
1013+
None
1014+
};
1015+
1016+
let err = if !data.inputs.is_empty() {
1017+
errors::BadReturnTypeNotation::Inputs {
10101018
span: data.inputs_span,
1011-
})
1019+
subdiag,
1020+
}
10121021
} else if let FnRetTy::Ty(ty) = &data.output {
1013-
self.dcx().create_err(errors::BadReturnTypeNotation::Output {
1022+
errors::BadReturnTypeNotation::Output {
10141023
span: data.inputs_span.shrink_to_hi().to(ty.span),
1015-
})
1024+
subdiag,
1025+
}
10161026
} else {
10171027
unreachable!("inputs are empty and return type is not provided")
10181028
};
1019-
if !self.tcx.features().return_type_notation
1020-
&& self.tcx.sess.is_nightly_build()
1021-
{
1022-
add_feature_diagnostics(
1023-
&mut err,
1024-
&self.tcx.sess,
1025-
sym::return_type_notation,
1026-
);
1027-
}
1028-
err.emit();
1029+
self.dcx().create_err(err).emit();
1030+
10291031
GenericArgsCtor {
10301032
args: Default::default(),
10311033
bindings: &[],

compiler/rustc_hir_analysis/src/check/mod.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -284,28 +284,28 @@ fn default_body_is_unstable(
284284
None => none_note = true,
285285
};
286286

287-
let mut err = tcx.dcx().create_err(errors::MissingTraitItemUnstable {
288-
span: impl_span,
289-
some_note,
290-
none_note,
291-
missing_item_name,
292-
feature,
293-
reason: reason_str,
294-
});
295-
296287
let inject_span = item_did
297288
.as_local()
298289
.and_then(|id| tcx.crate_level_attribute_injection_span(tcx.local_def_id_to_hir_id(id)));
299-
rustc_session::parse::add_feature_diagnostics_for_issue(
300-
&mut err,
290+
let subdiag = rustc_session::parse::get_feature_diagnostics_for_issue(
301291
&tcx.sess,
302292
feature,
303293
rustc_feature::GateIssue::Library(issue),
304294
false,
305295
inject_span,
306296
);
307297

308-
err.emit();
298+
tcx.dcx()
299+
.create_err(errors::MissingTraitItemUnstable {
300+
span: impl_span,
301+
some_note,
302+
none_note,
303+
missing_item_name,
304+
feature,
305+
reason: reason_str,
306+
subdiag,
307+
})
308+
.emit();
309309
}
310310

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

compiler/rustc_hir_analysis/src/errors.rs

+3
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, Span, Symbol};
1011
mod pattern_types;
1112
pub use pattern_types::*;
@@ -954,6 +955,8 @@ pub(crate) struct MissingTraitItemUnstable {
954955
pub some_note: bool,
955956
#[note(hir_analysis_none_note)]
956957
pub none_note: bool,
958+
#[subdiagnostic]
959+
pub subdiag: FeatureGateSubdiagnostic,
957960
pub missing_item_name: Symbol,
958961
pub feature: Symbol,
959962
pub reason: String,

compiler/rustc_lint/src/levels.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -1072,13 +1072,15 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
10721072
|lint| {
10731073
lint.arg("name", lint_id.lint.name_lower());
10741074
lint.note(fluent::lint_note);
1075-
rustc_session::parse::add_feature_diagnostics_for_issue(
1076-
lint,
1077-
&self.sess,
1078-
feature,
1079-
GateIssue::Language,
1080-
lint_from_cli,
1081-
None,
1075+
lint.subdiagnostic(
1076+
self.sess.dcx(),
1077+
rustc_session::parse::get_feature_diagnostics_for_issue(
1078+
&self.sess,
1079+
feature,
1080+
GateIssue::Language,
1081+
lint_from_cli,
1082+
None,
1083+
),
10821084
);
10831085
},
10841086
);

compiler/rustc_lint/src/lints.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -244,10 +244,9 @@ pub struct BuiltinUngatedAsyncFnTrackCaller<'a> {
244244
impl<'a> LintDiagnostic<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> {
245245
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
246246
diag.span_label(self.label, fluent::lint_label);
247-
rustc_session::parse::add_feature_diagnostics(
248-
diag,
249-
self.session,
250-
sym::async_fn_track_caller,
247+
diag.subdiagnostic(
248+
self.session.dcx(),
249+
rustc_session::parse::get_feature_diagnostics(self.session, sym::async_fn_track_caller),
251250
);
252251
}
253252

compiler/rustc_session/src/errors.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,19 @@ use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
1212

1313
use crate::{config::CrateType, parse::ParseSess};
1414

15+
// FIXME: factor into separate structs to avoid dynamic DiagMessage field
1516
pub(crate) struct FeatureGateError {
1617
pub(crate) span: MultiSpan,
1718
pub(crate) explain: DiagMessage,
19+
pub(crate) subdiag: FeatureGateSubdiagnostic,
1820
}
1921

2022
impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for FeatureGateError {
2123
#[track_caller]
2224
fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
23-
Diag::new(dcx, level, self.explain).with_span(self.span).with_code(E0658)
25+
let mut diag = Diag::new(dcx, level, self.explain).with_span(self.span).with_code(E0658);
26+
diag.subdiagnostic(dcx, self.subdiag);
27+
diag
2428
}
2529
}
2630

compiler/rustc_session/src/parse.rs

+15-21
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
1515
use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc};
1616
use rustc_errors::emitter::{stderr_destination, HumanEmitter, SilentEmitter};
1717
use rustc_errors::{
18-
fallback_fluent_bundle, ColorConfig, Diag, DiagCtxt, DiagMessage, EmissionGuarantee, MultiSpan,
19-
StashKey,
18+
fallback_fluent_bundle, ColorConfig, Diag, DiagCtxt, DiagMessage, MultiSpan, StashKey,
2019
};
2120
use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures};
2221
use rustc_span::edition::Edition;
@@ -111,9 +110,9 @@ pub fn feature_err_issue(
111110
}
112111
}
113112

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

119118
/// Construct a future incompatibility diagnostic for a feature gate.
@@ -141,7 +140,10 @@ pub fn feature_warn_issue(
141140
explain: &'static str,
142141
) {
143142
let mut err = sess.psess.dcx.struct_span_warn(span, explain);
144-
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false, None);
143+
err.subdiagnostic(
144+
sess.dcx(),
145+
get_feature_diagnostics_for_issue(sess, feature, issue, false, None),
146+
);
145147

146148
// Decorate this as a future-incompatibility lint as in rustc_middle::lint::lint_level
147149
let lint = UNSTABLE_SYNTAX_PRE_EXPANSION;
@@ -154,29 +156,23 @@ pub fn feature_warn_issue(
154156
err.stash(span, StashKey::EarlySyntaxWarning);
155157
}
156158

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);
159+
/// Returns the subdiagnostics for a feature gate error.
160+
pub fn get_feature_diagnostics(sess: &Session, feature: Symbol) -> FeatureGateSubdiagnostic {
161+
get_feature_diagnostics_for_issue(sess, feature, GateIssue::Language, false, None)
164162
}
165163

166-
/// Adds the diagnostics for a feature to an existing error.
164+
/// Returns the subdiagnostics for a feature gate error.
167165
///
168166
/// This variant allows you to control whether it is a library or language feature.
169167
/// Almost always, you want to use this for a language feature. If so, prefer
170168
/// `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>,
169+
pub fn get_feature_diagnostics_for_issue(
174170
sess: &Session,
175171
feature: Symbol,
176172
issue: GateIssue,
177173
feature_from_cli: bool,
178174
inject_span: Option<Span>,
179-
) {
175+
) -> FeatureGateSubdiagnostic {
180176
let issue = find_feature_issue(feature, issue).map(|n| FeatureDiagnosticForIssue { n });
181177

182178
// #23973: do not suggest `#![feature(...)]` if we are in beta/stable
@@ -200,9 +196,7 @@ pub fn add_feature_diagnostics_for_issue<G: EmissionGuarantee>(
200196
(None, None)
201197
};
202198

203-
let subdiagnostic = FeatureGateSubdiagnostic { issue, upgrade_compiler, enable_feature };
204-
205-
err.subdiagnostic(sess.dcx(), subdiagnostic);
199+
FeatureGateSubdiagnostic { issue, upgrade_compiler, enable_feature }
206200
}
207201

208202
/// Info about a parsing session.

compiler/rustc_session/src/session.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::config::{
66
};
77
use crate::config::{ErrorOutputType, Input};
88
use crate::errors;
9-
use crate::parse::{add_feature_diagnostics, ParseSess};
9+
use crate::parse::{get_feature_diagnostics, ParseSess};
1010
use crate::search_paths::{PathKind, SearchPath};
1111
use crate::{filesearch, lint};
1212

@@ -301,13 +301,13 @@ impl Session {
301301
}
302302

303303
#[track_caller]
304+
#[allow(rustc::diagnostic_outside_of_impl)]
304305
pub fn create_feature_err<'a>(&'a self, err: impl Diagnostic<'a>, feature: Symbol) -> Diag<'a> {
305306
let mut err = self.dcx().create_err(err);
306307
if err.code.is_none() {
307-
#[allow(rustc::diagnostic_outside_of_impl)]
308308
err.code(E0658);
309309
}
310-
add_feature_diagnostics(&mut err, self, feature);
310+
err.subdiagnostic(self.dcx(), get_feature_diagnostics(self, feature));
311311
err
312312
}
313313

src/librustdoc/passes/check_custom_code_classes.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::html::markdown::{find_codes, ErrorCodes, LangString};
1111

1212
use rustc_errors::StashKey;
1313
use rustc_feature::GateIssue;
14-
use rustc_session::parse::add_feature_diagnostics_for_issue;
14+
use rustc_session::parse::get_feature_diagnostics_for_issue;
1515
use rustc_span::symbol::sym;
1616

1717
pub(crate) const CHECK_CUSTOM_CODE_CLASSES: Pass = Pass {
@@ -69,13 +69,15 @@ pub(crate) fn look_for_custom_classes<'tcx>(cx: &DocContext<'tcx>, item: &Item)
6969
let mut err = sess
7070
.dcx()
7171
.struct_span_warn(span, "custom classes in code blocks will change behaviour");
72-
add_feature_diagnostics_for_issue(
73-
&mut err,
74-
sess,
75-
sym::custom_code_classes_in_docs,
76-
GateIssue::Language,
77-
false,
78-
None,
72+
err.subdiagnostic(
73+
sess.dcx(),
74+
get_feature_diagnostics_for_issue(
75+
sess,
76+
sym::custom_code_classes_in_docs,
77+
GateIssue::Language,
78+
false,
79+
None,
80+
),
7981
);
8082

8183
err.note(

0 commit comments

Comments
 (0)