mirror of https://github.com/rust-lang/rust.git
Rollup merge of #127857 - tbu-:pr_deprecated_safe_todo, r=petrochenkov
Allow to customize `// TODO:` comment for deprecated safe autofix Relevant for the deprecation of `CommandExt::before_exit` in #125970. Tracking: - #124866
This commit is contained in:
commit
f68a28d95c
|
@ -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#"audit_that = "...""#),
|
||||||
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",
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
|
@ -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 {$guarantee}
|
||||||
|
|
||||||
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
|
||||||
|
|
|
@ -96,9 +96,32 @@ 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::audit_that))
|
||||||
|
.map(|item| {
|
||||||
|
item.value_str().expect(
|
||||||
|
"`#[rustc_deprecated_safe_2024(audit_that)]` must have a string value",
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
let sm = self.tcx.sess.source_map();
|
let sm = self.tcx.sess.source_map();
|
||||||
|
let guarantee = suggestion
|
||||||
|
.as_ref()
|
||||||
|
.map(|suggestion| format!("that {}", suggestion))
|
||||||
|
.unwrap_or_else(|| String::from("its unsafe preconditions"));
|
||||||
|
let suggestion = suggestion
|
||||||
|
.and_then(|suggestion| {
|
||||||
|
sm.indentation_before(span).map(|indent| {
|
||||||
|
format!("{}// TODO: Audit that {}.\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,
|
||||||
|
@ -106,8 +129,9 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
|
||||||
CallToDeprecatedSafeFnRequiresUnsafe {
|
CallToDeprecatedSafeFnRequiresUnsafe {
|
||||||
span,
|
span,
|
||||||
function: with_no_trimmed_paths!(self.tcx.def_path_str(id)),
|
function: with_no_trimmed_paths!(self.tcx.def_path_str(id)),
|
||||||
|
guarantee,
|
||||||
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(),
|
||||||
|
|
|
@ -28,6 +28,7 @@ pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafe {
|
||||||
#[label]
|
#[label]
|
||||||
pub(crate) span: Span,
|
pub(crate) span: Span,
|
||||||
pub(crate) function: String,
|
pub(crate) function: String,
|
||||||
|
pub(crate) guarantee: String,
|
||||||
#[subdiagnostic]
|
#[subdiagnostic]
|
||||||
pub(crate) sub: CallToDeprecatedSafeFnRequiresUnsafeSub,
|
pub(crate) sub: CallToDeprecatedSafeFnRequiresUnsafeSub,
|
||||||
}
|
}
|
||||||
|
@ -35,10 +36,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,
|
||||||
|
|
|
@ -472,6 +472,7 @@ symbols! {
|
||||||
attr,
|
attr,
|
||||||
attr_literals,
|
attr_literals,
|
||||||
attributes,
|
attributes,
|
||||||
|
audit_that,
|
||||||
augmented_assignments,
|
augmented_assignments,
|
||||||
auto_traits,
|
auto_traits,
|
||||||
automatically_derived,
|
automatically_derived,
|
||||||
|
|
|
@ -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(
|
||||||
|
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(
|
||||||
|
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();
|
||||||
|
|
|
@ -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 that the environment access only happens in single-threaded code
|
||||||
|
|
|
|
||||||
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 that the environment access only happens in single-threaded code
|
||||||
|
|
|
|
||||||
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") };
|
||||||
|
|
Loading…
Reference in New Issue