diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index d88f165b9e538..c4e44a6a4e388 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3566,6 +3566,15 @@ impl<'hir> OwnerNode<'hir> { } } + pub fn fn_sig(self) -> Option<&'hir FnSig<'hir>> { + match self { + OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) + | OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. }) + | OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig), + _ => None, + } + } + pub fn fn_decl(self) -> Option<&'hir FnDecl<'hir>> { match self { OwnerNode::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index d03d92c3a4b83..8feefb4c03ccc 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -66,8 +66,9 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp Use { source } => visitor.visit_expr(&visitor.thir()[source]), NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]), PointerCoercion { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]), - Let { expr, .. } => { + Let { expr, ref pat } => { visitor.visit_expr(&visitor.thir()[expr]); + visitor.visit_pat(pat); } Loop { body } => visitor.visit_expr(&visitor.thir()[body]), Match { scrutinee, ref arms, .. } => { diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 563851f712c66..54fc8f77f9367 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -320,6 +320,7 @@ mir_build_unreachable_pattern = unreachable pattern .label = unreachable pattern .catchall_label = matches any value +mir_build_unsafe_fn_safe_body = an unsafe function restricts its caller, but its body is safe by default mir_build_unsafe_not_inherited = items do not inherit unsafety from separate enclosing items mir_build_unsafe_op_in_unsafe_fn_borrow_of_layout_constrained_field_requires_unsafe = @@ -386,3 +387,5 @@ mir_build_unused_unsafe = unnecessary `unsafe` block mir_build_unused_unsafe_enclosing_block_label = because it's nested under this `unsafe` block mir_build_variant_defined_here = not covered + +mir_build_wrap_suggestion = consider wrapping the function body in an unsafe block diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 45be501537130..3d895c131a85c 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -35,6 +35,10 @@ struct UnsafetyVisitor<'a, 'tcx> { param_env: ParamEnv<'tcx>, inside_adt: bool, warnings: &'a mut Vec, + + /// Flag to ensure that we only suggest wrapping the entire function body in + /// an unsafe block once. + suggest_unsafe_block: bool, } impl<'tcx> UnsafetyVisitor<'_, 'tcx> { @@ -95,7 +99,13 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {} SafetyContext::UnsafeFn => { // unsafe_op_in_unsafe_fn is disallowed - kind.emit_unsafe_op_in_unsafe_fn_lint(self.tcx, self.hir_context, span); + kind.emit_unsafe_op_in_unsafe_fn_lint( + self.tcx, + self.hir_context, + span, + self.suggest_unsafe_block, + ); + self.suggest_unsafe_block = false; } SafetyContext::Safe => { kind.emit_requires_unsafe_err( @@ -297,6 +307,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } PatKind::InlineConstant { def, .. } => { self.visit_inner_body(*def); + visit::walk_pat(self, pat); } _ => { visit::walk_pat(self, pat); @@ -394,7 +405,9 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } } ExprKind::Deref { arg } => { - if let ExprKind::StaticRef { def_id, .. } = self.thir[arg].kind { + if let ExprKind::StaticRef { def_id, .. } | ExprKind::ThreadLocalRef(def_id) = + self.thir[arg].kind + { if self.tcx.is_mutable_static(def_id) { self.requires_unsafe(expr.span, UseOfMutableStatic); } else if self.tcx.is_foreign_item(def_id) { @@ -482,14 +495,6 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } } } - ExprKind::Let { expr: expr_id, .. } => { - let let_expr = &self.thir[expr_id]; - if let ty::Adt(adt_def, _) = let_expr.ty.kind() - && adt_def.is_union() - { - self.requires_unsafe(expr.span, AccessToUnionField); - } - } _ => {} } visit::walk_expr(self, expr); @@ -543,7 +548,22 @@ impl UnsafeOpKind { tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, + suggest_unsafe_block: bool, ) { + let parent_id = tcx.hir().get_parent_item(hir_id); + let parent_owner = tcx.hir().owner(parent_id); + let should_suggest = parent_owner.fn_sig().map_or(false, |sig| sig.header.is_unsafe()); + let unsafe_not_inherited_note = if should_suggest { + suggest_unsafe_block.then(|| { + let body_span = tcx.hir().body(parent_owner.body_id().unwrap()).value.span; + UnsafeNotInheritedLintNote { + signature_span: tcx.def_span(parent_id.def_id), + body_span, + } + }) + } else { + None + }; // FIXME: ideally we would want to trim the def paths, but this is not // feasible with the current lint emission API (see issue #106126). match self { @@ -554,61 +574,89 @@ impl UnsafeOpKind { UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe { span, function: &with_no_trimmed_paths!(tcx.def_path_str(*did)), + unsafe_not_inherited_note, }, ), CallToUnsafeFunction(None) => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { span }, + UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { + span, + unsafe_not_inherited_note, + }, ), UseOfInlineAssembly => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { span }, + UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), InitializingTypeWith => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { span }, + UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), UseOfMutableStatic => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { span }, + UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), UseOfExternStatic => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { span }, + UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), DerefOfRawPointer => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { span }, + UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), AccessToUnionField => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { span }, + UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), MutationOfLayoutConstrainedField => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { span }, + UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), BorrowOfLayoutConstrainedField => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, - UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { span }, + UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { + span, + unsafe_not_inherited_note, + }, ), CallToFunctionWith(did) => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, @@ -617,6 +665,7 @@ impl UnsafeOpKind { UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe { span, function: &with_no_trimmed_paths!(tcx.def_path_str(*did)), + unsafe_not_inherited_note, }, ), } @@ -831,6 +880,7 @@ pub fn thir_check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) { param_env: tcx.param_env(def), inside_adt: false, warnings: &mut warnings, + suggest_unsafe_block: true, }; visitor.visit_expr(&thir[expr]); diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index c4eed5532ee63..418f9bb9de94d 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -29,6 +29,8 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe<'a> { #[label] pub span: Span, pub function: &'a str, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -37,6 +39,8 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe<'a> { pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -45,6 +49,8 @@ pub struct UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafeNameless { pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -53,6 +59,8 @@ pub struct UnsafeOpInUnsafeFnUseOfInlineAssemblyRequiresUnsafe { pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -61,6 +69,8 @@ pub struct UnsafeOpInUnsafeFnInitializingTypeWithRequiresUnsafe { pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -69,6 +79,8 @@ pub struct UnsafeOpInUnsafeFnUseOfMutableStaticRequiresUnsafe { pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -77,6 +89,8 @@ pub struct UnsafeOpInUnsafeFnUseOfExternStaticRequiresUnsafe { pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -85,6 +99,8 @@ pub struct UnsafeOpInUnsafeFnDerefOfRawPointerRequiresUnsafe { pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -93,6 +109,8 @@ pub struct UnsafeOpInUnsafeFnAccessToUnionFieldRequiresUnsafe { pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -100,6 +118,8 @@ pub struct UnsafeOpInUnsafeFnMutationOfLayoutConstrainedFieldRequiresUnsafe { pub struct UnsafeOpInUnsafeFnBorrowOfLayoutConstrainedFieldRequiresUnsafe { #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(LintDiagnostic)] @@ -109,6 +129,8 @@ pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> { #[label] pub span: Span, pub function: &'a str, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option, } #[derive(Diagnostic)] @@ -376,6 +398,27 @@ pub struct UnsafeNotInheritedNote { pub span: Span, } +pub struct UnsafeNotInheritedLintNote { + pub signature_span: Span, + pub body_span: Span, +} + +impl AddToDiagnostic for UnsafeNotInheritedLintNote { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _: F) + where + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, + { + diag.span_note(self.signature_span, fluent::mir_build_unsafe_fn_safe_body); + let body_start = self.body_span.shrink_to_lo(); + let body_end = self.body_span.shrink_to_hi(); + diag.tool_only_multipart_suggestion( + fluent::mir_build_wrap_suggestion, + vec![(body_start, "{ unsafe ".into()), (body_end, "}".into())], + Applicability::MaybeIncorrect, + ); + } +} + #[derive(LintDiagnostic)] #[diag(mir_build_unused_unsafe)] pub struct UnusedUnsafe { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index e74d66a859926..620844f6f097c 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -3962,7 +3962,7 @@ impl<'test> TestCx<'test> { // And finally, compile the fixed code and make sure it both // succeeds and has no diagnostics. let rustc = self.make_compile_args( - &self.testpaths.file.with_extension(UI_FIXED), + &self.expected_output_path(UI_FIXED), TargetLocation::ThisFile(self.make_exe_name()), emit_metadata, AllowUnused::No, diff --git a/tests/ui/thread-local/thread-local-static.stderr b/tests/ui/thread-local/thread-local-static.mir.stderr similarity index 88% rename from tests/ui/thread-local/thread-local-static.stderr rename to tests/ui/thread-local/thread-local-static.mir.stderr index 712050a25fcfe..607d7ee902cb6 100644 --- a/tests/ui/thread-local/thread-local-static.stderr +++ b/tests/ui/thread-local/thread-local-static.mir.stderr @@ -1,5 +1,5 @@ error[E0658]: mutable references are not allowed in constant functions - --> $DIR/thread-local-static.rs:7:12 + --> $DIR/thread-local-static.rs:10:12 | LL | const fn g(x: &mut [u32; 8]) { | ^ @@ -8,13 +8,13 @@ LL | const fn g(x: &mut [u32; 8]) { = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error[E0625]: thread-local statics cannot be accessed at compile-time - --> $DIR/thread-local-static.rs:9:28 + --> $DIR/thread-local-static.rs:12:28 | LL | std::mem::swap(x, &mut STATIC_VAR_2) | ^^^^^^^^^^^^ error[E0013]: constant functions cannot refer to statics - --> $DIR/thread-local-static.rs:9:28 + --> $DIR/thread-local-static.rs:12:28 | LL | std::mem::swap(x, &mut STATIC_VAR_2) | ^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL | std::mem::swap(x, &mut STATIC_VAR_2) = help: consider extracting the value of the `static` to a `const`, and referring to that error[E0658]: mutable references are not allowed in constant functions - --> $DIR/thread-local-static.rs:9:23 + --> $DIR/thread-local-static.rs:12:23 | LL | std::mem::swap(x, &mut STATIC_VAR_2) | ^^^^^^^^^^^^^^^^^ @@ -31,7 +31,7 @@ LL | std::mem::swap(x, &mut STATIC_VAR_2) = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error[E0133]: use of mutable static is unsafe and requires unsafe function or block - --> $DIR/thread-local-static.rs:9:23 + --> $DIR/thread-local-static.rs:12:23 | LL | std::mem::swap(x, &mut STATIC_VAR_2) | ^^^^^^^^^^^^^^^^^ use of mutable static diff --git a/tests/ui/thread-local/thread-local-static.rs b/tests/ui/thread-local/thread-local-static.rs index c7fee9e6b4c5a..afaffbb7e9bbf 100644 --- a/tests/ui/thread-local/thread-local-static.rs +++ b/tests/ui/thread-local/thread-local-static.rs @@ -1,7 +1,10 @@ // edition:2018 +// revisions: mir thir +//thir: -Zthir-unsafeck #![feature(thread_local)] #![feature(const_swap)] + #[thread_local] static mut STATIC_VAR_2: [u32; 8] = [4; 8]; const fn g(x: &mut [u32; 8]) { diff --git a/tests/ui/thread-local/thread-local-static.thir.stderr b/tests/ui/thread-local/thread-local-static.thir.stderr new file mode 100644 index 0000000000000..607d7ee902cb6 --- /dev/null +++ b/tests/ui/thread-local/thread-local-static.thir.stderr @@ -0,0 +1,44 @@ +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/thread-local-static.rs:10:12 + | +LL | const fn g(x: &mut [u32; 8]) { + | ^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0625]: thread-local statics cannot be accessed at compile-time + --> $DIR/thread-local-static.rs:12:28 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^ + +error[E0013]: constant functions cannot refer to statics + --> $DIR/thread-local-static.rs:12:28 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/thread-local-static.rs:12:23 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0133]: use of mutable static is unsafe and requires unsafe function or block + --> $DIR/thread-local-static.rs:12:23 + | +LL | std::mem::swap(x, &mut STATIC_VAR_2) + | ^^^^^^^^^^^^^^^^^ 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 5 previous errors + +Some errors have detailed explanations: E0013, E0133, E0625, E0658. +For more information about an error, try `rustc --explain E0013`. diff --git a/tests/ui/union/union-unsafe.mir.stderr b/tests/ui/union/union-unsafe.mir.stderr index 544213dbc5543..15f059ffa4875 100644 --- a/tests/ui/union/union-unsafe.mir.stderr +++ b/tests/ui/union/union-unsafe.mir.stderr @@ -1,5 +1,5 @@ error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:33:5 + --> $DIR/union-unsafe.rs:34:5 | LL | *(u.p) = 13; | ^^^^^^^^^^^ access to union field @@ -7,7 +7,7 @@ LL | *(u.p) = 13; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:46:6 + --> $DIR/union-unsafe.rs:47:6 | LL | *u3.a = T::default(); | ^^^^ access to union field @@ -15,7 +15,7 @@ LL | *u3.a = T::default(); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:52:6 + --> $DIR/union-unsafe.rs:53:6 | LL | *u3.a = T::default(); | ^^^^ access to union field @@ -23,7 +23,7 @@ LL | *u3.a = T::default(); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:60:13 + --> $DIR/union-unsafe.rs:61:13 | LL | let a = u1.a; | ^^^^ access to union field @@ -31,7 +31,7 @@ LL | let a = u1.a; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:63:14 + --> $DIR/union-unsafe.rs:64:14 | LL | let U1 { a } = u1; | ^ access to union field @@ -39,7 +39,7 @@ LL | let U1 { a } = u1; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:64:12 + --> $DIR/union-unsafe.rs:65:12 | LL | if let U1 { a: 12 } = u1 {} | ^^^^^^^^^^^^ access to union field @@ -47,7 +47,15 @@ LL | if let U1 { a: 12 } = u1 {} = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:69:6 + --> $DIR/union-unsafe.rs:66:12 + | +LL | if let Some(U1 { a: 13 }) = Some(u1) {} + | ^^^^^^^^^^^^^^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:71:6 | LL | *u2.a = String::from("new"); | ^^^^ access to union field @@ -55,7 +63,7 @@ LL | *u2.a = String::from("new"); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:73:6 + --> $DIR/union-unsafe.rs:75:6 | LL | *u3.a = 1; | ^^^^ access to union field @@ -63,13 +71,13 @@ LL | *u3.a = 1; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:77:6 + --> $DIR/union-unsafe.rs:79:6 | LL | *u3.a = String::from("new"); | ^^^^ access to union field | = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/union/union-unsafe.rs b/tests/ui/union/union-unsafe.rs index 5e1837a901d46..d1465486f7784 100644 --- a/tests/ui/union/union-unsafe.rs +++ b/tests/ui/union/union-unsafe.rs @@ -1,30 +1,31 @@ // revisions: mir thir // [thir]compile-flags: -Z thir-unsafeck -use std::mem::ManuallyDrop; use std::cell::RefCell; +use std::mem::ManuallyDrop; union U1 { - a: u8 + a: u8, } union U2 { - a: ManuallyDrop + a: ManuallyDrop, } union U3 { - a: ManuallyDrop + a: ManuallyDrop, } union U4 { - a: T + a: T, } union URef { p: &'static mut i32, } -union URefCell { // field that does not drop but is not `Copy`, either +union URefCell { + // field that does not drop but is not `Copy`, either a: (ManuallyDrop>, i32), } @@ -62,6 +63,7 @@ fn main() { let U1 { a } = u1; //~ ERROR access to union field is unsafe if let U1 { a: 12 } = u1 {} //~ ERROR access to union field is unsafe + if let Some(U1 { a: 13 }) = Some(u1) {} //~ ERROR access to union field is unsafe // let U1 { .. } = u1; // OK let mut u2 = U2 { a: ManuallyDrop::new(String::from("old")) }; // OK diff --git a/tests/ui/union/union-unsafe.thir.stderr b/tests/ui/union/union-unsafe.thir.stderr index f959fe5bdb5c5..9ce835497c519 100644 --- a/tests/ui/union/union-unsafe.thir.stderr +++ b/tests/ui/union/union-unsafe.thir.stderr @@ -1,5 +1,5 @@ error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:33:6 + --> $DIR/union-unsafe.rs:34:6 | LL | *(u.p) = 13; | ^^^^^ access to union field @@ -7,7 +7,7 @@ LL | *(u.p) = 13; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:46:6 + --> $DIR/union-unsafe.rs:47:6 | LL | *u3.a = T::default(); | ^^^^ access to union field @@ -15,7 +15,7 @@ LL | *u3.a = T::default(); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:52:6 + --> $DIR/union-unsafe.rs:53:6 | LL | *u3.a = T::default(); | ^^^^ access to union field @@ -23,7 +23,7 @@ LL | *u3.a = T::default(); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:60:13 + --> $DIR/union-unsafe.rs:61:13 | LL | let a = u1.a; | ^^^^ access to union field @@ -31,7 +31,7 @@ LL | let a = u1.a; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:63:14 + --> $DIR/union-unsafe.rs:64:14 | LL | let U1 { a } = u1; | ^ access to union field @@ -39,15 +39,23 @@ LL | let U1 { a } = u1; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:64:8 + --> $DIR/union-unsafe.rs:65:20 | LL | if let U1 { a: 12 } = u1 {} - | ^^^^^^^^^^^^^^^^^^^^^ access to union field + | ^^ access to union field | = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:69:6 + --> $DIR/union-unsafe.rs:66:25 + | +LL | if let Some(U1 { a: 13 }) = Some(u1) {} + | ^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:71:6 | LL | *u2.a = String::from("new"); | ^^^^ access to union field @@ -55,7 +63,7 @@ LL | *u2.a = String::from("new"); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:73:6 + --> $DIR/union-unsafe.rs:75:6 | LL | *u3.a = 1; | ^^^^ access to union field @@ -63,13 +71,13 @@ LL | *u3.a = 1; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:77:6 + --> $DIR/union-unsafe.rs:79:6 | LL | *u3.a = String::from("new"); | ^^^^ access to union field | = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.mir.stderr similarity index 80% rename from tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr rename to tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.mir.stderr index fbc621f4d0e37..ea53bf59d3101 100644 --- a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.stderr +++ b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.mir.stderr @@ -1,12 +1,12 @@ warning: call to unsafe function is unsafe and requires unsafe block (error E0133) - --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:12:5 + --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:13: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/edition-2024-unsafe_op_in_unsafe_fn.rs:11:1 + --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:12:1 | LL | unsafe fn foo() { | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.rs b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.rs index a192f3445f73e..1b429955cb035 100644 --- a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.rs +++ b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.rs @@ -1,17 +1,21 @@ // edition: 2024 // compile-flags: -Zunstable-options // check-pass +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck #![crate_type = "lib"] - #![deny(unused_unsafe)] unsafe fn unsf() {} unsafe fn foo() { unsf(); - //~^ WARN call to unsafe function is unsafe and requires unsafe block + //[mir]~^ WARN call to unsafe function is unsafe and requires unsafe block + //[thir]~^^ WARN call to unsafe function `unsf` is unsafe and requires unsafe block // no unused_unsafe - unsafe { unsf(); } + unsafe { + unsf(); + } } diff --git a/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.thir.stderr b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.thir.stderr new file mode 100644 index 0000000000000..d63843ed2b361 --- /dev/null +++ b/tests/ui/unsafe/edition-2024-unsafe_op_in_unsafe_fn.thir.stderr @@ -0,0 +1,16 @@ +warning: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) + --> $DIR/edition-2024-unsafe_op_in_unsafe_fn.rs:13: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/edition-2024-unsafe_op_in_unsafe_fn.rs:12:1 + | +LL | unsafe fn foo() { + | ^^^^^^^^^^^^^^^ + = note: `#[warn(unsafe_op_in_unsafe_fn)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr b/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr index 427843f8d45ce..dc6bd72f56c57 100644 --- a/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr +++ b/tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr @@ -6,6 +6,14 @@ LL | let y = &mut x.0; | = note: mutating layout constrained fields cannot statically be checked for valid values -error: aborting due to previous error +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints2.rs:12:25 + | +LL | if let Some(NonZero(ref mut y)) = Some(x) {} + | ^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/ranged_ints2.rs b/tests/ui/unsafe/ranged_ints2.rs index 9a6bb18f92664..ad9d598aba2a4 100644 --- a/tests/ui/unsafe/ranged_ints2.rs +++ b/tests/ui/unsafe/ranged_ints2.rs @@ -9,4 +9,5 @@ pub(crate) struct NonZero(pub(crate) T); fn main() { let mut x = unsafe { NonZero(1) }; let y = &mut x.0; //~ ERROR mutation of layout constrained field is unsafe + if let Some(NonZero(ref mut y)) = Some(x) {} //~ ERROR mutation of layout constrained field is unsafe } diff --git a/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr b/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr index 427843f8d45ce..dc6bd72f56c57 100644 --- a/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr +++ b/tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr @@ -6,6 +6,14 @@ LL | let y = &mut x.0; | = note: mutating layout constrained fields cannot statically be checked for valid values -error: aborting due to previous error +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints2.rs:12:25 + | +LL | if let Some(NonZero(ref mut y)) = Some(x) {} + | ^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr index 4cdd97e5e06aa..ad0621a1d0435 100644 --- a/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr +++ b/tests/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.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.mir.fixed similarity index 73% rename from tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed rename to tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.fixed index db1c102210e3b..b59029df6429b 100644 --- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.fixed +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.fixed @@ -1,7 +1,10 @@ // run-rustfix // aux-build:external_unsafe_macro.rs +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck #![deny(unsafe_op_in_unsafe_fn)] //~ NOTE +#![crate_name = "wrapping_unsafe_block_sugg"] extern crate external_unsafe_macro; @@ -9,11 +12,13 @@ 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 + unsf(); //[mir]~ ERROR call to unsafe function is unsafe + //[thir]~^ ERROR call to unsafe function `unsf` is unsafe + //~^^ NOTE //~| NOTE - unsf(); //~ ERROR call to unsafe function is unsafe - //~^ NOTE + unsf(); //[mir]~ ERROR call to unsafe function is unsafe + //[thir]~^ ERROR call to unsafe function `unsf` is unsafe + //~^^ NOTE //~| NOTE }} @@ -39,10 +44,12 @@ pub unsafe fn baz() -> i32 { unsafe { }} macro_rules! unsafe_macro { () => (unsf()) } -//~^ ERROR call to unsafe function is unsafe +//[mir]~^ ERROR call to unsafe function is unsafe +//[thir]~^^ ERROR call to unsafe function `unsf` is unsafe //~| NOTE //~| NOTE -//~| ERROR call to unsafe function is unsafe +//[mir]~| ERROR call to unsafe function is unsafe +//[thir]~| ERROR call to unsafe function `unsf` is unsafe //~| NOTE //~| NOTE diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.stderr similarity index 86% rename from tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr rename to tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.stderr index 43f619c27d274..7a1b83c7367da 100644 --- a/tests/ui/unsafe/wrapping-unsafe-block-sugg.stderr +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.mir.stderr @@ -1,23 +1,23 @@ 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 | = 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:10:1 + --> $DIR/wrapping-unsafe-block-sugg.rs:13:1 | LL | pub unsafe fn foo() { | ^^^^^^^^^^^^^^^^^^^ note: the lint level is defined here - --> $DIR/wrapping-unsafe-block-sugg.rs:4:9 + --> $DIR/wrapping-unsafe-block-sugg.rs:6: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:15:5 + --> $DIR/wrapping-unsafe-block-sugg.rs:19: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:22:13 + --> $DIR/wrapping-unsafe-block-sugg.rs:27: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:20:1 + --> $DIR/wrapping-unsafe-block-sugg.rs:25: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:25:9 + --> $DIR/wrapping-unsafe-block-sugg.rs:30:9 | LL | y + *x | ^^ dereference of raw pointer @@ -46,20 +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:33:13 + --> $DIR/wrapping-unsafe-block-sugg.rs:38: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:31:1 + --> $DIR/wrapping-unsafe-block-sugg.rs:36: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:36:9 + --> $DIR/wrapping-unsafe-block-sugg.rs:41:9 | LL | y + BAZ | ^^^ use of mutable static @@ -67,7 +67,7 @@ LL | y + BAZ = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior error: call to unsafe function is unsafe and requires unsafe block (error E0133) - --> $DIR/wrapping-unsafe-block-sugg.rs:41:36 + --> $DIR/wrapping-unsafe-block-sugg.rs:46:36 | LL | macro_rules! unsafe_macro { () => (unsf()) } | ^^^^^^ call to unsafe function @@ -77,14 +77,14 @@ LL | unsafe_macro!(); | = 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 + --> $DIR/wrapping-unsafe-block-sugg.rs:56: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 + --> $DIR/wrapping-unsafe-block-sugg.rs:46:36 | LL | macro_rules! unsafe_macro { () => (unsf()) } | ^^^^^^ call to unsafe function diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs b/tests/ui/unsafe/wrapping-unsafe-block-sugg.rs index 9c6be45896e25..3629b8a1beb5f 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 +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck #![deny(unsafe_op_in_unsafe_fn)] //~ NOTE +#![crate_name = "wrapping_unsafe_block_sugg"] extern crate external_unsafe_macro; @@ -9,11 +12,13 @@ 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 + unsf(); //[mir]~ ERROR call to unsafe function is unsafe + //[thir]~^ ERROR call to unsafe function `unsf` is unsafe + //~^^ NOTE //~| NOTE - unsf(); //~ ERROR call to unsafe function is unsafe - //~^ NOTE + unsf(); //[mir]~ ERROR call to unsafe function is unsafe + //[thir]~^ ERROR call to unsafe function `unsf` is unsafe + //~^^ NOTE //~| NOTE } @@ -39,10 +44,12 @@ pub unsafe fn baz() -> i32 { } macro_rules! unsafe_macro { () => (unsf()) } -//~^ ERROR call to unsafe function is unsafe +//[mir]~^ ERROR call to unsafe function is unsafe +//[thir]~^^ ERROR call to unsafe function `unsf` is unsafe //~| NOTE //~| NOTE -//~| ERROR call to unsafe function is unsafe +//[mir]~| ERROR call to unsafe function is unsafe +//[thir]~| ERROR call to unsafe function `unsf` is unsafe //~| NOTE //~| NOTE diff --git a/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.fixed b/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.fixed new file mode 100644 index 0000000000000..b59029df6429b --- /dev/null +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.fixed @@ -0,0 +1,73 @@ +// run-rustfix +// aux-build:external_unsafe_macro.rs +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck + +#![deny(unsafe_op_in_unsafe_fn)] //~ NOTE +#![crate_name = "wrapping_unsafe_block_sugg"] + +extern crate external_unsafe_macro; + +unsafe fn unsf() {} + +pub unsafe fn foo() { unsafe { + //~^ NOTE an unsafe function restricts its caller, but its body is safe by default + unsf(); //[mir]~ ERROR call to unsafe function is unsafe + //[thir]~^ ERROR call to unsafe function `unsf` is unsafe + //~^^ NOTE + //~| NOTE + unsf(); //[mir]~ ERROR call to unsafe function is unsafe + //[thir]~^ ERROR call to unsafe function `unsf` 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 +}} + +macro_rules! unsafe_macro { () => (unsf()) } +//[mir]~^ ERROR call to unsafe function is unsafe +//[thir]~^^ ERROR call to unsafe function `unsf` is unsafe +//~| NOTE +//~| NOTE +//[mir]~| ERROR call to unsafe function is unsafe +//[thir]~| ERROR call to unsafe function `unsf` 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.thir.stderr b/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.stderr new file mode 100644 index 0000000000000..b1fb35f85a606 --- /dev/null +++ b/tests/ui/unsafe/wrapping-unsafe-block-sugg.thir.stderr @@ -0,0 +1,99 @@ +error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:15: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:13:1 + | +LL | pub unsafe fn foo() { + | ^^^^^^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/wrapping-unsafe-block-sugg.rs:6:9 + | +LL | #![deny(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:19:5 + | +LL | unsf(); + | ^^^^^^ call to unsafe function + | + = 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:27: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:25: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:30: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:38: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:36: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:41: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: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:46: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:56: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 `unsf` is unsafe and requires unsafe block (error E0133) + --> $DIR/wrapping-unsafe-block-sugg.rs:46: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 +