about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTobias Bucher <tobiasbucher5991@gmail.com>2024-07-17 13:45:31 +0200
committerTobias Bucher <tobiasbucher5991@gmail.com>2024-08-13 11:32:24 +0200
commit399ef23d2bf2b1619d360a87de9b83edf9d99762 (patch)
tree071223c58c3c1bbf57696e600671b7b60c3154e4
parent591ecb88dffdb0f233e2fae74fd3d7c81d65ff0c (diff)
downloadrust-399ef23d2bf2b1619d360a87de9b83edf9d99762.tar.gz
rust-399ef23d2bf2b1619d360a87de9b83edf9d99762.zip
Allow to customize `// TODO:` comment for deprecated safe autofix
Relevant for the deprecation of `CommandExt::before_exit` in #125970.
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs4
-rw-r--r--compiler/rustc_mir_build/messages.ftl2
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs22
-rw-r--r--compiler/rustc_mir_build/src/errors.rs6
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--library/std/src/env.rs16
-rw-r--r--tests/ui/rust-2024/unsafe-env-suggestion.stderr4
7 files changed, 42 insertions, 13 deletions
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 72ea55d5999..1b4c18e96fc 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -643,8 +643,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         through unstable paths"
     ),
     rustc_attr!(
-        rustc_deprecated_safe_2024, Normal, template!(Word), WarnFollowing,
-        EncodeCrossCrate::Yes,
+        rustc_deprecated_safe_2024, Normal, template!(List: r#"todo = "...""#),
+        ErrorFollowing, EncodeCrossCrate::Yes,
         "rustc_deprecated_safe_2024 is supposed to be used in libstd only",
     ),
 
diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl
index dda4debecec..91c4de79636 100644
--- a/compiler/rustc_mir_build/messages.ftl
+++ b/compiler/rustc_mir_build/messages.ftl
@@ -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
     .note = consult the function's documentation for information on how to avoid undefined behavior
     .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 =
     call to function `{$function}` with `#[target_feature]` is unsafe and requires unsafe block
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 54a4204da71..f856555a95c 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -96,9 +96,27 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
             // from an edition before 2024.
             &UnsafeOpKind::CallToUnsafeFunction(Some(id))
                 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 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(
                     DEPRECATED_SAFE_2024,
                     self.hir_context,
@@ -107,7 +125,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
                         span,
                         function: with_no_trimmed_paths!(self.tcx.def_path_str(id)),
                         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(),
                             left: span.shrink_to_lo(),
                             right: span.shrink_to_hi(),
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index 42eca71ca3f..8c45f949e43 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -35,10 +35,8 @@ pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafe {
 #[derive(Subdiagnostic)]
 #[multipart_suggestion(mir_build_suggestion, applicability = "machine-applicable")]
 pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafeSub {
-    pub(crate) indent: String,
-    #[suggestion_part(
-        code = "{indent}// TODO: Audit that the environment access only happens in single-threaded code.\n" // ignore-tidy-todo
-    )]
+    pub(crate) start_of_line_suggestion: String,
+    #[suggestion_part(code = "{start_of_line_suggestion}")]
     pub(crate) start_of_line: Span,
     #[suggestion_part(code = "unsafe {{ ")]
     pub(crate) left: Span,
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 9cb729ec485..95810a9a837 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1897,6 +1897,7 @@ symbols! {
         to_string,
         to_string_method,
         to_vec,
+        todo,
         todo_macro,
         tool_attributes,
         tool_lints,
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index 50ae83090c7..631d86dbe6e 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -355,7 +355,13 @@ impl Error for VarError {
 /// }
 /// 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")]
 pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
     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());
 /// ```
-#[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")]
 pub unsafe fn remove_var<K: AsRef<OsStr>>(key: K) {
     let key = key.as_ref();
diff --git a/tests/ui/rust-2024/unsafe-env-suggestion.stderr b/tests/ui/rust-2024/unsafe-env-suggestion.stderr
index 3aa10a3bed6..5c90c08e2dd 100644
--- a/tests/ui/rust-2024/unsafe-env-suggestion.stderr
+++ b/tests/ui/rust-2024/unsafe-env-suggestion.stderr
@@ -11,7 +11,7 @@ note: the lint level is defined here
    |
 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 ~     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!
    = 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 ~     unsafe { env::remove_var("FOO") };