From 975152ce30b8c0aa3cb7a3dca0a17c6c20e9db5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lanteri=20Thauvin?= Date: Thu, 28 Jul 2022 00:03:16 +0200 Subject: [PATCH 1/5] Add MVP suggestion for `unsafe_op_in_unsafe_fn` Nemo157 rebase notes: Migrated the changes to the lint into fluent --- compiler/rustc_mir_transform/messages.ftl | 1 + .../rustc_mir_transform/src/check_unsafety.rs | 26 ++++++++++++---- compiler/rustc_mir_transform/src/errors.rs | 19 ++++++++---- ...rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr | 16 ++++++++++ .../unsafe/wrapping-unsafe-block-sugg.fixed | 12 ++++++++ tests/ui/unsafe/wrapping-unsafe-block-sugg.rs | 12 ++++++++ .../unsafe/wrapping-unsafe-block-sugg.stderr | 30 +++++++++++++++++++ 7 files changed, 105 insertions(+), 11 deletions(-) create mode 100644 tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed create mode 100644 tests/ui/unsafe/wrapping-unsafe-block-sugg.rs create mode 100644 tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr diff --git a/compiler/rustc_mir_transform/messages.ftl b/compiler/rustc_mir_transform/messages.ftl index b13429d121d10..300e592a6b463 100644 --- a/compiler/rustc_mir_transform/messages.ftl +++ b/compiler/rustc_mir_transform/messages.ftl @@ -55,6 +55,7 @@ mir_transform_unaligned_packed_ref = reference to packed field is unaligned mir_transform_union_access_label = access to union field mir_transform_union_access_note = the field may not be properly initialized: using uninitialized data will cause undefined behavior mir_transform_unsafe_op_in_unsafe_fn = {$details} is unsafe and requires unsafe block (error E0133) + .suggestion = consider wrapping the function body in an unsafe block mir_transform_unused_unsafe = unnecessary `unsafe` block .label = because it's nested under this `unsafe` block diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index 069514d8a3bf3..fd8e02ebeab79 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -527,6 +527,8 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { } let UnsafetyCheckResult { violations, unused_unsafes, .. } = tcx.unsafety_check_result(def_id); + // Only suggest wrapping the entire function body in an unsafe block once + let mut suggest_unsafe_block = true; for &UnsafetyViolation { source_info, lint_root, kind, details } in violations.iter() { let details = errors::RequiresUnsafeDetail { violation: details, span: source_info.span }; @@ -561,12 +563,24 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { op_in_unsafe_fn_allowed, }); } - UnsafetyViolationKind::UnsafeFn => tcx.emit_spanned_lint( - UNSAFE_OP_IN_UNSAFE_FN, - lint_root, - source_info.span, - errors::UnsafeOpInUnsafeFn { details }, - ), + UnsafetyViolationKind::UnsafeFn => { + tcx.emit_spanned_lint( + UNSAFE_OP_IN_UNSAFE_FN, + lint_root, + source_info.span, + errors::UnsafeOpInUnsafeFn { + details, + suggest_unsafe_block: suggest_unsafe_block.then(|| { + let body = tcx.hir().body_owned_by(def_id); + let body_span = tcx.hir().body(body).value.span; + let start = tcx.sess.source_map().start_point(body_span).shrink_to_hi(); + let end = tcx.sess.source_map().end_point(body_span).shrink_to_lo(); + (start, end) + }), + }, + ); + suggest_unsafe_block = false; + } } } diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 602e40d513104..b546e34f037df 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -1,5 +1,6 @@ use rustc_errors::{ - DecorateLint, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Handler, IntoDiagnostic, + Applicability, DecorateLint, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Handler, + IntoDiagnostic, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::mir::{AssertKind, UnsafetyViolationDetails}; @@ -130,6 +131,7 @@ impl RequiresUnsafeDetail { pub(crate) struct UnsafeOpInUnsafeFn { pub details: RequiresUnsafeDetail, + pub suggest_unsafe_block: Option<(Span, Span)>, } impl<'a> DecorateLint<'a, ()> for UnsafeOpInUnsafeFn { @@ -138,13 +140,20 @@ impl<'a> DecorateLint<'a, ()> for UnsafeOpInUnsafeFn { self, diag: &'b mut DiagnosticBuilder<'a, ()>, ) -> &'b mut DiagnosticBuilder<'a, ()> { - let desc = diag - .handler() - .expect("lint should not yet be emitted") - .eagerly_translate_to_string(self.details.label(), [].into_iter()); + let handler = diag.handler().expect("lint should not yet be emitted"); + let desc = handler.eagerly_translate_to_string(self.details.label(), [].into_iter()); diag.set_arg("details", desc); diag.span_label(self.details.span, self.details.label()); diag.note(self.details.note()); + + if let Some((start, end)) = self.suggest_unsafe_block { + diag.multipart_suggestion_verbose( + crate::fluent_generated::mir_transform_suggestion, + vec![(start, " unsafe {".into()), (end, "}".into())], + Applicability::MaybeIncorrect, + ); + } + diag } diff --git a/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr index 6f005fe895848..2333f710c4050 100644 --- a/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr +++ b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr @@ -10,6 +10,14 @@ note: the lint level is defined here | LL | #![deny(unsafe_op_in_unsafe_fn)] | ^^^^^^^^^^^^^^^^^^^^^^ +help: consider wrapping the function body in an unsafe block + | +LL ~ unsafe fn deny_level() { unsafe { +LL | unsf(); + ... +LL | +LL ~ }} + | error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:15:5 @@ -52,6 +60,14 @@ note: the lint level is defined here LL | #[deny(warnings)] | ^^^^^^^^ = note: `#[deny(unsafe_op_in_unsafe_fn)]` implied by `#[deny(warnings)]` +help: consider wrapping the function body in an unsafe block + | +LL ~ unsafe fn warning_level() { unsafe { +LL | unsf(); + ... +LL | +LL ~ }} + | error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:31:5 diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed b/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed new file mode 100644 index 0000000000000..81b7d68bc4aca --- /dev/null +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed @@ -0,0 +1,12 @@ +// run-rustfix + +#![deny(unsafe_op_in_unsafe_fn)] + +unsafe fn unsf() {} + +pub unsafe fn foo() { unsafe { + unsf(); //~ ERROR call to unsafe function is unsafe + unsf(); //~ ERROR call to unsafe function is unsafe +}} + +fn main() {} diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs b/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs new file mode 100644 index 0000000000000..ef6936d91d187 --- /dev/null +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs @@ -0,0 +1,12 @@ +// run-rustfix + +#![deny(unsafe_op_in_unsafe_fn)] + +unsafe fn unsf() {} + +pub unsafe fn foo() { + unsf(); //~ ERROR call to unsafe function is unsafe + unsf(); //~ ERROR call to unsafe function is unsafe +} + +fn main() {} diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr b/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr new file mode 100644 index 0000000000000..7283ee08bdfa2 --- /dev/null +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr @@ -0,0 +1,30 @@ +error: call to unsafe function is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:8:5 + | +LL | unsf(); + | ^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior +note: the lint level is defined here + --> $DIR/wrapping-unsafe-block-sugg.rs:3:9 + | +LL | #![deny(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ +help: consider wrapping the function body in an unsafe block + | +LL ~ pub unsafe fn foo() { unsafe { +LL | unsf(); +LL | unsf(); +LL ~ }} + | + +error: call to unsafe function is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:9:5 + | +LL | unsf(); + | ^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 2 previous errors + From aca61b2c07f2f7b644ca000385473af9de2d5f77 Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Sat, 27 May 2023 14:37:18 +0200 Subject: [PATCH 2/5] Test that a couple more types of unsafe-ops get a wrapping unsafe block added --- .../unsafe/wrapping-unsafe-block-sugg.fixed | 11 +++++ tests/ui/unsafe/wrapping-unsafe-block-sugg.rs | 11 +++++ .../unsafe/wrapping-unsafe-block-sugg.stderr | 48 ++++++++++++++++++- 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed b/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed index 81b7d68bc4aca..c36aabb7c92fa 100644 --- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed @@ -9,4 +9,15 @@ pub unsafe fn foo() { unsafe { unsf(); //~ ERROR call to unsafe function is unsafe }} +pub unsafe fn bar(x: *const i32) -> i32 { unsafe { + let y = *x; //~ ERROR dereference of raw pointer is unsafe and requires unsafe block + y + *x //~ ERROR dereference of raw pointer is unsafe and requires unsafe block +}} + +static mut BAZ: i32 = 0; +pub unsafe fn baz() -> i32 { unsafe { + let y = BAZ; //~ ERROR use of mutable static is unsafe and requires unsafe block + y + BAZ //~ ERROR use of mutable static is unsafe and requires unsafe block +}} + fn main() {} diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs b/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs index ef6936d91d187..95e22d1bc4d5e 100644 --- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs @@ -9,4 +9,15 @@ pub unsafe fn foo() { unsf(); //~ ERROR call to unsafe function is unsafe } +pub unsafe fn bar(x: *const i32) -> i32 { + let y = *x; //~ ERROR dereference of raw pointer is unsafe and requires unsafe block + y + *x //~ ERROR dereference of raw pointer is unsafe and requires unsafe block +} + +static mut BAZ: i32 = 0; +pub unsafe fn baz() -> i32 { + let y = BAZ; //~ ERROR use of mutable static is unsafe and requires unsafe block + y + BAZ //~ ERROR use of mutable static is unsafe and requires unsafe block +} + fn main() {} diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr b/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr index 7283ee08bdfa2..b05d87069abe4 100644 --- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr @@ -26,5 +26,51 @@ LL | unsf(); | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to 2 previous errors +error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:13:13 + | +LL | let y = *x; + | ^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior +help: consider wrapping the function body in an unsafe block + | +LL ~ pub unsafe fn bar(x: *const i32) -> i32 { unsafe { +LL | let y = *x; +LL | y + *x +LL ~ }} + | + +error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:14:9 + | +LL | y + *x + | ^^ dereference of raw pointer + | + = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior + +error: use of mutable static is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:19:13 + | +LL | let y = BAZ; + | ^^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior +help: consider wrapping the function body in an unsafe block + | +LL ~ pub unsafe fn baz() -> i32 { unsafe { +LL | let y = BAZ; +LL | y + BAZ +LL ~ }} + | + +error: use of mutable static is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:20:9 + | +LL | y + BAZ + | ^^^ use of mutable static + | + = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior + +error: aborting due to 6 previous errors From 62a712a8bbb29a5d2f4e82b74d1ee5aa0490a5a3 Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Sat, 27 May 2023 22:19:09 +0200 Subject: [PATCH 3/5] Hide suggestion to wrap function in unsafe block --- compiler/rustc_mir_transform/src/errors.rs | 2 +- ...rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr | 16 -------------- .../unsafe/wrapping-unsafe-block-sugg.stderr | 21 ------------------- 3 files changed, 1 insertion(+), 38 deletions(-) diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index b546e34f037df..6570da51bcc6f 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -147,7 +147,7 @@ impl<'a> DecorateLint<'a, ()> for UnsafeOpInUnsafeFn { diag.note(self.details.note()); if let Some((start, end)) = self.suggest_unsafe_block { - diag.multipart_suggestion_verbose( + diag.tool_only_multipart_suggestion( crate::fluent_generated::mir_transform_suggestion, vec![(start, " unsafe {".into()), (end, "}".into())], Applicability::MaybeIncorrect, diff --git a/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr index 2333f710c4050..6f005fe895848 100644 --- a/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr +++ b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr @@ -10,14 +10,6 @@ note: the lint level is defined here | LL | #![deny(unsafe_op_in_unsafe_fn)] | ^^^^^^^^^^^^^^^^^^^^^^ -help: consider wrapping the function body in an unsafe block - | -LL ~ unsafe fn deny_level() { unsafe { -LL | unsf(); - ... -LL | -LL ~ }} - | error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:15:5 @@ -60,14 +52,6 @@ note: the lint level is defined here LL | #[deny(warnings)] | ^^^^^^^^ = note: `#[deny(unsafe_op_in_unsafe_fn)]` implied by `#[deny(warnings)]` -help: consider wrapping the function body in an unsafe block - | -LL ~ unsafe fn warning_level() { unsafe { -LL | unsf(); - ... -LL | -LL ~ }} - | error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:31:5 diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr b/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr index b05d87069abe4..b22c5b74b5610 100644 --- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr @@ -10,13 +10,6 @@ note: the lint level is defined here | LL | #![deny(unsafe_op_in_unsafe_fn)] | ^^^^^^^^^^^^^^^^^^^^^^ -help: consider wrapping the function body in an unsafe block - | -LL ~ pub unsafe fn foo() { unsafe { -LL | unsf(); -LL | unsf(); -LL ~ }} - | error: call to unsafe function is unsafe and requires unsafe block (error E0133) --> $DIR/wrapping-unsafe-block-sugg.rs:9:5 @@ -33,13 +26,6 @@ LL | let y = *x; | ^^ dereference of raw pointer | = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior -help: consider wrapping the function body in an unsafe block - | -LL ~ pub unsafe fn bar(x: *const i32) -> i32 { unsafe { -LL | let y = *x; -LL | y + *x -LL ~ }} - | error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) --> $DIR/wrapping-unsafe-block-sugg.rs:14:9 @@ -56,13 +42,6 @@ LL | let y = BAZ; | ^^^ use of mutable static | = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior -help: consider wrapping the function body in an unsafe block - | -LL ~ pub unsafe fn baz() -> i32 { unsafe { -LL | let y = BAZ; -LL | y + BAZ -LL ~ }} - | error: use of mutable static is unsafe and requires unsafe block (error E0133) --> $DIR/wrapping-unsafe-block-sugg.rs:20:9 From 8f3e876e522f9ecc8f855485bb4857163c0f86e4 Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Sat, 27 May 2023 22:20:14 +0200 Subject: [PATCH 4/5] Add note about unsafe functions body not being unsafe --- compiler/rustc_mir_transform/messages.ftl | 1 + .../rustc_mir_transform/src/check_unsafety.rs | 7 ++++- compiler/rustc_mir_transform/src/errors.rs | 10 +++++-- ...rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr | 10 +++++++ .../unsafe/wrapping-unsafe-block-sugg.fixed | 17 +++++++++++- tests/ui/unsafe/wrapping-unsafe-block-sugg.rs | 17 +++++++++++- .../unsafe/wrapping-unsafe-block-sugg.stderr | 27 ++++++++++++++----- 7 files changed, 78 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_mir_transform/messages.ftl b/compiler/rustc_mir_transform/messages.ftl index 300e592a6b463..2598eb2ed0968 100644 --- a/compiler/rustc_mir_transform/messages.ftl +++ b/compiler/rustc_mir_transform/messages.ftl @@ -56,6 +56,7 @@ mir_transform_union_access_label = access to union field mir_transform_union_access_note = the field may not be properly initialized: using uninitialized data will cause undefined behavior mir_transform_unsafe_op_in_unsafe_fn = {$details} is unsafe and requires unsafe block (error E0133) .suggestion = consider wrapping the function body in an unsafe block + .note = an unsafe function restricts its caller, but its body is safe by default mir_transform_unused_unsafe = unnecessary `unsafe` block .label = because it's nested under this `unsafe` block diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index fd8e02ebeab79..41e31df77cb92 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -571,11 +571,16 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { errors::UnsafeOpInUnsafeFn { details, suggest_unsafe_block: suggest_unsafe_block.then(|| { + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let fn_sig = tcx + .hir() + .fn_sig_by_hir_id(hir_id) + .expect("this violation only occurs in fn"); let body = tcx.hir().body_owned_by(def_id); let body_span = tcx.hir().body(body).value.span; let start = tcx.sess.source_map().start_point(body_span).shrink_to_hi(); let end = tcx.sess.source_map().end_point(body_span).shrink_to_lo(); - (start, end) + (start, end, fn_sig.span) }), }, ); diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 6570da51bcc6f..05a27f853b875 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -131,7 +131,12 @@ impl RequiresUnsafeDetail { pub(crate) struct UnsafeOpInUnsafeFn { pub details: RequiresUnsafeDetail, - pub suggest_unsafe_block: Option<(Span, Span)>, + + /// These spans point to: + /// 1. the start of the function body + /// 2. the end of the function body + /// 3. the function signature + pub suggest_unsafe_block: Option<(Span, Span, Span)>, } impl<'a> DecorateLint<'a, ()> for UnsafeOpInUnsafeFn { @@ -146,7 +151,8 @@ impl<'a> DecorateLint<'a, ()> for UnsafeOpInUnsafeFn { diag.span_label(self.details.span, self.details.label()); diag.note(self.details.note()); - if let Some((start, end)) = self.suggest_unsafe_block { + if let Some((start, end, fn_sig)) = self.suggest_unsafe_block { + diag.span_note(fn_sig, crate::fluent_generated::mir_transform_note); diag.tool_only_multipart_suggestion( crate::fluent_generated::mir_transform_suggestion, vec![(start, " unsafe {".into()), (end, "}".into())], diff --git a/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr index 6f005fe895848..0c0826c1cfb39 100644 --- a/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr +++ b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr @@ -5,6 +5,11 @@ LL | unsf(); | ^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:11:1 + | +LL | unsafe fn deny_level() { + | ^^^^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:4:9 | @@ -46,6 +51,11 @@ LL | unsf(); | ^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:27:1 + | +LL | unsafe fn warning_level() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:26:8 | diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed b/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed index c36aabb7c92fa..8fdc21ee1091b 100644 --- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed @@ -1,23 +1,38 @@ // run-rustfix -#![deny(unsafe_op_in_unsafe_fn)] +#![deny(unsafe_op_in_unsafe_fn)] //~ NOTE unsafe fn unsf() {} pub unsafe fn foo() { unsafe { + //~^ NOTE an unsafe function restricts its caller, but its body is safe by default unsf(); //~ ERROR call to unsafe function is unsafe + //~^ NOTE + //~| NOTE unsf(); //~ ERROR call to unsafe function is unsafe + //~^ NOTE + //~| NOTE }} pub unsafe fn bar(x: *const i32) -> i32 { unsafe { + //~^ NOTE an unsafe function restricts its caller, but its body is safe by default let y = *x; //~ ERROR dereference of raw pointer is unsafe and requires unsafe block + //~^ NOTE + //~| NOTE y + *x //~ ERROR dereference of raw pointer is unsafe and requires unsafe block + //~^ NOTE + //~| NOTE }} static mut BAZ: i32 = 0; pub unsafe fn baz() -> i32 { unsafe { + //~^ NOTE an unsafe function restricts its caller, but its body is safe by default let y = BAZ; //~ ERROR use of mutable static is unsafe and requires unsafe block + //~^ NOTE + //~| NOTE y + BAZ //~ ERROR use of mutable static is unsafe and requires unsafe block + //~^ NOTE + //~| NOTE }} fn main() {} diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs b/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs index 95e22d1bc4d5e..0c6feee4ff2c0 100644 --- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs @@ -1,23 +1,38 @@ // run-rustfix -#![deny(unsafe_op_in_unsafe_fn)] +#![deny(unsafe_op_in_unsafe_fn)] //~ NOTE unsafe fn unsf() {} pub unsafe fn foo() { + //~^ NOTE an unsafe function restricts its caller, but its body is safe by default unsf(); //~ ERROR call to unsafe function is unsafe + //~^ NOTE + //~| NOTE unsf(); //~ ERROR call to unsafe function is unsafe + //~^ NOTE + //~| NOTE } pub unsafe fn bar(x: *const i32) -> i32 { + //~^ NOTE an unsafe function restricts its caller, but its body is safe by default let y = *x; //~ ERROR dereference of raw pointer is unsafe and requires unsafe block + //~^ NOTE + //~| NOTE y + *x //~ ERROR dereference of raw pointer is unsafe and requires unsafe block + //~^ NOTE + //~| NOTE } static mut BAZ: i32 = 0; pub unsafe fn baz() -> i32 { + //~^ NOTE an unsafe function restricts its caller, but its body is safe by default let y = BAZ; //~ ERROR use of mutable static is unsafe and requires unsafe block + //~^ NOTE + //~| NOTE y + BAZ //~ ERROR use of mutable static is unsafe and requires unsafe block + //~^ NOTE + //~| NOTE } fn main() {} diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr b/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr index b22c5b74b5610..76f86b09d68af 100644 --- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr @@ -1,10 +1,15 @@ error: call to unsafe function is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:8:5 + --> $DIR/wrapping-unsafe-block-sugg.rs:9:5 | LL | unsf(); | ^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/wrapping-unsafe-block-sugg.rs:7:1 + | +LL | pub unsafe fn foo() { + | ^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here --> $DIR/wrapping-unsafe-block-sugg.rs:3:9 | @@ -12,7 +17,7 @@ LL | #![deny(unsafe_op_in_unsafe_fn)] | ^^^^^^^^^^^^^^^^^^^^^^ error: call to unsafe function is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:9:5 + --> $DIR/wrapping-unsafe-block-sugg.rs:12:5 | LL | unsf(); | ^^^^^^ call to unsafe function @@ -20,15 +25,20 @@ LL | unsf(); = note: consult the function's documentation for information on how to avoid undefined behavior error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:13:13 + --> $DIR/wrapping-unsafe-block-sugg.rs:19:13 | LL | let y = *x; | ^^ dereference of raw pointer | = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/wrapping-unsafe-block-sugg.rs:17:1 + | +LL | pub unsafe fn bar(x: *const i32) -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:14:9 + --> $DIR/wrapping-unsafe-block-sugg.rs:22:9 | LL | y + *x | ^^ dereference of raw pointer @@ -36,15 +46,20 @@ LL | y + *x = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior error: use of mutable static is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:19:13 + --> $DIR/wrapping-unsafe-block-sugg.rs:30:13 | LL | let y = BAZ; | ^^^ use of mutable static | = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/wrapping-unsafe-block-sugg.rs:28:1 + | +LL | pub unsafe fn baz() -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of mutable static is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:20:9 + --> $DIR/wrapping-unsafe-block-sugg.rs:33:9 | LL | y + BAZ | ^^^ use of mutable static From 802c1d5979683c8bf991122643ee2cdbdb51eec4 Mon Sep 17 00:00:00 2001 From: Wim Looman Date: Sun, 11 Jun 2023 11:59:15 +0200 Subject: [PATCH 5/5] Add test cases for suggestions with unsafe operations contained inside macros --- .../unsafe/auxiliary/external_unsafe_macro.rs | 4 ++ .../unsafe/wrapping-unsafe-block-sugg.fixed | 28 ++++++++++ tests/ui/unsafe/wrapping-unsafe-block-sugg.rs | 28 ++++++++++ .../unsafe/wrapping-unsafe-block-sugg.stderr | 51 +++++++++++++++---- 4 files changed, 100 insertions(+), 11 deletions(-) create mode 100644 tests/ui/unsafe/auxiliary/external_unsafe_macro.rs diff --git a/tests/ui/unsafe/auxiliary/external_unsafe_macro.rs b/tests/ui/unsafe/auxiliary/external_unsafe_macro.rs new file mode 100644 index 0000000000000..b3837338b331e --- /dev/null +++ b/tests/ui/unsafe/auxiliary/external_unsafe_macro.rs @@ -0,0 +1,4 @@ +pub unsafe fn unsf() {} + +#[macro_export] +macro_rules! unsafe_macro { () => ($crate::unsf()) } diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed b/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed index 8fdc21ee1091b..db1c102210e3b 100644 --- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed @@ -1,7 +1,10 @@ // run-rustfix +// aux-build:external_unsafe_macro.rs #![deny(unsafe_op_in_unsafe_fn)] //~ NOTE +extern crate external_unsafe_macro; + unsafe fn unsf() {} pub unsafe fn foo() { unsafe { @@ -35,4 +38,29 @@ pub unsafe fn baz() -> i32 { unsafe { //~| NOTE }} +macro_rules! unsafe_macro { () => (unsf()) } +//~^ ERROR call to unsafe function is unsafe +//~| NOTE +//~| NOTE +//~| ERROR call to unsafe function is unsafe +//~| NOTE +//~| NOTE + +pub unsafe fn unsafe_in_macro() { unsafe { + //~^ NOTE an unsafe function restricts its caller, but its body is safe by default + unsafe_macro!(); + //~^ NOTE + //~| NOTE + unsafe_macro!(); + //~^ NOTE + //~| NOTE +}} + +pub unsafe fn unsafe_in_external_macro() { + // FIXME: https://github.com/rust-lang/rust/issues/112504 + // FIXME: ~^ NOTE an unsafe function restricts its caller, but its body is safe by default + external_unsafe_macro::unsafe_macro!(); + external_unsafe_macro::unsafe_macro!(); +} + fn main() {} diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs b/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs index 0c6feee4ff2c0..9c6be45896e25 100644 --- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs @@ -1,7 +1,10 @@ // run-rustfix +// aux-build:external_unsafe_macro.rs #![deny(unsafe_op_in_unsafe_fn)] //~ NOTE +extern crate external_unsafe_macro; + unsafe fn unsf() {} pub unsafe fn foo() { @@ -35,4 +38,29 @@ pub unsafe fn baz() -> i32 { //~| NOTE } +macro_rules! unsafe_macro { () => (unsf()) } +//~^ ERROR call to unsafe function is unsafe +//~| NOTE +//~| NOTE +//~| ERROR call to unsafe function is unsafe +//~| NOTE +//~| NOTE + +pub unsafe fn unsafe_in_macro() { + //~^ NOTE an unsafe function restricts its caller, but its body is safe by default + unsafe_macro!(); + //~^ NOTE + //~| NOTE + unsafe_macro!(); + //~^ NOTE + //~| NOTE +} + +pub unsafe fn unsafe_in_external_macro() { + // FIXME: https://github.com/rust-lang/rust/issues/112504 + // FIXME: ~^ NOTE an unsafe function restricts its caller, but its body is safe by default + external_unsafe_macro::unsafe_macro!(); + external_unsafe_macro::unsafe_macro!(); +} + fn main() {} diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr b/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr index 76f86b09d68af..43f619c27d274 100644 --- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr @@ -1,23 +1,23 @@ error: call to unsafe function is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:9:5 + --> $DIR/wrapping-unsafe-block-sugg.rs:12:5 | LL | unsf(); | ^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior note: an unsafe function restricts its caller, but its body is safe by default - --> $DIR/wrapping-unsafe-block-sugg.rs:7:1 + --> $DIR/wrapping-unsafe-block-sugg.rs:10:1 | LL | pub unsafe fn foo() { | ^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here - --> $DIR/wrapping-unsafe-block-sugg.rs:3:9 + --> $DIR/wrapping-unsafe-block-sugg.rs:4:9 | LL | #![deny(unsafe_op_in_unsafe_fn)] | ^^^^^^^^^^^^^^^^^^^^^^ error: call to unsafe function is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:12:5 + --> $DIR/wrapping-unsafe-block-sugg.rs:15:5 | LL | unsf(); | ^^^^^^ call to unsafe function @@ -25,20 +25,20 @@ LL | unsf(); = note: consult the function's documentation for information on how to avoid undefined behavior error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:19:13 + --> $DIR/wrapping-unsafe-block-sugg.rs:22:13 | LL | let y = *x; | ^^ dereference of raw pointer | = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior note: an unsafe function restricts its caller, but its body is safe by default - --> $DIR/wrapping-unsafe-block-sugg.rs:17:1 + --> $DIR/wrapping-unsafe-block-sugg.rs:20:1 | LL | pub unsafe fn bar(x: *const i32) -> i32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: dereference of raw pointer is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:22:9 + --> $DIR/wrapping-unsafe-block-sugg.rs:25:9 | LL | y + *x | ^^ dereference of raw pointer @@ -46,25 +46,54 @@ LL | y + *x = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior error: use of mutable static is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:30:13 + --> $DIR/wrapping-unsafe-block-sugg.rs:33:13 | LL | let y = BAZ; | ^^^ use of mutable static | = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior note: an unsafe function restricts its caller, but its body is safe by default - --> $DIR/wrapping-unsafe-block-sugg.rs:28:1 + --> $DIR/wrapping-unsafe-block-sugg.rs:31:1 | LL | pub unsafe fn baz() -> i32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of mutable static is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:33:9 + --> $DIR/wrapping-unsafe-block-sugg.rs:36:9 | LL | y + BAZ | ^^^ use of mutable static | = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior -error: aborting due to 6 previous errors +error: call to unsafe function is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:41:36 + | +LL | macro_rules! unsafe_macro { () => (unsf()) } + | ^^^^^^ call to unsafe function +... +LL | unsafe_macro!(); + | --------------- in this macro invocation + | + = note: consult the function's documentation for information on how to avoid undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/wrapping-unsafe-block-sugg.rs:49:1 + | +LL | pub unsafe fn unsafe_in_macro() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the macro `unsafe_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: call to unsafe function is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:41:36 + | +LL | macro_rules! unsafe_macro { () => (unsf()) } + | ^^^^^^ call to unsafe function +... +LL | unsafe_macro!(); + | --------------- in this macro invocation + | + = note: consult the function's documentation for information on how to avoid undefined behavior + = note: this error originates in the macro `unsafe_macro` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 8 previous errors