From b0888614f1ba57881494cde078e71706cea51da1 Mon Sep 17 00:00:00 2001 From: Fabian Wolff Date: Sun, 27 Jun 2021 14:59:38 +0200 Subject: [PATCH] Implement Mutation- and BorrowOfLayoutConstrainedField in thir-unsafeck --- .../rustc_mir_build/src/build/expr/mod.rs | 2 +- compiler/rustc_mir_build/src/build/mod.rs | 2 + .../rustc_mir_build/src/check_unsafety.rs | 197 +++++++++++++----- ...stderr => ranged_ints2.mirunsafeck.stderr} | 2 +- src/test/ui/unsafe/ranged_ints2.rs | 3 + .../unsafe/ranged_ints2.thirunsafeck.stderr | 11 + ... => ranged_ints2_const.mirunsafeck.stderr} | 8 +- src/test/ui/unsafe/ranged_ints2_const.rs | 3 + .../ranged_ints2_const.thirunsafeck.stderr | 39 ++++ ...stderr => ranged_ints3.mirunsafeck.stderr} | 2 +- src/test/ui/unsafe/ranged_ints3.rs | 3 + .../unsafe/ranged_ints3.thirunsafeck.stderr | 11 + ... => ranged_ints3_const.mirunsafeck.stderr} | 6 +- src/test/ui/unsafe/ranged_ints3_const.rs | 3 + .../ranged_ints3_const.thirunsafeck.stderr | 30 +++ .../ranged_ints3_match.mirunsafeck.stderr | 19 ++ src/test/ui/unsafe/ranged_ints3_match.rs | 22 ++ .../ranged_ints3_match.thirunsafeck.stderr | 19 ++ ...stderr => ranged_ints4.mirunsafeck.stderr} | 2 +- src/test/ui/unsafe/ranged_ints4.rs | 3 + ...tderr => ranged_ints4.thirunsafeck.stderr} | 2 +- .../ranged_ints4_const.mirunsafeck.stderr | 11 + src/test/ui/unsafe/ranged_ints4_const.rs | 3 + .../ranged_ints4_const.thirunsafeck.stderr | 11 + .../unsafe/unsafe-assign.mirunsafeck.stderr | 11 + src/test/ui/unsafe/unsafe-assign.rs | 25 +++ .../unsafe/unsafe-assign.thirunsafeck.stderr | 11 + .../unsafe/unsafe-borrow.mirunsafeck.stderr | 27 +++ src/test/ui/unsafe/unsafe-borrow.rs | 56 +++++ .../unsafe/unsafe-borrow.thirunsafeck.stderr | 27 +++ 30 files changed, 512 insertions(+), 59 deletions(-) rename src/test/ui/unsafe/{ranged_ints2.stderr => ranged_ints2.mirunsafeck.stderr} (92%) create mode 100644 src/test/ui/unsafe/ranged_ints2.thirunsafeck.stderr rename src/test/ui/unsafe/{ranged_ints2_const.stderr => ranged_ints2_const.mirunsafeck.stderr} (90%) create mode 100644 src/test/ui/unsafe/ranged_ints2_const.thirunsafeck.stderr rename src/test/ui/unsafe/{ranged_ints3.stderr => ranged_ints3.mirunsafeck.stderr} (93%) create mode 100644 src/test/ui/unsafe/ranged_ints3.thirunsafeck.stderr rename src/test/ui/unsafe/{ranged_ints3_const.stderr => ranged_ints3_const.mirunsafeck.stderr} (91%) create mode 100644 src/test/ui/unsafe/ranged_ints3_const.thirunsafeck.stderr create mode 100644 src/test/ui/unsafe/ranged_ints3_match.mirunsafeck.stderr create mode 100644 src/test/ui/unsafe/ranged_ints3_match.rs create mode 100644 src/test/ui/unsafe/ranged_ints3_match.thirunsafeck.stderr rename src/test/ui/unsafe/{ranged_ints4.stderr => ranged_ints4.mirunsafeck.stderr} (92%) rename src/test/ui/unsafe/{ranged_ints4_const.stderr => ranged_ints4.thirunsafeck.stderr} (90%) create mode 100644 src/test/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr create mode 100644 src/test/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr create mode 100644 src/test/ui/unsafe/unsafe-assign.mirunsafeck.stderr create mode 100644 src/test/ui/unsafe/unsafe-assign.rs create mode 100644 src/test/ui/unsafe/unsafe-assign.thirunsafeck.stderr create mode 100644 src/test/ui/unsafe/unsafe-borrow.mirunsafeck.stderr create mode 100644 src/test/ui/unsafe/unsafe-borrow.rs create mode 100644 src/test/ui/unsafe/unsafe-borrow.thirunsafeck.stderr diff --git a/compiler/rustc_mir_build/src/build/expr/mod.rs b/compiler/rustc_mir_build/src/build/expr/mod.rs index 539de80cab71c..7c1a592f5515e 100644 --- a/compiler/rustc_mir_build/src/build/expr/mod.rs +++ b/compiler/rustc_mir_build/src/build/expr/mod.rs @@ -65,6 +65,6 @@ mod as_operand; pub mod as_place; mod as_rvalue; mod as_temp; -mod category; +pub mod category; mod into; mod stmt; diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index f5f6da3ec0bba..60cfd73b19a6e 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -1131,3 +1131,5 @@ mod expr; mod matches; mod misc; mod scope; + +pub(crate) use expr::category::Category as ExprCategory; diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index c3af98fae9d59..9c610b88dbb5b 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -1,9 +1,11 @@ +use crate::build::ExprCategory; use crate::thir::visit::{self, Visitor}; use rustc_errors::struct_span_err; use rustc_hir as hir; +use rustc_middle::mir::BorrowKind; use rustc_middle::thir::*; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, ParamEnv, TyCtxt}; use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; use rustc_session::lint::Level; use rustc_span::def_id::{DefId, LocalDefId}; @@ -28,6 +30,8 @@ struct UnsafetyVisitor<'a, 'tcx> { is_const: bool, in_possible_lhs_union_assign: bool, in_union_destructure: bool, + param_env: ParamEnv<'tcx>, + inside_adt: bool, } impl<'tcx> UnsafetyVisitor<'_, 'tcx> { @@ -134,6 +138,50 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { } } +// Searches for accesses to layout constrained fields. +struct LayoutConstrainedPlaceVisitor<'a, 'tcx> { + found: bool, + thir: &'a Thir<'tcx>, + tcx: TyCtxt<'tcx>, +} + +impl<'a, 'tcx> LayoutConstrainedPlaceVisitor<'a, 'tcx> { + fn new(thir: &'a Thir<'tcx>, tcx: TyCtxt<'tcx>) -> Self { + Self { found: false, thir, tcx } + } +} + +impl<'a, 'tcx> Visitor<'a, 'tcx> for LayoutConstrainedPlaceVisitor<'a, 'tcx> { + fn thir(&self) -> &'a Thir<'tcx> { + self.thir + } + + fn visit_expr(&mut self, expr: &Expr<'tcx>) { + match expr.kind { + ExprKind::Field { lhs, .. } => { + if let ty::Adt(adt_def, _) = self.thir[lhs].ty.kind() { + if (Bound::Unbounded, Bound::Unbounded) + != self.tcx.layout_scalar_valid_range(adt_def.did) + { + self.found = true; + } + } + visit::walk_expr(self, expr); + } + + // Keep walking through the expression as long as we stay in the same + // place, i.e. the expression is a place expression and not a dereference + // (since dereferencing something leads us to a different place). + ExprKind::Deref { .. } => {} + ref kind if ExprCategory::of(kind).map_or(true, |cat| cat == ExprCategory::Place) => { + visit::walk_expr(self, expr); + } + + _ => {} + } + } +} + impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { fn thir(&self) -> &'a Thir<'tcx> { &self.thir @@ -161,60 +209,82 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } fn visit_pat(&mut self, pat: &Pat<'tcx>) { - use PatKind::*; - if self.in_union_destructure { match *pat.kind { // binding to a variable allows getting stuff out of variable - Binding { .. } + PatKind::Binding { .. } // match is conditional on having this value - | Constant { .. } - | Variant { .. } - | Leaf { .. } - | Deref { .. } - | Range { .. } - | Slice { .. } - | Array { .. } => { + | PatKind::Constant { .. } + | PatKind::Variant { .. } + | PatKind::Leaf { .. } + | PatKind::Deref { .. } + | PatKind::Range { .. } + | PatKind::Slice { .. } + | PatKind::Array { .. } => { self.requires_unsafe(pat.span, AccessToUnionField); - return; // don't walk pattern + return; // we can return here since this already requires unsafe } // wildcard doesn't take anything - Wild | + PatKind::Wild | // these just wrap other patterns - Or { .. } | - AscribeUserType { .. } => {} + PatKind::Or { .. } | + PatKind::AscribeUserType { .. } => {} } }; - if let ty::Adt(adt_def, _) = pat.ty.kind() { - // check for extracting values from union via destructuring - if adt_def.is_union() { - match *pat.kind { - // assigning the whole union is okay - // let x = Union { ... }; - // let y = x; // safe - Binding { .. } | - // binding to wildcard is okay since that never reads anything and stops double errors - // with implict wildcard branches from `if let`s - Wild | - // doesn't have any effect on semantics - AscribeUserType { .. } | - // creating a union literal - Constant { .. } => {}, - Leaf { .. } | Or { .. } => { - // pattern matching with a union and not doing something like v = Union { bar: 5 } - self.in_union_destructure = true; + match &*pat.kind { + PatKind::Leaf { .. } => { + if let ty::Adt(adt_def, ..) = pat.ty.kind() { + if adt_def.is_union() { + let old_in_union_destructure = + std::mem::replace(&mut self.in_union_destructure, true); + visit::walk_pat(self, pat); + self.in_union_destructure = old_in_union_destructure; + } else if (Bound::Unbounded, Bound::Unbounded) + != self.tcx.layout_scalar_valid_range(adt_def.did) + { + let old_inside_adt = std::mem::replace(&mut self.inside_adt, true); + visit::walk_pat(self, pat); + self.inside_adt = old_inside_adt; + } else { visit::walk_pat(self, pat); - self.in_union_destructure = false; - return; // don't walk pattern } - Variant { .. } | Deref { .. } | Range { .. } | Slice { .. } | Array { .. } => - unreachable!("impossible union destructuring type"), + } else { + visit::walk_pat(self, pat); } } + PatKind::Binding { mode: BindingMode::ByRef(borrow_kind), ty, .. } => { + if self.inside_adt { + if let ty::Ref(_, ty, _) = ty.kind() { + match borrow_kind { + BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique => { + if !ty.is_freeze(self.tcx.at(pat.span), self.param_env) { + self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField); + } + } + BorrowKind::Mut { .. } => { + self.requires_unsafe(pat.span, MutationOfLayoutConstrainedField); + } + } + } else { + span_bug!( + pat.span, + "BindingMode::ByRef in pattern, but found non-reference type {}", + ty + ); + } + } + visit::walk_pat(self, pat); + } + PatKind::Deref { .. } => { + let old_inside_adt = std::mem::replace(&mut self.inside_adt, false); + visit::walk_pat(self, pat); + self.inside_adt = old_inside_adt; + } + _ => { + visit::walk_pat(self, pat); + } } - - visit::walk_pat(self, pat); } fn visit_expr(&mut self, expr: &Expr<'tcx>) { @@ -361,15 +431,46 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { } } } - // don't have any special handling for AssignOp since it causes a read *and* write to lhs - ExprKind::Assign { lhs, rhs } => { - // assigning to a union is safe, check here so it doesn't get treated as a read later - self.in_possible_lhs_union_assign = true; - visit::walk_expr(self, &self.thir()[lhs]); - self.in_possible_lhs_union_assign = false; - visit::walk_expr(self, &self.thir()[rhs]); - return; // don't visit the whole expression + ExprKind::Assign { lhs, rhs } | ExprKind::AssignOp { lhs, rhs, .. } => { + // First, check whether we are mutating a layout constrained field + let mut visitor = LayoutConstrainedPlaceVisitor::new(self.thir, self.tcx); + visit::walk_expr(&mut visitor, &self.thir[lhs]); + if visitor.found { + self.requires_unsafe(expr.span, MutationOfLayoutConstrainedField); + } + + // Second, check for accesses to union fields + // don't have any special handling for AssignOp since it causes a read *and* write to lhs + if matches!(expr.kind, ExprKind::Assign { .. }) { + // assigning to a union is safe, check here so it doesn't get treated as a read later + self.in_possible_lhs_union_assign = true; + visit::walk_expr(self, &self.thir()[lhs]); + self.in_possible_lhs_union_assign = false; + visit::walk_expr(self, &self.thir()[rhs]); + return; // we have already visited everything by now + } } + ExprKind::Borrow { borrow_kind, arg } => match borrow_kind { + BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique => { + if !self.thir[arg] + .ty + .is_freeze(self.tcx.at(self.thir[arg].span), self.param_env) + { + let mut visitor = LayoutConstrainedPlaceVisitor::new(self.thir, self.tcx); + visit::walk_expr(&mut visitor, expr); + if visitor.found { + self.requires_unsafe(expr.span, BorrowOfLayoutConstrainedField); + } + } + } + BorrowKind::Mut { .. } => { + let mut visitor = LayoutConstrainedPlaceVisitor::new(self.thir, self.tcx); + visit::walk_expr(&mut visitor, expr); + if visitor.found { + self.requires_unsafe(expr.span, MutationOfLayoutConstrainedField); + } + } + }, _ => {} } visit::walk_expr(self, expr); @@ -541,6 +642,8 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam $DIR/ranged_ints2.rs:8:13 + --> $DIR/ranged_ints2.rs:11:13 | LL | let y = &mut x.0; | ^^^^^^^^ mutation of layout constrained field diff --git a/src/test/ui/unsafe/ranged_ints2.rs b/src/test/ui/unsafe/ranged_ints2.rs index 68ba120b279c0..9a6bb18f92664 100644 --- a/src/test/ui/unsafe/ranged_ints2.rs +++ b/src/test/ui/unsafe/ranged_ints2.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![feature(rustc_attrs)] #[rustc_layout_scalar_valid_range_start(1)] diff --git a/src/test/ui/unsafe/ranged_ints2.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints2.thirunsafeck.stderr new file mode 100644 index 0000000000000..427843f8d45ce --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints2.thirunsafeck.stderr @@ -0,0 +1,11 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints2.rs:11:13 + | +LL | let y = &mut x.0; + | ^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/ranged_ints2_const.stderr b/src/test/ui/unsafe/ranged_ints2_const.mirunsafeck.stderr similarity index 90% rename from src/test/ui/unsafe/ranged_ints2_const.stderr rename to src/test/ui/unsafe/ranged_ints2_const.mirunsafeck.stderr index a0dc950e76dd1..c16550a58005f 100644 --- a/src/test/ui/unsafe/ranged_ints2_const.stderr +++ b/src/test/ui/unsafe/ranged_ints2_const.mirunsafeck.stderr @@ -1,5 +1,5 @@ error[E0658]: mutable references are not allowed in constant functions - --> $DIR/ranged_ints2_const.rs:11:13 + --> $DIR/ranged_ints2_const.rs:14:13 | LL | let y = &mut x.0; | ^^^^^^^^ @@ -8,7 +8,7 @@ LL | let y = &mut x.0; = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error[E0658]: mutable references are not allowed in constant functions - --> $DIR/ranged_ints2_const.rs:18:22 + --> $DIR/ranged_ints2_const.rs:21:22 | LL | let y = unsafe { &mut x.0 }; | ^^^^^^^^ @@ -17,7 +17,7 @@ LL | let y = unsafe { &mut x.0 }; = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error[E0658]: mutable references are not allowed in constant functions - --> $DIR/ranged_ints2_const.rs:24:22 + --> $DIR/ranged_ints2_const.rs:27:22 | LL | unsafe { let y = &mut x.0; } | ^^^^^^^^ @@ -26,7 +26,7 @@ LL | unsafe { let y = &mut x.0; } = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block - --> $DIR/ranged_ints2_const.rs:11:13 + --> $DIR/ranged_ints2_const.rs:14:13 | LL | let y = &mut x.0; | ^^^^^^^^ mutation of layout constrained field diff --git a/src/test/ui/unsafe/ranged_ints2_const.rs b/src/test/ui/unsafe/ranged_ints2_const.rs index b7178c2b52bfb..56f5407bb6ebe 100644 --- a/src/test/ui/unsafe/ranged_ints2_const.rs +++ b/src/test/ui/unsafe/ranged_ints2_const.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![feature(rustc_attrs)] #[rustc_layout_scalar_valid_range_start(1)] diff --git a/src/test/ui/unsafe/ranged_ints2_const.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints2_const.thirunsafeck.stderr new file mode 100644 index 0000000000000..b3f139f7213ff --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints2_const.thirunsafeck.stderr @@ -0,0 +1,39 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints2_const.rs:14:13 + | +LL | let y = &mut x.0; + | ^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/ranged_ints2_const.rs:14:13 + | +LL | let y = &mut x.0; + | ^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/ranged_ints2_const.rs:21:22 + | +LL | let y = unsafe { &mut x.0 }; + | ^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constant functions + --> $DIR/ranged_ints2_const.rs:27:22 + | +LL | unsafe { let y = &mut x.0; } + | ^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/ranged_ints3.stderr b/src/test/ui/unsafe/ranged_ints3.mirunsafeck.stderr similarity index 93% rename from src/test/ui/unsafe/ranged_ints3.stderr rename to src/test/ui/unsafe/ranged_ints3.mirunsafeck.stderr index 4d4c9167150ed..9eec0b09e9b18 100644 --- a/src/test/ui/unsafe/ranged_ints3.stderr +++ b/src/test/ui/unsafe/ranged_ints3.mirunsafeck.stderr @@ -1,5 +1,5 @@ error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block - --> $DIR/ranged_ints3.rs:10:13 + --> $DIR/ranged_ints3.rs:13:13 | LL | let y = &x.0; | ^^^^ borrow of layout constrained field with interior mutability diff --git a/src/test/ui/unsafe/ranged_ints3.rs b/src/test/ui/unsafe/ranged_ints3.rs index 47d67fac6785c..76d4bfe95307d 100644 --- a/src/test/ui/unsafe/ranged_ints3.rs +++ b/src/test/ui/unsafe/ranged_ints3.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![feature(rustc_attrs)] use std::cell::Cell; diff --git a/src/test/ui/unsafe/ranged_ints3.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints3.thirunsafeck.stderr new file mode 100644 index 0000000000000..9eec0b09e9b18 --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints3.thirunsafeck.stderr @@ -0,0 +1,11 @@ +error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block + --> $DIR/ranged_ints3.rs:13:13 + | +LL | let y = &x.0; + | ^^^^ borrow of layout constrained field with interior mutability + | + = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/ranged_ints3_const.stderr b/src/test/ui/unsafe/ranged_ints3_const.mirunsafeck.stderr similarity index 91% rename from src/test/ui/unsafe/ranged_ints3_const.stderr rename to src/test/ui/unsafe/ranged_ints3_const.mirunsafeck.stderr index 215005571f6d7..62df933306962 100644 --- a/src/test/ui/unsafe/ranged_ints3_const.stderr +++ b/src/test/ui/unsafe/ranged_ints3_const.mirunsafeck.stderr @@ -1,5 +1,5 @@ error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability - --> $DIR/ranged_ints3_const.rs:12:13 + --> $DIR/ranged_ints3_const.rs:15:13 | LL | let y = &x.0; | ^^^^ @@ -8,7 +8,7 @@ LL | let y = &x.0; = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability - --> $DIR/ranged_ints3_const.rs:19:22 + --> $DIR/ranged_ints3_const.rs:22:22 | LL | let y = unsafe { &x.0 }; | ^^^^ @@ -17,7 +17,7 @@ LL | let y = unsafe { &x.0 }; = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block - --> $DIR/ranged_ints3_const.rs:12:13 + --> $DIR/ranged_ints3_const.rs:15:13 | LL | let y = &x.0; | ^^^^ borrow of layout constrained field with interior mutability diff --git a/src/test/ui/unsafe/ranged_ints3_const.rs b/src/test/ui/unsafe/ranged_ints3_const.rs index c069ae7da0212..637198d360422 100644 --- a/src/test/ui/unsafe/ranged_ints3_const.rs +++ b/src/test/ui/unsafe/ranged_ints3_const.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![feature(rustc_attrs)] use std::cell::Cell; diff --git a/src/test/ui/unsafe/ranged_ints3_const.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints3_const.thirunsafeck.stderr new file mode 100644 index 0000000000000..5dbc563aad261 --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints3_const.thirunsafeck.stderr @@ -0,0 +1,30 @@ +error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block + --> $DIR/ranged_ints3_const.rs:15:13 + | +LL | let y = &x.0; + | ^^^^ borrow of layout constrained field with interior mutability + | + = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values + +error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability + --> $DIR/ranged_ints3_const.rs:15:13 + | +LL | let y = &x.0; + | ^^^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable + +error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability + --> $DIR/ranged_ints3_const.rs:22:22 + | +LL | let y = unsafe { &x.0 }; + | ^^^^ + | + = note: see issue #80384 for more information + = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0133, E0658. +For more information about an error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/ranged_ints3_match.mirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints3_match.mirunsafeck.stderr new file mode 100644 index 0000000000000..27c06640928fa --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints3_match.mirunsafeck.stderr @@ -0,0 +1,19 @@ +error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block + --> $DIR/ranged_ints3_match.rs:14:17 + | +LL | NonZero(ref x) => { x } + | ^^^^^ borrow of layout constrained field with interior mutability + | + = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values + +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints3_match.rs:20:23 + | +LL | match y { NonZero(ref mut y) => { y } }; + | ^^^^^^^^^ 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/src/test/ui/unsafe/ranged_ints3_match.rs b/src/test/ui/unsafe/ranged_ints3_match.rs new file mode 100644 index 0000000000000..d9fcf0bd665c2 --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints3_match.rs @@ -0,0 +1,22 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![feature(rustc_attrs)] + +use std::cell::Cell; + +#[rustc_layout_scalar_valid_range_start(1)] +#[repr(transparent)] +pub(crate) struct NonZero(pub(crate) T); +fn main() { + let mut x = unsafe { NonZero(Cell::new(1)) }; + match x { + NonZero(ref x) => { x } + //~^ ERROR borrow of layout constrained field with interior mutability + }; + + let mut y = unsafe { NonZero(42) }; + match y { NonZero(ref y) => { y } }; // OK, type of `y` is freeze + match y { NonZero(ref mut y) => { y } }; + //~^ ERROR mutation of layout constrained field +} diff --git a/src/test/ui/unsafe/ranged_ints3_match.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints3_match.thirunsafeck.stderr new file mode 100644 index 0000000000000..27c06640928fa --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints3_match.thirunsafeck.stderr @@ -0,0 +1,19 @@ +error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block + --> $DIR/ranged_ints3_match.rs:14:17 + | +LL | NonZero(ref x) => { x } + | ^^^^^ borrow of layout constrained field with interior mutability + | + = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values + +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints3_match.rs:20:23 + | +LL | match y { NonZero(ref mut y) => { y } }; + | ^^^^^^^^^ 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/src/test/ui/unsafe/ranged_ints4.stderr b/src/test/ui/unsafe/ranged_ints4.mirunsafeck.stderr similarity index 92% rename from src/test/ui/unsafe/ranged_ints4.stderr rename to src/test/ui/unsafe/ranged_ints4.mirunsafeck.stderr index 68c22589d3ff5..493483d2c4540 100644 --- a/src/test/ui/unsafe/ranged_ints4.stderr +++ b/src/test/ui/unsafe/ranged_ints4.mirunsafeck.stderr @@ -1,5 +1,5 @@ error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block - --> $DIR/ranged_ints4.rs:8:5 + --> $DIR/ranged_ints4.rs:11:5 | LL | x.0 = 0; | ^^^^^^^ mutation of layout constrained field diff --git a/src/test/ui/unsafe/ranged_ints4.rs b/src/test/ui/unsafe/ranged_ints4.rs index d8632c48434f2..fe80af454cb8d 100644 --- a/src/test/ui/unsafe/ranged_ints4.rs +++ b/src/test/ui/unsafe/ranged_ints4.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![feature(rustc_attrs)] #[rustc_layout_scalar_valid_range_start(1)] diff --git a/src/test/ui/unsafe/ranged_ints4_const.stderr b/src/test/ui/unsafe/ranged_ints4.thirunsafeck.stderr similarity index 90% rename from src/test/ui/unsafe/ranged_ints4_const.stderr rename to src/test/ui/unsafe/ranged_ints4.thirunsafeck.stderr index fe83b15ce5cec..493483d2c4540 100644 --- a/src/test/ui/unsafe/ranged_ints4_const.stderr +++ b/src/test/ui/unsafe/ranged_ints4.thirunsafeck.stderr @@ -1,5 +1,5 @@ error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block - --> $DIR/ranged_ints4_const.rs:10:5 + --> $DIR/ranged_ints4.rs:11:5 | LL | x.0 = 0; | ^^^^^^^ mutation of layout constrained field diff --git a/src/test/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr new file mode 100644 index 0000000000000..a06c6f479b8da --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr @@ -0,0 +1,11 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints4_const.rs:13:5 + | +LL | x.0 = 0; + | ^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/ranged_ints4_const.rs b/src/test/ui/unsafe/ranged_ints4_const.rs index f09168c3d3f9c..a43c8be71c4fd 100644 --- a/src/test/ui/unsafe/ranged_ints4_const.rs +++ b/src/test/ui/unsafe/ranged_ints4_const.rs @@ -1,3 +1,6 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + #![feature(rustc_attrs)] #[rustc_layout_scalar_valid_range_start(1)] diff --git a/src/test/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr new file mode 100644 index 0000000000000..a06c6f479b8da --- /dev/null +++ b/src/test/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr @@ -0,0 +1,11 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/ranged_ints4_const.rs:13:5 + | +LL | x.0 = 0; + | ^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/unsafe-assign.mirunsafeck.stderr b/src/test/ui/unsafe/unsafe-assign.mirunsafeck.stderr new file mode 100644 index 0000000000000..9abc51424abaf --- /dev/null +++ b/src/test/ui/unsafe/unsafe-assign.mirunsafeck.stderr @@ -0,0 +1,11 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-assign.rs:12:5 + | +LL | foo.0.0 = 0; + | ^^^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/unsafe-assign.rs b/src/test/ui/unsafe/unsafe-assign.rs new file mode 100644 index 0000000000000..15273165b5e13 --- /dev/null +++ b/src/test/ui/unsafe/unsafe-assign.rs @@ -0,0 +1,25 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![feature(rustc_attrs)] +#![allow(unused,dead_code)] + +fn nested_field() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero(T); + + let mut foo = unsafe { NonZero((1,)) }; + foo.0.0 = 0; + //~^ ERROR: mutation of layout constrained field is unsafe +} + +fn block() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero(T); + + let mut foo = unsafe { NonZero((1,)) }; + { foo.0 }.0 = 0; + // ^ not unsafe because the result of the block expression is a new place +} + +fn main() {} diff --git a/src/test/ui/unsafe/unsafe-assign.thirunsafeck.stderr b/src/test/ui/unsafe/unsafe-assign.thirunsafeck.stderr new file mode 100644 index 0000000000000..9abc51424abaf --- /dev/null +++ b/src/test/ui/unsafe/unsafe-assign.thirunsafeck.stderr @@ -0,0 +1,11 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-assign.rs:12:5 + | +LL | foo.0.0 = 0; + | ^^^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/unsafe-borrow.mirunsafeck.stderr b/src/test/ui/unsafe/unsafe-borrow.mirunsafeck.stderr new file mode 100644 index 0000000000000..a206722495ac3 --- /dev/null +++ b/src/test/ui/unsafe/unsafe-borrow.mirunsafeck.stderr @@ -0,0 +1,27 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-borrow.rs:12:13 + | +LL | let a = &mut foo.0.0; + | ^^^^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-borrow.rs:32:13 + | +LL | let a = &mut foo.0[2]; + | ^^^^^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-borrow.rs:51:18 + | +LL | NonZero((a,)) => *a = 0, + | ^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/unsafe/unsafe-borrow.rs b/src/test/ui/unsafe/unsafe-borrow.rs new file mode 100644 index 0000000000000..8dddc70be45c7 --- /dev/null +++ b/src/test/ui/unsafe/unsafe-borrow.rs @@ -0,0 +1,56 @@ +// revisions: mirunsafeck thirunsafeck +// [thirunsafeck]compile-flags: -Z thir-unsafeck + +#![feature(rustc_attrs)] +#![allow(unused,dead_code)] + +fn tuple_struct() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero(T); + + let mut foo = unsafe { NonZero((1,)) }; + let a = &mut foo.0.0; + //~^ ERROR: mutation of layout constrained field is unsafe +} + +fn slice() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero<'a, T>(&'a mut [T]); + + let mut nums = [1, 2, 3, 4]; + let mut foo = unsafe { NonZero(&mut nums[..]) }; + let a = &mut foo.0[2]; + // ^ not unsafe because there is an implicit dereference here +} + +fn array() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero([T; 4]); + + let nums = [1, 2, 3, 4]; + let mut foo = unsafe { NonZero(nums) }; + let a = &mut foo.0[2]; + //~^ ERROR: mutation of layout constrained field is unsafe +} + +fn block() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero(T); + + let foo = unsafe { NonZero((1,)) }; + &mut { foo.0 }.0; + // ^ not unsafe because the result of the block expression is a new place +} + +fn mtch() { + #[rustc_layout_scalar_valid_range_start(1)] + struct NonZero(T); + + let mut foo = unsafe { NonZero((1,)) }; + match &mut foo { + NonZero((a,)) => *a = 0, + //~^ ERROR: mutation of layout constrained field is unsafe + } +} + +fn main() {} diff --git a/src/test/ui/unsafe/unsafe-borrow.thirunsafeck.stderr b/src/test/ui/unsafe/unsafe-borrow.thirunsafeck.stderr new file mode 100644 index 0000000000000..a206722495ac3 --- /dev/null +++ b/src/test/ui/unsafe/unsafe-borrow.thirunsafeck.stderr @@ -0,0 +1,27 @@ +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-borrow.rs:12:13 + | +LL | let a = &mut foo.0.0; + | ^^^^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-borrow.rs:32:13 + | +LL | let a = &mut foo.0[2]; + | ^^^^^^^^^^^^^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block + --> $DIR/unsafe-borrow.rs:51:18 + | +LL | NonZero((a,)) => *a = 0, + | ^ mutation of layout constrained field + | + = note: mutating layout constrained fields cannot statically be checked for valid values + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0133`.