Skip to content

Commit 039e6de

Browse files
committed
Make unstable library feature errors translatable
Translation is in an awkward position, but this provides a similar interface for both errors and soft-unstable lints, and enables the use of `DiagSymbolList` for simplifying error message construction.
1 parent 729ced5 commit 039e6de

File tree

9 files changed

+107
-72
lines changed

9 files changed

+107
-72
lines changed

compiler/rustc_lint/src/context/diagnostics.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -382,8 +382,9 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
382382
BuiltinLintDiag::MacroRuleNeverUsed(n, name) => {
383383
lints::MacroRuleNeverUsed { n: n + 1, name }.decorate_lint(diag);
384384
}
385-
BuiltinLintDiag::UnstableFeature(msg) => {
386-
lints::UnstableFeature { msg }.decorate_lint(diag);
385+
BuiltinLintDiag::SoftUnstableMacro { feature, reason } => {
386+
rustc_middle::error::SoftUnstableLibraryFeature::new(feature, reason)
387+
.decorate_lint(diag);
387388
}
388389
BuiltinLintDiag::AvoidUsingIntelSyntax => {
389390
lints::AvoidIntelSyntax.decorate_lint(diag);

compiler/rustc_lint/src/lints.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2408,16 +2408,6 @@ pub(crate) struct MacroRuleNeverUsed {
24082408
pub name: Symbol,
24092409
}
24102410

2411-
pub(crate) struct UnstableFeature {
2412-
pub msg: DiagMessage,
2413-
}
2414-
2415-
impl<'a> LintDiagnostic<'a, ()> for UnstableFeature {
2416-
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
2417-
diag.primary_message(self.msg);
2418-
}
2419-
}
2420-
24212411
#[derive(LintDiagnostic)]
24222412
#[diag(lint_avoid_intel_syntax)]
24232413
pub(crate) struct AvoidIntelSyntax;

compiler/rustc_lint_defs/src/lib.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
99
use rustc_data_structures::stable_hasher::{
1010
HashStable, StableCompare, StableHasher, ToStableHashKey,
1111
};
12-
use rustc_error_messages::{DiagMessage, MultiSpan};
12+
use rustc_error_messages::MultiSpan;
1313
use rustc_hir::def::Namespace;
1414
use rustc_hir::{HashStableContext, HirId, MissingLifetimeKind};
1515
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
@@ -750,7 +750,10 @@ pub enum BuiltinLintDiag {
750750
MacroIsPrivate(Ident),
751751
UnusedMacroDefinition(Symbol),
752752
MacroRuleNeverUsed(usize, Symbol),
753-
UnstableFeature(DiagMessage),
753+
SoftUnstableMacro {
754+
feature: Symbol,
755+
reason: Option<Symbol>,
756+
},
754757
AvoidUsingIntelSyntax,
755758
AvoidUsingAttSyntax,
756759
IncompleteInclude,

compiler/rustc_middle/messages.ftl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,15 @@ middle_type_length_limit = reached the type-length limit while instantiating `{$
102102
middle_unknown_layout =
103103
the type `{$ty}` has an unknown layout
104104
105+
middle_unstable_library_feature =
106+
use of unstable library {$count ->
107+
[one] feature
108+
*[other] features
109+
} {$features}{STREQ($reason, "") ->
110+
[true] {""}
111+
*[false] : {$reason}
112+
}
113+
105114
middle_values_too_big =
106115
values of the type `{$ty}` are too big for the target architecture
107116
middle_written_to_path = the full type name has been written to '{$path}'

compiler/rustc_middle/src/error.rs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use std::fmt;
22
use std::path::PathBuf;
33

44
use rustc_errors::codes::*;
5-
use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage};
6-
use rustc_macros::{Diagnostic, Subdiagnostic};
5+
use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, DiagSymbolList};
6+
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
77
use rustc_span::{Span, Symbol};
88

99
use crate::ty::Ty;
@@ -164,3 +164,40 @@ pub struct TypeLengthLimit {
164164
pub path: PathBuf,
165165
pub type_length: usize,
166166
}
167+
168+
#[derive(Diagnostic)]
169+
#[diag(middle_unstable_library_feature, code = E0658)]
170+
pub struct UnstableLibraryFeatureError {
171+
#[primary_span]
172+
pub span: Span,
173+
pub features: DiagSymbolList,
174+
pub count: usize,
175+
pub reason: String,
176+
}
177+
178+
impl UnstableLibraryFeatureError {
179+
pub fn new(feature: Symbol, reason: Option<Symbol>, span: Span) -> Self {
180+
let SoftUnstableLibraryFeature { features, count, reason } =
181+
SoftUnstableLibraryFeature::new(feature, reason);
182+
UnstableLibraryFeatureError { span, features, count, reason }
183+
}
184+
}
185+
186+
/// Lint diagnostic for soft_unstable
187+
#[derive(LintDiagnostic)]
188+
#[diag(middle_unstable_library_feature)]
189+
pub struct SoftUnstableLibraryFeature {
190+
pub features: DiagSymbolList,
191+
pub count: usize,
192+
pub reason: String,
193+
}
194+
195+
impl SoftUnstableLibraryFeature {
196+
pub fn new(feature: Symbol, reason: Option<Symbol>) -> Self {
197+
SoftUnstableLibraryFeature {
198+
features: vec![feature].into(),
199+
count: 1,
200+
reason: reason.map_or(String::new(), |r| r.to_string()),
201+
}
202+
}
203+
}

compiler/rustc_middle/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#![feature(if_let_guard)]
4949
#![feature(intra_doc_pointers)]
5050
#![feature(iter_from_coroutine)]
51+
#![feature(iter_intersperse)]
5152
#![feature(let_chains)]
5253
#![feature(macro_metavar_expr)]
5354
#![feature(min_specialization)]

compiler/rustc_middle/src/middle/stability.rs

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
1717
use rustc_session::Session;
1818
use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE};
1919
use rustc_session::lint::{BuiltinLintDiag, DeprecatedSinceKind, Level, Lint, LintBuffer};
20-
use rustc_session::parse::feature_err_issues;
20+
use rustc_session::parse::add_feature_diagnostics_for_issues;
2121
use rustc_span::Span;
2222
use rustc_span::symbol::{Symbol, sym};
2323
use tracing::debug;
2424

2525
pub use self::StabilityLevel::*;
26+
use crate::error::{SoftUnstableLibraryFeature, UnstableLibraryFeatureError};
2627
use crate::ty::TyCtxt;
2728

2829
#[derive(PartialEq, Clone, Copy, Debug)]
@@ -106,25 +107,23 @@ pub fn report_unstable(
106107
reason: Option<Symbol>,
107108
issue: Option<NonZero<u32>>,
108109
suggestion: Option<(Span, String, String, Applicability)>,
109-
is_soft: bool,
110110
span: Span,
111-
soft_handler: impl FnOnce(&'static Lint, Span, String),
112111
) {
113-
let msg = match reason {
114-
Some(r) => format!("use of unstable library feature `{feature}`: {r}"),
115-
None => format!("use of unstable library feature `{feature}`"),
116-
};
117-
118-
if is_soft {
119-
soft_handler(SOFT_UNSTABLE, span, msg)
120-
} else {
121-
let issues = Vec::from_iter(issue);
122-
let mut err = feature_err_issues(sess, &[feature], span, GateIssues::Library(issues), msg);
123-
if let Some((inner_types, msg, sugg, applicability)) = suggestion {
124-
err.span_suggestion(inner_types, msg, sugg, applicability);
125-
}
126-
err.emit();
112+
let features = vec![feature];
113+
114+
let mut err = sess.dcx().create_err(UnstableLibraryFeatureError::new(feature, reason, span));
115+
add_feature_diagnostics_for_issues(
116+
&mut err,
117+
sess,
118+
&features,
119+
GateIssues::Library(Vec::from_iter(issue)),
120+
false,
121+
None,
122+
);
123+
if let Some((inner_types, msg, sugg, applicability)) = suggestion {
124+
err.span_suggestion(inner_types, msg, sugg, applicability);
127125
}
126+
err.emit();
128127
}
129128

130129
fn deprecation_lint(is_in_effect: bool) -> &'static Lint {
@@ -565,26 +564,23 @@ impl<'tcx> TyCtxt<'tcx> {
565564
allow_unstable: AllowUnstable,
566565
unmarked: impl FnOnce(Span, DefId),
567566
) -> bool {
568-
let soft_handler = |lint, span, msg: String| {
569-
self.node_span_lint(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, |lint| {
570-
lint.primary_message(msg);
571-
})
572-
};
573567
let eval_result =
574568
self.eval_stability_allow_unstable(def_id, id, span, method_span, allow_unstable);
575569
let is_allowed = matches!(eval_result, EvalResult::Allow);
576570
match eval_result {
577571
EvalResult::Allow => {}
578-
EvalResult::Deny { feature, reason, issue, suggestion, is_soft } => report_unstable(
579-
self.sess,
580-
feature,
581-
reason,
582-
issue,
583-
suggestion,
584-
is_soft,
585-
span,
586-
soft_handler,
587-
),
572+
EvalResult::Deny { feature, reason, issue, suggestion, is_soft } => {
573+
if is_soft {
574+
self.emit_node_span_lint(
575+
SOFT_UNSTABLE,
576+
id.unwrap_or(hir::CRATE_HIR_ID),
577+
span,
578+
SoftUnstableLibraryFeature::new(feature, reason),
579+
);
580+
} else {
581+
report_unstable(self.sess, feature, reason, issue, suggestion, span);
582+
}
583+
}
588584
EvalResult::Unmarked => unmarked(span, def_id),
589585
}
590586

compiler/rustc_middle/src/ty/context.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2969,22 +2969,22 @@ impl<'tcx> TyCtxt<'tcx> {
29692969
self,
29702970
diag: &mut Diag<'_, E>,
29712971
hir_id: Option<HirId>,
2972-
features: impl IntoIterator<Item = (String, Symbol)>,
2972+
featuresets: impl IntoIterator<Item = (String, impl std::fmt::Display)>,
29732973
) {
29742974
if !self.sess.is_nightly_build() {
29752975
return;
29762976
}
29772977

29782978
let span = hir_id.and_then(|id| self.crate_level_attribute_injection_span(id));
2979-
for (desc, feature) in features {
2979+
for (desc, features) in featuresets {
29802980
// FIXME: make this string translatable
29812981
let msg =
2982-
format!("add `#![feature({feature})]` to the crate attributes to enable{desc}");
2982+
format!("add `#![feature({features})]` to the crate attributes to enable{desc}");
29832983
if let Some(span) = span {
29842984
diag.span_suggestion_verbose(
29852985
span,
29862986
msg,
2987-
format!("#![feature({feature})]\n"),
2987+
format!("#![feature({features})]\n"),
29882988
Applicability::MaybeIncorrect,
29892989
);
29902990
} else {

compiler/rustc_resolve/src/macros.rs

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,28 +1009,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
10091009
|feature| self.tcx.features().enabled(feature) || span.allows_unstable(feature);
10101010
let allowed_by_implication = implied_by.is_some_and(|feature| is_allowed(feature));
10111011
if !is_allowed(feature) && !allowed_by_implication {
1012-
let lint_buffer = &mut self.lint_buffer;
1013-
let soft_handler = |lint, span, msg: String| {
1014-
lint_buffer.buffer_lint(
1015-
lint,
1012+
if is_soft {
1013+
self.lint_buffer.buffer_lint(
1014+
SOFT_UNSTABLE,
10161015
node_id,
10171016
span,
1018-
BuiltinLintDiag::UnstableFeature(
1019-
// FIXME make this translatable
1020-
msg.into(),
1021-
),
1022-
)
1023-
};
1024-
stability::report_unstable(
1025-
self.tcx.sess,
1026-
feature,
1027-
reason.to_opt_reason(),
1028-
issue,
1029-
None,
1030-
is_soft,
1031-
span,
1032-
soft_handler,
1033-
);
1017+
BuiltinLintDiag::SoftUnstableMacro {
1018+
feature,
1019+
reason: reason.to_opt_reason(),
1020+
},
1021+
);
1022+
} else {
1023+
stability::report_unstable(
1024+
self.tcx.sess,
1025+
feature,
1026+
reason.to_opt_reason(),
1027+
issue,
1028+
None,
1029+
span,
1030+
);
1031+
}
10341032
}
10351033
}
10361034
}

0 commit comments

Comments
 (0)