Skip to content

Commit 9e51884

Browse files
committed
Allow to customize // TODO: comment for deprecated safe autofix
Relevant for the deprecation of `CommandExt::before_exit` in #125970.
1 parent d3a3939 commit 9e51884

File tree

7 files changed

+47
-13
lines changed

7 files changed

+47
-13
lines changed

compiler/rustc_feature/src/builtin_attrs.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -643,8 +643,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
643643
through unstable paths"
644644
),
645645
rustc_attr!(
646-
rustc_deprecated_safe_2024, Normal, template!(Word), WarnFollowing,
647-
EncodeCrossCrate::Yes,
646+
rustc_deprecated_safe_2024, Normal, template!(List: r#"todo = "...""#),
647+
ErrorFollowing, EncodeCrossCrate::Yes,
648648
"rustc_deprecated_safe_2024 is supposed to be used in libstd only",
649649
),
650650

compiler/rustc_mir_build/messages.ftl

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

compiler/rustc_mir_build/src/check_unsafety.rs

+25-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::borrow::Cow;
22
use std::mem;
33
use std::ops::Bound;
44

5+
use rustc_ast::Attribute;
56
use rustc_errors::DiagArgValue;
67
use rustc_hir::def::DefKind;
78
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability};
@@ -91,14 +92,36 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
9192
}
9293

9394
fn emit_deprecated_safe_fn_call(&self, span: Span, kind: &UnsafeOpKind) -> bool {
95+
fn parse_rustc_deprecated_safe_2024_attr(attr: &Attribute) -> Option<Symbol> {
96+
for item in attr.meta_item_list().unwrap_or_default() {
97+
if item.has_name(sym::todo) {
98+
return Some(
99+
item.value_str().expect(
100+
"`#[rustc_deprecated_safe_2024(todo)]` must have a string value",
101+
),
102+
);
103+
}
104+
}
105+
None
106+
}
107+
94108
match kind {
95109
// Allow calls to deprecated-safe unsafe functions if the caller is
96110
// from an edition before 2024.
97111
&UnsafeOpKind::CallToUnsafeFunction(Some(id))
98112
if !span.at_least_rust_2024()
99-
&& self.tcx.has_attr(id, sym::rustc_deprecated_safe_2024) =>
113+
&& let Some(attr) = self.tcx.get_attr(id, sym::rustc_deprecated_safe_2024) =>
100114
{
115+
let suggestion = parse_rustc_deprecated_safe_2024_attr(attr);
116+
101117
let sm = self.tcx.sess.source_map();
118+
let suggestion = suggestion
119+
.and_then(|suggestion| {
120+
sm.indentation_before(span)
121+
.map(|indent| format!("{}// TODO: {}\n", indent, suggestion)) // ignore-tidy-todo
122+
})
123+
.unwrap_or_default();
124+
102125
self.tcx.emit_node_span_lint(
103126
DEPRECATED_SAFE_2024,
104127
self.hir_context,
@@ -107,7 +130,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
107130
span,
108131
function: with_no_trimmed_paths!(self.tcx.def_path_str(id)),
109132
sub: CallToDeprecatedSafeFnRequiresUnsafeSub {
110-
indent: sm.indentation_before(span).unwrap_or_default(),
133+
start_of_line_suggestion: suggestion,
111134
start_of_line: sm.span_extend_to_line(span).shrink_to_lo(),
112135
left: span.shrink_to_lo(),
113136
right: span.shrink_to_hi(),

compiler/rustc_mir_build/src/errors.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,8 @@ pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafe {
3535
#[derive(Subdiagnostic)]
3636
#[multipart_suggestion(mir_build_suggestion, applicability = "machine-applicable")]
3737
pub(crate) struct CallToDeprecatedSafeFnRequiresUnsafeSub {
38-
pub(crate) indent: String,
39-
#[suggestion_part(
40-
code = "{indent}// TODO: Audit that the environment access only happens in single-threaded code.\n" // ignore-tidy-todo
41-
)]
38+
pub(crate) start_of_line_suggestion: String,
39+
#[suggestion_part(code = "{start_of_line_suggestion}")]
4240
pub(crate) start_of_line: Span,
4341
#[suggestion_part(code = "unsafe {{ ")]
4442
pub(crate) left: Span,

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1896,6 +1896,7 @@ symbols! {
18961896
to_string,
18971897
to_string_method,
18981898
to_vec,
1899+
todo,
18991900
todo_macro,
19001901
tool_attributes,
19011902
tool_lints,

library/std/src/env.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,13 @@ impl Error for VarError {
355355
/// }
356356
/// assert_eq!(env::var(key), Ok("VALUE".to_string()));
357357
/// ```
358-
#[rustc_deprecated_safe_2024]
358+
#[cfg_attr(bootstrap, rustc_deprecated_safe_2024)]
359+
#[cfg_attr(
360+
not(bootstrap),
361+
rustc_deprecated_safe_2024(
362+
todo = "Audit that the environment access only happens in single-threaded code."
363+
)
364+
)]
359365
#[stable(feature = "env", since = "1.0.0")]
360366
pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
361367
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) {
419425
/// }
420426
/// assert!(env::var(key).is_err());
421427
/// ```
422-
#[rustc_deprecated_safe_2024]
428+
#[cfg_attr(bootstrap, rustc_deprecated_safe_2024)]
429+
#[cfg_attr(
430+
not(bootstrap),
431+
rustc_deprecated_safe_2024(
432+
todo = "Audit that the environment access only happens in single-threaded code."
433+
)
434+
)]
423435
#[stable(feature = "env", since = "1.0.0")]
424436
pub unsafe fn remove_var<K: AsRef<OsStr>>(key: K) {
425437
let key = key.as_ref();

tests/ui/rust-2024/unsafe-env-suggestion.stderr

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

0 commit comments

Comments
 (0)