Skip to content

Commit bf612e9

Browse files
committed
Allow to customize // TODO: comment for deprecated safe autofix
Relevant for the deprecation of `CommandExt::before_exit` in rust-lang#125970.
1 parent cb12b52 commit bf612e9

File tree

7 files changed

+47
-12
lines changed

7 files changed

+47
-12
lines changed

compiler/rustc_feature/src/builtin_attrs.rs

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

compiler/rustc_mir_build/messages.ftl

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

compiler/rustc_mir_build/src/check_unsafety.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::build::ExprCategory;
22
use crate::errors::*;
33

4+
use rustc_ast::Attribute;
45
use rustc_errors::DiagArgValue;
56
use rustc_hir::def::DefKind;
67
use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability};
@@ -90,14 +91,37 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
9091
}
9192

9293
fn emit_deprecated_safe_fn_call(&self, span: Span, kind: &UnsafeOpKind) -> bool {
94+
fn parse_rustc_deprecated_safe_2024_attr(attr: &Attribute) -> Option<Symbol> {
95+
for item in attr.meta_item_list().unwrap_or_default() {
96+
if item.has_name(sym::todo) {
97+
return Some(
98+
item.value_str().expect(
99+
"`#[rustc_deprecated_safe_2024(todo)]` must have a string value",
100+
),
101+
);
102+
}
103+
}
104+
None
105+
}
106+
93107
match kind {
94108
// Allow calls to deprecated-safe unsafe functions if the caller is
95109
// from an edition before 2024.
96110
&UnsafeOpKind::CallToUnsafeFunction(Some(id))
97111
if !span.at_least_rust_2024()
98112
&& self.tcx.has_attr(id, sym::rustc_deprecated_safe_2024) =>
99113
{
114+
let attr = self.tcx.get_attr(id, sym::rustc_deprecated_safe_2024).unwrap();
115+
let suggestion = parse_rustc_deprecated_safe_2024_attr(attr);
116+
100117
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+
101125
self.tcx.emit_node_span_lint(
102126
DEPRECATED_SAFE,
103127
self.hir_context,
@@ -106,7 +130,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
106130
span,
107131
function: with_no_trimmed_paths!(self.tcx.def_path_str(id)),
108132
sub: CallToDeprecatedSafeFnRequiresUnsafeSub {
109-
indent: sm.indentation_before(span).unwrap_or_default(),
133+
start_of_line_suggestion: suggestion,
110134
start_of_line: sm.span_extend_to_line(span).shrink_to_lo(),
111135
left: span.shrink_to_lo(),
112136
right: span.shrink_to_hi(),

compiler/rustc_mir_build/src/errors.rs

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

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1888,6 +1888,7 @@ symbols! {
18881888
to_string,
18891889
to_string_method,
18901890
to_vec,
1891+
todo,
18911892
todo_macro,
18921893
tool_attributes,
18931894
tool_lints,

library/std/src/env.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,13 @@ impl Error for VarError {
357357
/// }
358358
/// assert_eq!(env::var(key), Ok("VALUE".to_string()));
359359
/// ```
360-
#[rustc_deprecated_safe_2024]
360+
#[cfg_attr(bootstrap, rustc_deprecated_safe_2024)]
361+
#[cfg_attr(
362+
not(bootstrap),
363+
rustc_deprecated_safe_2024(
364+
todo = "Audit that the environment access only happens in single-threaded code."
365+
)
366+
)]
361367
#[stable(feature = "env", since = "1.0.0")]
362368
pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
363369
let (key, value) = (key.as_ref(), value.as_ref());
@@ -421,7 +427,13 @@ pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) {
421427
/// }
422428
/// assert!(env::var(key).is_err());
423429
/// ```
424-
#[rustc_deprecated_safe_2024]
430+
#[cfg_attr(bootstrap, rustc_deprecated_safe_2024)]
431+
#[cfg_attr(
432+
not(bootstrap),
433+
rustc_deprecated_safe_2024(
434+
todo = "Audit that the environment access only happens in single-threaded code."
435+
)
436+
)]
425437
#[stable(feature = "env", since = "1.0.0")]
426438
pub unsafe fn remove_var<K: AsRef<OsStr>>(key: K) {
427439
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)]
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)