Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multiple stability attributes on items #131824

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Prev Previous commit
Next Next commit
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.
dianne committed Nov 19, 2024
commit 039e6de0fedd3bf6a56f50c140ac7e35c9de1034
5 changes: 3 additions & 2 deletions compiler/rustc_lint/src/context/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -382,8 +382,9 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
BuiltinLintDiag::MacroRuleNeverUsed(n, name) => {
lints::MacroRuleNeverUsed { n: n + 1, name }.decorate_lint(diag);
}
BuiltinLintDiag::UnstableFeature(msg) => {
lints::UnstableFeature { msg }.decorate_lint(diag);
BuiltinLintDiag::SoftUnstableMacro { feature, reason } => {
rustc_middle::error::SoftUnstableLibraryFeature::new(feature, reason)
.decorate_lint(diag);
}
BuiltinLintDiag::AvoidUsingIntelSyntax => {
lints::AvoidIntelSyntax.decorate_lint(diag);
10 changes: 0 additions & 10 deletions compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
@@ -2408,16 +2408,6 @@ pub(crate) struct MacroRuleNeverUsed {
pub name: Symbol,
}

pub(crate) struct UnstableFeature {
pub msg: DiagMessage,
}

impl<'a> LintDiagnostic<'a, ()> for UnstableFeature {
fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
diag.primary_message(self.msg);
}
}

#[derive(LintDiagnostic)]
#[diag(lint_avoid_intel_syntax)]
pub(crate) struct AvoidIntelSyntax;
7 changes: 5 additions & 2 deletions compiler/rustc_lint_defs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::stable_hasher::{
HashStable, StableCompare, StableHasher, ToStableHashKey,
};
use rustc_error_messages::{DiagMessage, MultiSpan};
use rustc_error_messages::MultiSpan;
use rustc_hir::def::Namespace;
use rustc_hir::{HashStableContext, HirId, MissingLifetimeKind};
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
@@ -750,7 +750,10 @@ pub enum BuiltinLintDiag {
MacroIsPrivate(Ident),
UnusedMacroDefinition(Symbol),
MacroRuleNeverUsed(usize, Symbol),
UnstableFeature(DiagMessage),
SoftUnstableMacro {
feature: Symbol,
reason: Option<Symbol>,
},
AvoidUsingIntelSyntax,
AvoidUsingAttSyntax,
IncompleteInclude,
9 changes: 9 additions & 0 deletions compiler/rustc_middle/messages.ftl
Original file line number Diff line number Diff line change
@@ -102,6 +102,15 @@ middle_type_length_limit = reached the type-length limit while instantiating `{$
middle_unknown_layout =
the type `{$ty}` has an unknown layout

middle_unstable_library_feature =
use of unstable library {$count ->
[one] feature
*[other] features
} {$features}{STREQ($reason, "") ->
[true] {""}
*[false] : {$reason}
}

middle_values_too_big =
values of the type `{$ty}` are too big for the target architecture
middle_written_to_path = the full type name has been written to '{$path}'
41 changes: 39 additions & 2 deletions compiler/rustc_middle/src/error.rs
Original file line number Diff line number Diff line change
@@ -2,8 +2,8 @@ use std::fmt;
use std::path::PathBuf;

use rustc_errors::codes::*;
use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage};
use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, DiagSymbolList};
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_span::{Span, Symbol};

use crate::ty::Ty;
@@ -164,3 +164,40 @@ pub struct TypeLengthLimit {
pub path: PathBuf,
pub type_length: usize,
}

#[derive(Diagnostic)]
#[diag(middle_unstable_library_feature, code = E0658)]
pub struct UnstableLibraryFeatureError {
#[primary_span]
pub span: Span,
pub features: DiagSymbolList,
pub count: usize,
pub reason: String,
}

impl UnstableLibraryFeatureError {
pub fn new(feature: Symbol, reason: Option<Symbol>, span: Span) -> Self {
let SoftUnstableLibraryFeature { features, count, reason } =
SoftUnstableLibraryFeature::new(feature, reason);
UnstableLibraryFeatureError { span, features, count, reason }
}
}

/// Lint diagnostic for soft_unstable
#[derive(LintDiagnostic)]
#[diag(middle_unstable_library_feature)]
pub struct SoftUnstableLibraryFeature {
pub features: DiagSymbolList,
pub count: usize,
pub reason: String,
}

impl SoftUnstableLibraryFeature {
pub fn new(feature: Symbol, reason: Option<Symbol>) -> Self {
SoftUnstableLibraryFeature {
features: vec![feature].into(),
count: 1,
reason: reason.map_or(String::new(), |r| r.to_string()),
}
}
}
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/lib.rs
Original file line number Diff line number Diff line change
@@ -48,6 +48,7 @@
#![feature(if_let_guard)]
#![feature(intra_doc_pointers)]
#![feature(iter_from_coroutine)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
#![feature(macro_metavar_expr)]
#![feature(min_specialization)]
60 changes: 28 additions & 32 deletions compiler/rustc_middle/src/middle/stability.rs
Original file line number Diff line number Diff line change
@@ -17,12 +17,13 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_session::Session;
use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE};
use rustc_session::lint::{BuiltinLintDiag, DeprecatedSinceKind, Level, Lint, LintBuffer};
use rustc_session::parse::feature_err_issues;
use rustc_session::parse::add_feature_diagnostics_for_issues;
use rustc_span::Span;
use rustc_span::symbol::{Symbol, sym};
use tracing::debug;

pub use self::StabilityLevel::*;
use crate::error::{SoftUnstableLibraryFeature, UnstableLibraryFeatureError};
use crate::ty::TyCtxt;

#[derive(PartialEq, Clone, Copy, Debug)]
@@ -106,25 +107,23 @@ pub fn report_unstable(
reason: Option<Symbol>,
issue: Option<NonZero<u32>>,
suggestion: Option<(Span, String, String, Applicability)>,
is_soft: bool,
span: Span,
soft_handler: impl FnOnce(&'static Lint, Span, String),
) {
let msg = match reason {
Some(r) => format!("use of unstable library feature `{feature}`: {r}"),
None => format!("use of unstable library feature `{feature}`"),
};

if is_soft {
soft_handler(SOFT_UNSTABLE, span, msg)
} else {
let issues = Vec::from_iter(issue);
let mut err = feature_err_issues(sess, &[feature], span, GateIssues::Library(issues), msg);
if let Some((inner_types, msg, sugg, applicability)) = suggestion {
err.span_suggestion(inner_types, msg, sugg, applicability);
}
err.emit();
let features = vec![feature];

let mut err = sess.dcx().create_err(UnstableLibraryFeatureError::new(feature, reason, span));
add_feature_diagnostics_for_issues(
&mut err,
sess,
&features,
GateIssues::Library(Vec::from_iter(issue)),
false,
None,
);
if let Some((inner_types, msg, sugg, applicability)) = suggestion {
err.span_suggestion(inner_types, msg, sugg, applicability);
}
err.emit();
}

fn deprecation_lint(is_in_effect: bool) -> &'static Lint {
@@ -565,26 +564,23 @@ impl<'tcx> TyCtxt<'tcx> {
allow_unstable: AllowUnstable,
unmarked: impl FnOnce(Span, DefId),
) -> bool {
let soft_handler = |lint, span, msg: String| {
self.node_span_lint(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, |lint| {
lint.primary_message(msg);
})
};
let eval_result =
self.eval_stability_allow_unstable(def_id, id, span, method_span, allow_unstable);
let is_allowed = matches!(eval_result, EvalResult::Allow);
match eval_result {
EvalResult::Allow => {}
EvalResult::Deny { feature, reason, issue, suggestion, is_soft } => report_unstable(
self.sess,
feature,
reason,
issue,
suggestion,
is_soft,
span,
soft_handler,
),
EvalResult::Deny { feature, reason, issue, suggestion, is_soft } => {
if is_soft {
self.emit_node_span_lint(
SOFT_UNSTABLE,
id.unwrap_or(hir::CRATE_HIR_ID),
span,
SoftUnstableLibraryFeature::new(feature, reason),
);
} else {
report_unstable(self.sess, feature, reason, issue, suggestion, span);
}
}
EvalResult::Unmarked => unmarked(span, def_id),
}

8 changes: 4 additions & 4 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
@@ -2969,22 +2969,22 @@ impl<'tcx> TyCtxt<'tcx> {
self,
diag: &mut Diag<'_, E>,
hir_id: Option<HirId>,
features: impl IntoIterator<Item = (String, Symbol)>,
featuresets: impl IntoIterator<Item = (String, impl std::fmt::Display)>,
) {
if !self.sess.is_nightly_build() {
return;
}

let span = hir_id.and_then(|id| self.crate_level_attribute_injection_span(id));
for (desc, feature) in features {
for (desc, features) in featuresets {
// FIXME: make this string translatable
let msg =
format!("add `#![feature({feature})]` to the crate attributes to enable{desc}");
format!("add `#![feature({features})]` to the crate attributes to enable{desc}");
if let Some(span) = span {
diag.span_suggestion_verbose(
span,
msg,
format!("#![feature({feature})]\n"),
format!("#![feature({features})]\n"),
Applicability::MaybeIncorrect,
);
} else {
38 changes: 18 additions & 20 deletions compiler/rustc_resolve/src/macros.rs
Original file line number Diff line number Diff line change
@@ -1009,28 +1009,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|feature| self.tcx.features().enabled(feature) || span.allows_unstable(feature);
let allowed_by_implication = implied_by.is_some_and(|feature| is_allowed(feature));
if !is_allowed(feature) && !allowed_by_implication {
let lint_buffer = &mut self.lint_buffer;
let soft_handler = |lint, span, msg: String| {
lint_buffer.buffer_lint(
lint,
if is_soft {
self.lint_buffer.buffer_lint(
SOFT_UNSTABLE,
node_id,
span,
BuiltinLintDiag::UnstableFeature(
// FIXME make this translatable
msg.into(),
),
)
};
stability::report_unstable(
self.tcx.sess,
feature,
reason.to_opt_reason(),
issue,
None,
is_soft,
span,
soft_handler,
);
BuiltinLintDiag::SoftUnstableMacro {
feature,
reason: reason.to_opt_reason(),
},
);
} else {
stability::report_unstable(
self.tcx.sess,
feature,
reason.to_opt_reason(),
issue,
None,
span,
);
}
}
}
}