Allow to customize // TODO: comment for deprecated safe autofix

Relevant for the deprecation of `CommandExt::before_exit` in #125970.
This commit is contained in:
Tobias Bucher 2024-07-17 13:45:31 +02:00
parent 591ecb88df
commit 399ef23d2b
7 changed files with 42 additions and 13 deletions

View File

@ -643,8 +643,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
through unstable paths" through unstable paths"
), ),
rustc_attr!( rustc_attr!(
rustc_deprecated_safe_2024, Normal, template!(Word), WarnFollowing, rustc_deprecated_safe_2024, Normal, template!(List: r#"todo = "...""#),
EncodeCrossCrate::Yes, ErrorFollowing, EncodeCrossCrate::Yes,
"rustc_deprecated_safe_2024 is supposed to be used in libstd only", "rustc_deprecated_safe_2024 is supposed to be used in libstd only",
), ),

View File

@ -30,7 +30,7 @@ mir_build_call_to_deprecated_safe_fn_requires_unsafe =
call to deprecated safe function `{$function}` is unsafe and requires unsafe block call to deprecated safe function `{$function}` is unsafe and requires unsafe block
.note = consult the function's documentation for information on how to avoid undefined behavior .note = consult the function's documentation for information on how to avoid undefined behavior
.label = call to unsafe function .label = call to unsafe function
.suggestion = you can wrap the call in an `unsafe` block if you can guarantee the code is only ever called from single-threaded code .suggestion = you can wrap the call in an `unsafe` block if you can guarantee its unsafe preconditions
mir_build_call_to_fn_with_requires_unsafe = mir_build_call_to_fn_with_requires_unsafe =
call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block

View File

@ -96,9 +96,27 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
// from an edition before 2024. // from an edition before 2024.
&UnsafeOpKind::CallToUnsafeFunction(Some(id)) &UnsafeOpKind::CallToUnsafeFunction(Some(id))
if !span.at_least_rust_2024() if !span.at_least_rust_2024()
&& self.tcx.has_attr(id, sym::rustc_deprecated_safe_2024) => && let Some(attr) = self.tcx.get_attr(id, sym::rustc_deprecated_safe_2024) =>
{ {
let suggestion = attr
.meta_item_list()
.unwrap_or_default()
.into_iter()
.find(|item| item.has_name(sym::todo))
.map(|item| {
item.value_str().expect(
"`#[rustc_deprecated_safe_2024(todo)]` must have a string value",
)
});
let sm = self.tcx.sess.source_map(); let sm = self.tcx.sess.source_map();
let suggestion = suggestion
.and_then(|suggestion| {
sm.indentation_before(span)
.map(|indent| format!("{}// TODO: {}\n", indent, suggestion)) // ignore-tidy-todo
})
.unwrap_or_default();
self.tcx.emit_node_span_lint( self.tcx.emit_node_span_lint(
DEPRECATED_SAFE_2024, DEPRECATED_SAFE_2024,
self.hir_context, self.hir_context,
@ -107,7 +125,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
span, span,
function: with_no_trimmed_paths!(self.tcx.def_path_str(id)), function: with_no_trimmed_paths!(self.tcx.def_path_str(id)),
sub: CallToDeprecatedSafeFnRequiresUnsafeSub { sub: CallToDeprecatedSafeFnRequiresUnsafeSub {
indent: sm.indentation_before(span).unwrap_or_default(), start_of_line_suggestion: suggestion,
start_of_line: sm.span_extend_to_line(span).shrink_to_lo(), start_of_line: sm.span_extend_to_line(span).shrink_to_lo(),
left: span.shrink_to_lo(), left: span.shrink_to_lo(),
right: span.shrink_to_hi(), right: span.shrink_to_hi(),

View File

@ -35,10 +35,8 @@ pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafe {
#[derive(Subdiagnostic)] #[derive(Subdiagnostic)]
#[multipart_suggestion(mir_build_suggestion, applicability = "machine-applicable")] #[multipart_suggestion(mir_build_suggestion, applicability = "machine-applicable")]
pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafeSub { pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafeSub {
pub(crate) indent: String, pub(crate) start_of_line_suggestion: String,
#[suggestion_part( #[suggestion_part(code = "{start_of_line_suggestion}")]
code = "{indent}// TODO: Audit that the environment access only happens in single-threaded code.\n" // ignore-tidy-todo
)]
pub(crate) start_of_line: Span, pub(crate) start_of_line: Span,
#[suggestion_part(code = "unsafe {{ ")] #[suggestion_part(code = "unsafe {{ ")]
pub(crate) left: Span, pub(crate) left: Span,

View File

@ -1897,6 +1897,7 @@ symbols! {
to_string, to_string,
to_string_method, to_string_method,
to_vec, to_vec,
todo,
todo_macro, todo_macro,
tool_attributes, tool_attributes,
tool_lints, tool_lints,

View File

@ -355,7 +355,13 @@ impl Error for VarError {
/// } /// }
/// assert_eq!(env::var(key), Ok("VALUE".to_string())); /// assert_eq!(env::var(key), Ok("VALUE".to_string()));
/// ``` /// ```
#[rustc_deprecated_safe_2024] #[cfg_attr(bootstrap, rustc_deprecated_safe_2024)]
#[cfg_attr(
not(bootstrap),
rustc_deprecated_safe_2024(
todo = "Audit that the environment access only happens in single-threaded code."
)
)]
#[stable(feature = "env", since = "1.0.0")] #[stable(feature = "env", since = "1.0.0")]
pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) { pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
let (key, value) = (key.as_ref(), value.as_ref()); let (key, value) = (key.as_ref(), value.as_ref());
@ -419,7 +425,13 @@ pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
/// } /// }
/// assert!(env::var(key).is_err()); /// assert!(env::var(key).is_err());
/// ``` /// ```
#[rustc_deprecated_safe_2024] #[cfg_attr(bootstrap, rustc_deprecated_safe_2024)]
#[cfg_attr(
not(bootstrap),
rustc_deprecated_safe_2024(
todo = "Audit that the environment access only happens in single-threaded code."
)
)]
#[stable(feature = "env", since = "1.0.0")] #[stable(feature = "env", since = "1.0.0")]
pub unsafe fn remove_var<K: AsRef<OsStr>>(key: K) { pub unsafe fn remove_var<K: AsRef<OsStr>>(key: K) {
let key = key.as_ref(); let key = key.as_ref();

View File

@ -11,7 +11,7 @@ note: the lint level is defined here
| |
LL | #![deny(deprecated_safe_2024)] LL | #![deny(deprecated_safe_2024)]
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^
help: you can wrap the call in an `unsafe` block if you can guarantee the code is only ever called from single-threaded code help: you can wrap the call in an `unsafe` block if you can guarantee its unsafe preconditions
| |
LL + // TODO: Audit that the environment access only happens in single-threaded code. LL + // TODO: Audit that the environment access only happens in single-threaded code.
LL ~ unsafe { env::set_var("FOO", "BAR") }; LL ~ unsafe { env::set_var("FOO", "BAR") };
@ -25,7 +25,7 @@ LL | env::remove_var("FOO");
| |
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
= note: for more information, see issue #27970 <https://github.com/rust-lang/rust/issues/27970> = note: for more information, see issue #27970 <https://github.com/rust-lang/rust/issues/27970>
help: you can wrap the call in an `unsafe` block if you can guarantee the code is only ever called from single-threaded code help: you can wrap the call in an `unsafe` block if you can guarantee its unsafe preconditions
| |
LL + // TODO: Audit that the environment access only happens in single-threaded code. LL + // TODO: Audit that the environment access only happens in single-threaded code.
LL ~ unsafe { env::remove_var("FOO") }; LL ~ unsafe { env::remove_var("FOO") };