From 3a19fbf95d3b289f4c17aba910051cd9afd75887 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 23 Dec 2018 19:00:58 +0000 Subject: [PATCH 1/8] Add Rvalue::AddressOf to MIR This operator creates a raw pointer to a Place directly, without first creating a reference. See RFC #2582 for motivation. The Rvalue is currently unused. --- src/librustc/mir/mod.rs | 18 +++ src/librustc/mir/tcx.rs | 7 ++ src/librustc/mir/visit.rs | 16 +++ src/librustc/ty/cast.rs | 3 - src/librustc_codegen_ssa/mir/analyze.rs | 2 + src/librustc_codegen_ssa/mir/place.rs | 2 +- src/librustc_codegen_ssa/mir/rvalue.rs | 58 +++++---- src/librustc_mir/borrow_check/invalidation.rs | 18 ++- src/librustc_mir/borrow_check/mod.rs | 25 ++++ .../borrow_check/type_check/mod.rs | 49 ++------ .../dataflow/move_paths/builder.rs | 1 + src/librustc_mir/interpret/step.rs | 2 +- src/librustc_mir/transform/add_retag.rs | 18 +-- .../transform/check_consts/ops.rs | 17 +++ .../transform/check_consts/qualifs.rs | 18 ++- .../transform/check_consts/validation.rs | 112 +++++++++++------- src/librustc_mir/transform/promote_consts.rs | 24 +++- .../transform/qualify_min_const_fn.rs | 8 +- src/librustc_mir/util/liveness.rs | 2 + src/librustc_typeck/check/cast.rs | 76 ++++++------ 20 files changed, 307 insertions(+), 169 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index ba8feb4ee739d..3b4adbaf78c74 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2060,6 +2060,11 @@ pub enum Rvalue<'tcx> { /// &x or &mut x Ref(Region<'tcx>, BorrowKind, Place<'tcx>), + /// Create a raw pointer to the given place + /// Can be generated by raw address of expressions (`&raw const x`), + /// or when casting a reference to a raw pointer. + AddressOf(Mutability, Place<'tcx>), + /// length of a [X] or [X;n] value Len(Place<'tcx>), @@ -2214,6 +2219,15 @@ impl<'tcx> Debug for Rvalue<'tcx> { write!(fmt, "&{}{}{:?}", region, kind_str, place) } + AddressOf(mutability, ref place) => { + let kind_str = match mutability { + Mutability::Mut => "mut", + Mutability::Not => "const", + }; + + write!(fmt, "&raw {} {:?}", kind_str, place) + } + Aggregate(ref kind, ref places) => { fn fmt_tuple(fmt: &mut Formatter<'_>, places: &[Operand<'_>]) -> fmt::Result { let mut tuple_fmt = fmt.debug_tuple(""); @@ -3085,6 +3099,9 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { Ref(region, bk, ref place) => { Ref(region.fold_with(folder), bk, place.fold_with(folder)) } + AddressOf(mutability, ref place) => { + AddressOf(mutability, place.fold_with(folder)) + } Len(ref place) => Len(place.fold_with(folder)), Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)), BinaryOp(op, ref rhs, ref lhs) => { @@ -3125,6 +3142,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { Use(ref op) => op.visit_with(visitor), Repeat(ref op, _) => op.visit_with(visitor), Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor), + AddressOf(_, ref place) => place.visit_with(visitor), Len(ref place) => place.visit_with(visitor), Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor), BinaryOp(_, ref rhs, ref lhs) | CheckedBinaryOp(_, ref rhs, ref lhs) => { diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 445fa6ea8cab3..a24b1d863d644 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -172,6 +172,13 @@ impl<'tcx> Rvalue<'tcx> { } ) } + Rvalue::AddressOf(mutability, ref place) => { + let place_ty = place.ty(local_decls, tcx).ty; + tcx.mk_ptr(ty::TypeAndMut { + ty: place_ty, + mutbl: mutability.into(), + }) + } Rvalue::Len(..) => tcx.types.usize, Rvalue::Cast(.., ty) => ty, Rvalue::BinaryOp(op, ref lhs, ref rhs) => { diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 5d273fe85b6d2..fa96b51347d35 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -570,6 +570,18 @@ macro_rules! make_mir_visitor { self.visit_place(path, ctx, location); } + Rvalue::AddressOf(m, path) => { + let ctx = match m { + Mutability::Mut => PlaceContext::MutatingUse( + MutatingUseContext::AddressOf + ), + Mutability::Not => PlaceContext::NonMutatingUse( + NonMutatingUseContext::AddressOf + ), + }; + self.visit_place(path, ctx, location); + } + Rvalue::Len(path) => { self.visit_place( path, @@ -1031,6 +1043,8 @@ pub enum NonMutatingUseContext { ShallowBorrow, /// Unique borrow. UniqueBorrow, + /// AddressOf for *const pointer. + AddressOf, /// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place. /// For example, the projection `x.y` is not marked as a mutation in these cases: /// @@ -1054,6 +1068,8 @@ pub enum MutatingUseContext { Drop, /// Mutable borrow. Borrow, + /// AddressOf for *mut pointer. + AddressOf, /// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place. /// For example, the projection `x.y` is marked as a mutation in these cases: /// diff --git a/src/librustc/ty/cast.rs b/src/librustc/ty/cast.rs index bc12412312deb..fca53db1475a0 100644 --- a/src/librustc/ty/cast.rs +++ b/src/librustc/ty/cast.rs @@ -28,8 +28,6 @@ pub enum CastTy<'tcx> { FnPtr, /// Raw pointers Ptr(ty::TypeAndMut<'tcx>), - /// References - RPtr(ty::TypeAndMut<'tcx>), } /// Cast Kind. See RFC 401 (or librustc_typeck/check/cast.rs) @@ -63,7 +61,6 @@ impl<'tcx> CastTy<'tcx> { ty::Adt(d,_) if d.is_enum() && d.is_payloadfree() => Some(CastTy::Int(IntTy::CEnum)), ty::RawPtr(mt) => Some(CastTy::Ptr(mt)), - ty::Ref(_, ty, mutbl) => Some(CastTy::RPtr(ty::TypeAndMut { ty, mutbl })), ty::FnPtr(..) => Some(CastTy::FnPtr), _ => None, } diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 6c627085b2ed8..7bcd981678640 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -340,10 +340,12 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> PlaceContext::MutatingUse(MutatingUseContext::Store) | PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) | PlaceContext::MutatingUse(MutatingUseContext::Borrow) | + PlaceContext::MutatingUse(MutatingUseContext::AddressOf) | PlaceContext::MutatingUse(MutatingUseContext::Projection) | PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) | PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow) | PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) => { self.not_ssa(local); } diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 5e13cabced000..5b21dfbdf1c69 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -448,7 +448,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let cx = self.cx; let tcx = self.cx.tcx(); - let result = match &place_ref { + let result = match place_ref { mir::PlaceRef { base: mir::PlaceBase::Local(index), projection: [], diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 488ae8dbf9036..3a8d782aa7308 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -7,7 +7,7 @@ use crate::MemFlags; use crate::common::{self, RealPredicate, IntPredicate}; use crate::traits::*; -use rustc::ty::{self, Ty, adjustment::{PointerCast}, Instance}; +use rustc::ty::{self, Ty, TyCtxt, adjustment::{PointerCast}, Instance}; use rustc::ty::cast::{CastTy, IntTy}; use rustc::ty::layout::{self, LayoutOf, HasTyCtxt}; use rustc::mir; @@ -342,8 +342,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } (CastTy::Ptr(_), CastTy::Ptr(_)) | - (CastTy::FnPtr, CastTy::Ptr(_)) | - (CastTy::RPtr(_), CastTy::Ptr(_)) => + (CastTy::FnPtr, CastTy::Ptr(_)) => bx.pointercast(llval, ll_t_out), (CastTy::Ptr(_), CastTy::Int(_)) | (CastTy::FnPtr, CastTy::Int(_)) => @@ -370,24 +369,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::Rvalue::Ref(_, bk, ref place) => { - let cg_place = self.codegen_place(&mut bx, &place.as_ref()); - - let ty = cg_place.layout.ty; + let mk_ref = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| tcx.mk_ref( + tcx.lifetimes.re_erased, + ty::TypeAndMut { ty, mutbl: bk.to_mutbl_lossy() } + ); + self.codegen_place_to_pointer(bx, place, mk_ref) + } - // Note: places are indirect, so storing the `llval` into the - // destination effectively creates a reference. - let val = if !bx.cx().type_has_metadata(ty) { - OperandValue::Immediate(cg_place.llval) - } else { - OperandValue::Pair(cg_place.llval, cg_place.llextra.unwrap()) - }; - (bx, OperandRef { - val, - layout: self.cx.layout_of(self.cx.tcx().mk_ref( - self.cx.tcx().lifetimes.re_erased, - ty::TypeAndMut { ty, mutbl: bk.to_mutbl_lossy() } - )), - }) + mir::Rvalue::AddressOf(mutability, ref place) => { + let mk_ptr = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| tcx.mk_ptr( + ty::TypeAndMut { ty, mutbl: mutability.into() } + ); + self.codegen_place_to_pointer(bx, place, mk_ptr) } mir::Rvalue::Len(ref place) => { @@ -543,6 +536,30 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { cg_value.len(bx.cx()) } + /// Codegen an `Rvalue::AddressOf` or `Rvalue::Ref` + fn codegen_place_to_pointer( + &mut self, + mut bx: Bx, + place: &mir::Place<'tcx>, + mk_ptr_ty: impl FnOnce(TyCtxt<'tcx>, Ty<'tcx>) -> Ty<'tcx>, + ) -> (Bx, OperandRef<'tcx, Bx::Value>) { + let cg_place = self.codegen_place(&mut bx, &place.as_ref()); + + let ty = cg_place.layout.ty; + + // Note: places are indirect, so storing the `llval` into the + // destination effectively creates a reference. + let val = if !bx.cx().type_has_metadata(ty) { + OperandValue::Immediate(cg_place.llval) + } else { + OperandValue::Pair(cg_place.llval, cg_place.llextra.unwrap()) + }; + (bx, OperandRef { + val, + layout: self.cx.layout_of(mk_ptr_ty(self.cx.tcx(), ty)), + }) + } + pub fn codegen_scalar_binop( &mut self, bx: &mut Bx, @@ -699,6 +716,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>, span: Span) -> bool { match *rvalue { mir::Rvalue::Ref(..) | + mir::Rvalue::AddressOf(..) | mir::Rvalue::Len(..) | mir::Rvalue::Cast(..) | // (*) mir::Rvalue::BinaryOp(..) | diff --git a/src/librustc_mir/borrow_check/invalidation.rs b/src/librustc_mir/borrow_check/invalidation.rs index 58fac5512d9b6..d5b9aaf9511a1 100644 --- a/src/librustc_mir/borrow_check/invalidation.rs +++ b/src/librustc_mir/borrow_check/invalidation.rs @@ -3,7 +3,7 @@ use rustc::mir::visit::Visitor; use rustc::mir::{BasicBlock, Location, Body, Place, ReadOnlyBodyAndCache, Rvalue}; use rustc::mir::{Statement, StatementKind}; use rustc::mir::TerminatorKind; -use rustc::mir::{Operand, BorrowKind}; +use rustc::mir::{Operand, BorrowKind, Mutability}; use rustc_data_structures::graph::dominators::Dominators; use crate::dataflow::indexes::BorrowIndex; @@ -337,6 +337,22 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { ); } + Rvalue::AddressOf(mutability, ref place) => { + let access_kind = match mutability { + Mutability::Mut => (Deep, Write(WriteKind::MutableBorrow(BorrowKind::Mut { + allow_two_phase_borrow: false, + }))), + Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))), + }; + + self.access_place( + location, + place, + access_kind, + LocalMutationIsAllowed::No, + ); + } + Rvalue::Use(ref operand) | Rvalue::Repeat(ref operand, _) | Rvalue::UnaryOp(_ /*un_op*/, ref operand) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 11012ef2fc7ee..2554d5e729da9 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1233,6 +1233,31 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); } + + Rvalue::AddressOf(mutability, ref place) => { + let access_kind = match mutability { + Mutability::Mut => (Deep, Write(WriteKind::MutableBorrow(BorrowKind::Mut { + allow_two_phase_borrow: false, + }))), + Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))), + }; + + self.access_place( + location, + (place, span), + access_kind, + LocalMutationIsAllowed::No, + flow_state, + ); + + self.check_if_path_or_subpath_is_moved( + location, + InitializationRequiringAction::Borrow, + (place.as_ref(), span), + flow_state, + ); + } + Rvalue::Use(ref operand) | Rvalue::Repeat(ref operand, _) | Rvalue::UnaryOp(_ /*un_op*/, ref operand) diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 663536bc2b4b6..108279eeef492 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -2273,41 +2273,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let cast_ty_from = CastTy::from_ty(ty_from); let cast_ty_to = CastTy::from_ty(ty); match (cast_ty_from, cast_ty_to) { - (Some(CastTy::RPtr(ref_tm)), Some(CastTy::Ptr(ptr_tm))) => { - if let hir::Mutability::Mutable = ptr_tm.mutbl { - if let Err(terr) = self.eq_types( - ref_tm.ty, - ptr_tm.ty, - location.to_locations(), - ConstraintCategory::Cast, - ) { - span_mirbug!( - self, - rvalue, - "equating {:?} with {:?} yields {:?}", - ref_tm.ty, - ptr_tm.ty, - terr - ) - } - } else { - if let Err(terr) = self.sub_types( - ref_tm.ty, - ptr_tm.ty, - location.to_locations(), - ConstraintCategory::Cast, - ) { - span_mirbug!( - self, - rvalue, - "relating {:?} with {:?} yields {:?}", - ref_tm.ty, - ptr_tm.ty, - terr - ) - } - } - }, (None, _) | (_, None) | (_, Some(CastTy::FnPtr)) @@ -2320,7 +2285,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ty_from, ty, ), - _ => (), + (Some(CastTy::Int(_)), Some(CastTy::Int(_))) + | (Some(CastTy::Float), Some(CastTy::Int(_))) + | (Some(CastTy::Int(_)), Some(CastTy::Float)) + | (Some(CastTy::Float), Some(CastTy::Float)) + | (Some(CastTy::Ptr(_)), Some(CastTy::Int(_))) + | (Some(CastTy::FnPtr), Some(CastTy::Int(_))) + | (Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) + | (Some(CastTy::Ptr(_)), Some(CastTy::Ptr(_))) + | (Some(CastTy::FnPtr), Some(CastTy::Ptr(_))) => (), } } } @@ -2371,7 +2344,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } - Rvalue::Use(..) + Rvalue::AddressOf(..) + | Rvalue::Use(..) | Rvalue::Len(..) | Rvalue::BinaryOp(..) | Rvalue::CheckedBinaryOp(..) @@ -2388,6 +2362,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Rvalue::Use(_) | Rvalue::Repeat(..) | Rvalue::Ref(..) + | Rvalue::AddressOf(..) | Rvalue::Len(..) | Rvalue::Cast(..) | Rvalue::BinaryOp(..) diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index fa0864e0de760..5522da6fbf085 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -335,6 +335,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { } } Rvalue::Ref(..) + | Rvalue::AddressOf(..) | Rvalue::Discriminant(..) | Rvalue::Len(..) | Rvalue::NullaryOp(NullOp::SizeOf, _) diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index 33ed69af6ba02..33cdf1b27f8db 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -248,7 +248,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { )?; } - Ref(_, _, ref place) => { + AddressOf(_, ref place) | Ref(_, _, ref place) => { let src = self.eval_place(place)?; let place = self.force_allocation(src)?; if place.layout.size.bytes() > 0 { diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs index dc21c674eea2f..0e4fe3f7f4015 100644 --- a/src/librustc_mir/transform/add_retag.rs +++ b/src/librustc_mir/transform/add_retag.rs @@ -136,21 +136,9 @@ impl<'tcx> MirPass<'tcx> for AddRetag { // iterate backwards using indices. for i in (0..block_data.statements.len()).rev() { let (retag_kind, place) = match block_data.statements[i].kind { - // If we are casting *from* a reference, we may have to retag-as-raw. - StatementKind::Assign(box(ref place, Rvalue::Cast( - CastKind::Misc, - ref src, - dest_ty, - ))) => { - let src_ty = src.ty(&*local_decls, tcx); - if src_ty.is_region_ptr() { - // The only `Misc` casts on references are those creating raw pointers. - assert!(dest_ty.is_unsafe_ptr()); - (RetagKind::Raw, place.clone()) - } else { - // Some other cast, no retag - continue - } + // Retag-as-raw after escaping to a raw pointer. + StatementKind::Assign(box (ref place, Rvalue::AddressOf(..))) => { + (RetagKind::Raw, place.clone()) } // Assignments of reference or ptr type are the ones where we may have // to update tags. This includes `x = &[mut] ...` and hence diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs index 3df60993d9ad5..e5f3003cd7110 100644 --- a/src/librustc_mir/transform/check_consts/ops.rs +++ b/src/librustc_mir/transform/check_consts/ops.rs @@ -224,6 +224,23 @@ impl NonConstOp for MutBorrow { } } +#[derive(Debug)] +pub struct MutAddressOf; +impl NonConstOp for MutAddressOf { + fn feature_gate(tcx: TyCtxt<'_>) -> Option { + Some(tcx.features().const_mut_refs) + } + + fn emit_error(&self, item: &Item<'_, '_>, span: Span) { + feature_err( + &item.tcx.sess.parse_sess, + sym::const_mut_refs, + span, + &format!("`&raw mut` is not allowed in {}s", item.const_kind()) + ).emit(); + } +} + #[derive(Debug)] pub struct MutDeref; impl NonConstOp for MutDeref { diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs index 223a5f8d605fc..28243bd71a228 100644 --- a/src/librustc_mir/transform/check_consts/qualifs.rs +++ b/src/librustc_mir/transform/check_consts/qualifs.rs @@ -151,17 +151,15 @@ pub trait Qualif { Self::in_operand(cx, per_local, lhs) || Self::in_operand(cx, per_local, rhs) } - Rvalue::Ref(_, _, ref place) => { + Rvalue::Ref(_, _, ref place) | Rvalue::AddressOf(_, ref place) => { // Special-case reborrows to be more like a copy of the reference. - if let &[ref proj_base @ .., elem] = place.projection.as_ref() { - if ProjectionElem::Deref == elem { - let base_ty = Place::ty_from(&place.base, proj_base, *cx.body, cx.tcx).ty; - if let ty::Ref(..) = base_ty.kind { - return Self::in_place(cx, per_local, PlaceRef { - base: &place.base, - projection: proj_base, - }); - } + if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() { + let base_ty = Place::ty_from(&place.base, proj_base, *cx.body, cx.tcx).ty; + if let ty::Ref(..) = base_ty.kind { + return Self::in_place(cx, per_local, PlaceRef { + base: &place.base, + projection: proj_base, + }); } } diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index 6261315c711cd..0904264586c7c 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -276,6 +276,27 @@ impl Validator<'a, 'mir, 'tcx> { self.check_op_spanned(ops::StaticAccess, span) } } + + fn check_immutable_borrow_like( + &mut self, + location: Location, + place: &Place<'tcx>, + ) { + // FIXME: Change the `in_*` methods to take a `FnMut` so we don't have to manually + // seek the cursors beforehand. + self.qualifs.has_mut_interior.cursor.seek_before(location); + self.qualifs.indirectly_mutable.seek(location); + + let borrowed_place_has_mut_interior = HasMutInterior::in_place( + &self.item, + &|local| self.qualifs.has_mut_interior_eager_seek(local), + place.as_ref(), + ); + + if borrowed_place_has_mut_interior { + self.check_op(ops::CellBorrow); + } + } } impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { @@ -302,26 +323,44 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { trace!("visit_rvalue: rvalue={:?} location={:?}", rvalue, location); // Special-case reborrows to be more like a copy of a reference. - if let Rvalue::Ref(_, kind, ref place) = *rvalue { - if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, *self.body, place) { - let ctx = match kind { - BorrowKind::Shared => PlaceContext::NonMutatingUse( - NonMutatingUseContext::SharedBorrow, - ), - BorrowKind::Shallow => PlaceContext::NonMutatingUse( - NonMutatingUseContext::ShallowBorrow, - ), - BorrowKind::Unique => PlaceContext::NonMutatingUse( - NonMutatingUseContext::UniqueBorrow, - ), - BorrowKind::Mut { .. } => PlaceContext::MutatingUse( - MutatingUseContext::Borrow, - ), - }; - self.visit_place_base(&place.base, ctx, location); - self.visit_projection(&place.base, reborrowed_proj, ctx, location); - return; + match *rvalue { + Rvalue::Ref(_, kind, ref place) => { + if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, *self.body, place) { + let ctx = match kind { + BorrowKind::Shared => PlaceContext::NonMutatingUse( + NonMutatingUseContext::SharedBorrow, + ), + BorrowKind::Shallow => PlaceContext::NonMutatingUse( + NonMutatingUseContext::ShallowBorrow, + ), + BorrowKind::Unique => PlaceContext::NonMutatingUse( + NonMutatingUseContext::UniqueBorrow, + ), + BorrowKind::Mut { .. } => PlaceContext::MutatingUse( + MutatingUseContext::Borrow, + ), + }; + self.visit_place_base(&place.base, ctx, location); + self.visit_projection(&place.base, reborrowed_proj, ctx, location); + return; + } } + Rvalue::AddressOf(mutbl, ref place) => { + if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, *self.body, place) { + let ctx = match mutbl { + Mutability::Not => PlaceContext::NonMutatingUse( + NonMutatingUseContext::AddressOf, + ), + Mutability::Mut => PlaceContext::MutatingUse( + MutatingUseContext::AddressOf, + ), + }; + self.visit_place_base(&place.base, ctx, location); + self.visit_projection(&place.base, reborrowed_proj, ctx, location); + return; + } + } + _ => {} } self.super_rvalue(rvalue, location); @@ -367,34 +406,25 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { } } + Rvalue::AddressOf(Mutability::Mut, _) => { + self.check_op(ops::MutAddressOf) + } + // At the moment, `PlaceBase::Static` is only used for promoted MIR. | Rvalue::Ref(_, BorrowKind::Shared, ref place) | Rvalue::Ref(_, BorrowKind::Shallow, ref place) + | Rvalue::AddressOf(Mutability::Not, ref place) if matches!(place.base, PlaceBase::Static(_)) => bug!("Saw a promoted during const-checking, which must run before promotion"), - | Rvalue::Ref(_, kind @ BorrowKind::Shared, ref place) - | Rvalue::Ref(_, kind @ BorrowKind::Shallow, ref place) - => { - // FIXME: Change the `in_*` methods to take a `FnMut` so we don't have to manually - // seek the cursors beforehand. - self.qualifs.has_mut_interior.cursor.seek_before(location); - self.qualifs.indirectly_mutable.seek(location); - - let borrowed_place_has_mut_interior = HasMutInterior::in_place( - &self.item, - &|local| self.qualifs.has_mut_interior_eager_seek(local), - place.as_ref(), - ); - - if borrowed_place_has_mut_interior { - if let BorrowKind::Mut{ .. } = kind { - self.check_op(ops::MutBorrow); - } else { - self.check_op(ops::CellBorrow); - } - } - } + | Rvalue::Ref(_, BorrowKind::Shared, ref place) + | Rvalue::Ref(_, BorrowKind::Shallow, ref place) => { + self.check_immutable_borrow_like(location, place) + }, + + Rvalue::AddressOf(Mutability::Not, ref place) => { + self.check_immutable_borrow_like(location, place) + }, Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) => { let operand_ty = operand.ty(*self.body, self.tcx); diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 4c723199102be..4e5d8ae08fe5b 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -196,7 +196,12 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> { } else if let TempState::Defined { ref mut uses, .. } = *temp { // We always allow borrows, even mutable ones, as we need // to promote mutable borrows of some ZSTs e.g., `&mut []`. - let allowed_use = context.is_borrow() || context.is_nonmutating_use(); + let allowed_use = match context { + PlaceContext::MutatingUse(MutatingUseContext::Borrow) + | PlaceContext::NonMutatingUse(_) => true, + PlaceContext::MutatingUse(_) + | PlaceContext::NonUse(_) => false, + }; debug!("visit_local: allowed_use={:?}", allowed_use); if allowed_use { *uses += 1; @@ -618,6 +623,21 @@ impl<'tcx> Validator<'_, 'tcx> { self.validate_operand(rhs) } + Rvalue::AddressOf(_, place) => { + // Raw reborrows can come from reference to pointer coercions, + // so are allowed. + if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() { + let base_ty = Place::ty_from(&place.base, proj_base, *self.body, self.tcx).ty; + if let ty::Ref(..) = base_ty.kind { + return self.validate_place(PlaceRef { + base: &place.base, + projection: proj_base, + }); + } + } + Err(Unpromotable) + } + Rvalue::Ref(_, kind, place) => { if let BorrowKind::Mut { .. } = kind { let ty = place.ty(*self.body, self.tcx).ty; @@ -950,7 +970,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { Candidate::Ref(loc) => { let ref mut statement = blocks[loc.block].statements[loc.statement_index]; match statement.kind { - StatementKind::Assign(box(_, Rvalue::Ref(_, _, ref mut place))) => { + StatementKind::Assign(box (_, Rvalue::Ref(_, _, ref mut place))) => { // Use the underlying local for this (necessarily interior) borrow. let ty = place.base.ty(local_decls).ty; let span = statement.source_info.span; diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index e2530795749a9..a61bff37fc873 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -135,7 +135,10 @@ fn check_rvalue( Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => { check_operand(tcx, operand, span, def_id, body) } - Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) => { + Rvalue::Len(place) + | Rvalue::Discriminant(place) + | Rvalue::Ref(_, _, place) + | Rvalue::AddressOf(_, place) => { check_place(tcx, place, span, def_id, body) } Rvalue::Cast(CastKind::Misc, operand, cast_ty) => { @@ -147,9 +150,6 @@ fn check_rvalue( span, "casting pointers to ints is unstable in const fn".into(), )), - (CastTy::RPtr(_), CastTy::Float) => bug!(), - (CastTy::RPtr(_), CastTy::Int(_)) => bug!(), - (CastTy::Ptr(_), CastTy::RPtr(_)) => bug!(), _ => check_operand(tcx, operand, span, def_id, body), } } diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 68c2e16399a59..01eebeb8c55a5 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -167,6 +167,8 @@ pub fn categorize(context: PlaceContext) -> Option { PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) | PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow) | + PlaceContext::MutatingUse(MutatingUseContext::AddressOf) | + PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) | diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 035ece238104f..21ba02746c79e 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -469,22 +469,48 @@ impl<'a, 'tcx> CastCheck<'tcx> { (Some(t_from), Some(t_cast)) => (t_from, t_cast), // Function item types may need to be reified before casts. (None, Some(t_cast)) => { - if let ty::FnDef(..) = self.expr_ty.kind { - // Attempt a coercion to a fn pointer type. - let f = self.expr_ty.fn_sig(fcx.tcx); - let res = fcx.try_coerce(self.expr, - self.expr_ty, - fcx.tcx.mk_fn_ptr(f), - AllowTwoPhase::No); - if let Err(TypeError::IntrinsicCast) = res { - return Err(CastError::IllegalCast); + match self.expr_ty.kind { + ty::FnDef(..) => { + // Attempt a coercion to a fn pointer type. + let f = self.expr_ty.fn_sig(fcx.tcx); + let res = fcx.try_coerce(self.expr, + self.expr_ty, + fcx.tcx.mk_fn_ptr(f), + AllowTwoPhase::No); + if let Err(TypeError::IntrinsicCast) = res { + return Err(CastError::IllegalCast); + } + if res.is_err() { + return Err(CastError::NonScalar); + } + (FnPtr, t_cast) } - if res.is_err() { - return Err(CastError::NonScalar); + // Special case some errors for references, and check for + // array-ptr-casts. `Ref` is not a CastTy because the cast + // is split into a coercion to a pointer type, followed by + // a cast. + ty::Ref(_, inner_ty, mutbl) => { + return match t_cast { + Int(_) | Float => match inner_ty.kind { + ty::Int(_) | + ty::Uint(_) | + ty::Float(_) | + ty::Infer(ty::InferTy::IntVar(_)) | + ty::Infer(ty::InferTy::FloatVar(_)) => { + Err(CastError::NeedDeref) + } + _ => Err(CastError::NeedViaPtr), + } + // array-ptr-cast + Ptr(mt) => self.check_ref_cast( + fcx, + TypeAndMut { mutbl, ty: inner_ty }, + mt, + ), + _ => Err(CastError::NonScalar), + }; } - (FnPtr, t_cast) - } else { - return Err(CastError::NonScalar); + _ => return Err(CastError::NonScalar), } } _ => return Err(CastError::NonScalar), @@ -492,7 +518,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { match (t_from, t_cast) { // These types have invariants! can't cast into them. - (_, RPtr(_)) | (_, Int(CEnum)) | (_, FnPtr) => Err(CastError::NonScalar), + (_, Int(CEnum)) | (_, FnPtr) => Err(CastError::NonScalar), // * -> Bool (_, Int(Bool)) => Err(CastError::CastToBool), @@ -517,28 +543,10 @@ impl<'a, 'tcx> CastCheck<'tcx> { (Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast (Ptr(m_expr), Int(_)) => self.check_ptr_addr_cast(fcx, m_expr), // ptr-addr-cast (FnPtr, Int(_)) => Ok(CastKind::FnPtrAddrCast), - (RPtr(p), Int(_)) | - (RPtr(p), Float) => { - match p.ty.kind { - ty::Int(_) | - ty::Uint(_) | - ty::Float(_) => { - Err(CastError::NeedDeref) - } - ty::Infer(t) => { - match t { - ty::InferTy::IntVar(_) | - ty::InferTy::FloatVar(_) => Err(CastError::NeedDeref), - _ => Err(CastError::NeedViaPtr), - } - } - _ => Err(CastError::NeedViaPtr), - } - } + // * -> ptr (Int(_), Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt), // addr-ptr-cast (FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt), - (RPtr(rmt), Ptr(mt)) => self.check_ref_cast(fcx, rmt, mt), // array-ptr-cast // prim -> prim (Int(CEnum), Int(_)) => Ok(CastKind::EnumCast), From 35919ace7084e10fce15cb9bb42a9404b63b849d Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 20 Apr 2019 18:06:03 +0100 Subject: [PATCH 2/8] Start generating AddressOf rvalues in MIR `hir::BorrowKind::Raw` borrows and casting a reference to a raw pointer no longer do a reborrow followed by a cast. Instead we dereference and take the address. --- src/librustc_mir/build/expr/as_place.rs | 1 + src/librustc_mir/build/expr/as_rvalue.rs | 1 + src/librustc_mir/build/expr/category.rs | 1 + src/librustc_mir/build/expr/into.rs | 18 ++++ src/librustc_mir/hair/cx/expr.rs | 84 +++---------------- src/librustc_mir/hair/mod.rs | 5 ++ src/test/mir-opt/array-index-is-temporary.rs | 19 ++--- .../const_prop/const_prop_fails_gracefully.rs | 18 ++-- src/test/mir-opt/retag.rs | 10 +-- src/test/ui/cast/cast-as-bool.rs | 2 +- src/test/ui/cast/cast-as-bool.stderr | 7 +- 11 files changed, 61 insertions(+), 105 deletions(-) diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index ddacda72e1e65..15c7c92d7db51 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -276,6 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::Pointer { .. } | ExprKind::Repeat { .. } | ExprKind::Borrow { .. } + | ExprKind::AddressOf { .. } | ExprKind::Match { .. } | ExprKind::Loop { .. } | ExprKind::Block { .. } diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 37eb0cc9d961e..24282a6617acf 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -276,6 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::NeverToAny { .. } | ExprKind::Use { .. } | ExprKind::Borrow { .. } + | ExprKind::AddressOf { .. } | ExprKind::Adt { .. } | ExprKind::Loop { .. } | ExprKind::LogicalOp { .. } diff --git a/src/librustc_mir/build/expr/category.rs b/src/librustc_mir/build/expr/category.rs index 270a1a6447435..4d0039b2e8cec 100644 --- a/src/librustc_mir/build/expr/category.rs +++ b/src/librustc_mir/build/expr/category.rs @@ -49,6 +49,7 @@ impl Category { | ExprKind::Use { .. } | ExprKind::Adt { .. } | ExprKind::Borrow { .. } + | ExprKind::AddressOf { .. } | ExprKind::Call { .. } => Some(Category::Rvalue(RvalueFunc::Into)), ExprKind::Array { .. } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 07a44b190b20a..6b33e8433f673 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -3,6 +3,7 @@ use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use crate::hair::*; +use rustc::hir; use rustc::mir::*; use rustc::ty::{self, CanonicalUserTypeAnnotation}; use rustc_data_structures::fx::FxHashMap; @@ -295,6 +296,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.cfg.push_assign(block, source_info, destination, borrow); block.unit() } + ExprKind::AddressOf { + mutability, + arg, + } => { + let address_of = match mutability { + hir::Mutability::Immutable => Rvalue::AddressOf( + Mutability::Not, + unpack!(block = this.as_read_only_place(block, arg)), + ), + hir::Mutability::Mutable => Rvalue::AddressOf( + Mutability::Mut, + unpack!(block = this.as_place(block, arg)), + ), + }; + this.cfg.push_assign(block, source_info, destination, address_of); + block.unit() + } ExprKind::Adt { adt_def, variant_index, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 8c852854be1f9..6cbc25aa7356e 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -137,8 +137,11 @@ fn apply_adjustment<'a, 'tcx>( arg: expr.to_ref(), } } - Adjust::Borrow(AutoBorrow::RawPtr(mutbl)) => { - raw_ref_shim(cx, expr.to_ref(), adjustment.target, mutbl, span, temp_lifetime) + Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => { + ExprKind::AddressOf { + mutability, + arg: expr.to_ref(), + } } }; @@ -262,17 +265,11 @@ fn make_mirror_unadjusted<'a, 'tcx>( } } - hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutbl, ref arg) => { - cx.tcx.sess - .struct_span_err( - expr.span, - "raw borrows are not yet implemented" - ) - .note("for more information, see https://github.com/rust-lang/rust/issues/64490") - .emit(); - - // Lower to an approximation to avoid further errors. - raw_ref_shim(cx, arg.to_ref(), expr_ty, mutbl, expr.span, temp_lifetime) + hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, ref arg) => { + ExprKind::AddressOf { + mutability, + arg: arg.to_ref(), + } } hir::ExprKind::Block(ref blk, _) => ExprKind::Block { body: &blk }, @@ -1082,67 +1079,6 @@ fn convert_var( } -/// Fake `&raw [mut|const] expr` using a borrow and a cast until `AddressOf` -/// exists in MIR. -fn raw_ref_shim<'tcx>( - cx: &mut Cx<'_, 'tcx>, - arg: ExprRef<'tcx>, - ty: Ty<'tcx>, - mutbl: hir::Mutability, - span: Span, - temp_lifetime: Option, -) -> ExprKind<'tcx> { - let arg_tm = if let ty::RawPtr(type_mutbl) = ty.kind { - type_mutbl - } else { - bug!("raw_ref_shim called with non-raw pointer type"); - }; - // Convert this to a suitable `&foo` and - // then an unsafe coercion. - let borrow_expr = Expr { - temp_lifetime, - ty: cx.tcx.mk_ref(cx.tcx.lifetimes.re_erased, arg_tm), - span, - kind: ExprKind::Borrow { - borrow_kind: mutbl.to_borrow_kind(), - arg, - }, - }; - let cast_expr = Expr { - temp_lifetime, - ty, - span, - kind: ExprKind::Cast { source: borrow_expr.to_ref() } - }; - - // To ensure that both implicit and explicit coercions are - // handled the same way, we insert an extra layer of indirection here. - // For explicit casts (e.g., 'foo as *const T'), the source of the 'Use' - // will be an ExprKind::Hair with the appropriate cast expression. Here, - // we make our Use source the generated Cast from the original coercion. - // - // In both cases, this outer 'Use' ensures that the inner 'Cast' is handled by - // as_operand, not by as_rvalue - causing the cast result to be stored in a temporary. - // Ordinary, this is identical to using the cast directly as an rvalue. However, if the - // source of the cast was previously borrowed as mutable, storing the cast in a - // temporary gives the source a chance to expire before the cast is used. For - // structs with a self-referential *mut ptr, this allows assignment to work as - // expected. - // - // For example, consider the type 'struct Foo { field: *mut Foo }', - // The method 'fn bar(&mut self) { self.field = self }' - // triggers a coercion from '&mut self' to '*mut self'. In order - // for the assignment to be valid, the implicit borrow - // of 'self' involved in the coercion needs to end before the local - // containing the '*mut T' is assigned to 'self.field' - otherwise, - // we end up trying to assign to 'self.field' while we have another mutable borrow - // active. - // - // We only need to worry about this kind of thing for coercions from refs to ptrs, - // since they get rid of a borrow implicitly. - ExprKind::Use { source: cast_expr.to_ref() } -} - fn bin_op(op: hir::BinOpKind) -> BinOp { match op { hir::BinOpKind::Add => BinOp::Add, diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 47644d9ba8372..46e0d2a17b32d 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -212,6 +212,11 @@ pub enum ExprKind<'tcx> { borrow_kind: BorrowKind, arg: ExprRef<'tcx>, }, + /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`. + AddressOf { + mutability: hir::Mutability, + arg: ExprRef<'tcx>, + }, Break { label: region::Scope, value: Option>, diff --git a/src/test/mir-opt/array-index-is-temporary.rs b/src/test/mir-opt/array-index-is-temporary.rs index 00a6b26d0cf22..096f98bade25a 100644 --- a/src/test/mir-opt/array-index-is-temporary.rs +++ b/src/test/mir-opt/array-index-is-temporary.rs @@ -18,24 +18,23 @@ fn main() { // START rustc.main.EraseRegions.after.mir // bb0: { // ... -// _5 = &mut _2; -// _4 = &mut (*_5); -// _3 = move _4 as *mut usize (Misc); +// _4 = &mut _2; +// _3 = &raw mut (*_4); // ... -// _7 = _3; -// _6 = const foo(move _7) -> bb1; +// _6 = _3; +// _5 = const foo(move _6) -> bb1; // } // // bb1: { // ... -// _8 = _2; -// _9 = Len(_1); -// _10 = Lt(_8, _9); -// assert(move _10, "index out of bounds: the len is move _9 but the index is _8") -> bb2; +// _7 = _2; +// _8 = Len(_1); +// _9 = Lt(_7, _8); +// assert(move _9, "index out of bounds: the len is move _8 but the index is _7") -> bb2; // } // // bb2: { -// _1[_8] = move _6; +// _1[_7] = move _5; // ... // return; // } diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs index 3f82b81a47de5..3c8c0ff449345 100644 --- a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs +++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs @@ -11,25 +11,21 @@ fn main() { // START rustc.main.ConstProp.before.mir // bb0: { // ... -// _3 = _4; -// _2 = move _3 as *const i32 (Misc); -// ... +// _2 = &raw const (*_3); // _1 = move _2 as usize (Misc); // ... -// _6 = _1; -// _5 = const read(move _6) -> bb1; +// _5 = _1; +// _4 = const read(move _5) -> bb1; // } // END rustc.main.ConstProp.before.mir // START rustc.main.ConstProp.after.mir // bb0: { // ... -// _4 = const main::FOO; -// _3 = _4; -// _2 = move _3 as *const i32 (Misc); -// ... +// _3 = const main::FOO; +// _2 = &raw const (*_3); // _1 = move _2 as usize (Misc); // ... -// _6 = _1; -// _5 = const read(move _6) -> bb1; +// _5 = _1; +// _4 = const read(move _5) -> bb1; // } // END rustc.main.ConstProp.after.mir diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs index 32995448a21e9..ccecaeac96b83 100644 --- a/src/test/mir-opt/retag.rs +++ b/src/test/mir-opt/retag.rs @@ -82,18 +82,16 @@ fn main() { // _10 = move _8; // Retag(_10); // ... -// _13 = &mut (*_10); -// Retag(_13); -// _12 = move _13 as *mut i32 (Misc); +// _12 = &raw mut (*_10); // Retag([raw] _12); // ... -// _16 = move _17(move _18) -> bb5; +// _15 = move _16(move _17) -> bb5; // } // // bb5: { -// Retag(_16); +// Retag(_15); // ... -// _20 = const Test::foo_shr(move _21, move _23) -> [return: bb6, unwind: bb7]; +// _19 = const Test::foo_shr(move _20, move _22) -> [return: bb6, unwind: bb7]; // } // // ... diff --git a/src/test/ui/cast/cast-as-bool.rs b/src/test/ui/cast/cast-as-bool.rs index 8130f4dedc9aa..1aed218aeb473 100644 --- a/src/test/ui/cast/cast-as-bool.rs +++ b/src/test/ui/cast/cast-as-bool.rs @@ -5,5 +5,5 @@ fn main() { let t = (1 + 2) as bool; //~ ERROR cannot cast as `bool` //~| HELP compare with zero instead //~| SUGGESTION (1 + 2) != 0 - let v = "hello" as bool; //~ ERROR cannot cast as `bool` + let v = "hello" as bool; //~ ERROR casting `&'static str` as `bool` is invalid } diff --git a/src/test/ui/cast/cast-as-bool.stderr b/src/test/ui/cast/cast-as-bool.stderr index 30f8459c2e1e1..15d94ab69d88c 100644 --- a/src/test/ui/cast/cast-as-bool.stderr +++ b/src/test/ui/cast/cast-as-bool.stderr @@ -10,12 +10,13 @@ error[E0054]: cannot cast as `bool` LL | let t = (1 + 2) as bool; | ^^^^^^^^^^^^^^^ help: compare with zero instead: `(1 + 2) != 0` -error[E0054]: cannot cast as `bool` +error[E0606]: casting `&'static str` as `bool` is invalid --> $DIR/cast-as-bool.rs:8:13 | LL | let v = "hello" as bool; - | ^^^^^^^^^^^^^^^ unsupported cast + | ^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0054`. +Some errors have detailed explanations: E0054, E0606. +For more information about an error, try `rustc --explain E0054`. From 5fb797ca753dfc5586ac277d5af4facab8c7c22f Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 20 Apr 2019 18:06:10 +0100 Subject: [PATCH 3/8] Make slice drop shims use AddressOf --- src/librustc_mir/util/elaborate_drops.rs | 61 +++++++++--------------- src/test/mir-opt/slice-drop-shim.rs | 18 +++---- 2 files changed, 32 insertions(+), 47 deletions(-) diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 67e5bfafafd12..4f482431d3323 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -557,10 +557,10 @@ where /// if can_go then succ else drop-block /// drop-block: /// if ptr_based { - /// ptr = &mut *cur + /// ptr = cur /// cur = cur.offset(1) /// } else { - /// ptr = &mut P[cur] + /// ptr = &raw mut P[cur] /// cur = cur + 1 /// } /// drop(ptr) @@ -574,34 +574,28 @@ where unwind: Unwind, ptr_based: bool, ) -> BasicBlock { - let copy = |place: &Place<'tcx>| Operand::Copy(place.clone()); - let move_ = |place: &Place<'tcx>| Operand::Move(place.clone()); + let copy = |place: Place<'tcx>| Operand::Copy(place); + let move_ = |place: Place<'tcx>| Operand::Move(place); let tcx = self.tcx(); - let ref_ty = tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut { + let ptr_ty = tcx.mk_ptr(ty::TypeAndMut { ty: ety, mutbl: hir::Mutability::Mutable }); - let ptr = &Place::from(self.new_temp(ref_ty)); - let can_go = &Place::from(self.new_temp(tcx.types.bool)); + let ptr = &Place::from(self.new_temp(ptr_ty)); + let can_go = Place::from(self.new_temp(tcx.types.bool)); let one = self.constant_usize(1); let (ptr_next, cur_next) = if ptr_based { - (Rvalue::Ref( - tcx.lifetimes.re_erased, - BorrowKind::Mut { allow_two_phase_borrow: false }, - Place { - base: PlaceBase::Local(cur), - projection: tcx.intern_place_elems(&vec![ProjectionElem::Deref]), - } - ), - Rvalue::BinaryOp(BinOp::Offset, move_(&Place::from(cur)), one)) + ( + Rvalue::Use(copy(cur.into())), + Rvalue::BinaryOp(BinOp::Offset, move_(cur.into()), one), + ) } else { - (Rvalue::Ref( - tcx.lifetimes.re_erased, - BorrowKind::Mut { allow_two_phase_borrow: false }, - tcx.mk_place_index(self.place.clone(), cur)), - Rvalue::BinaryOp(BinOp::Add, move_(&Place::from(cur)), one)) + ( + Rvalue::AddressOf(Mutability::Mut, tcx.mk_place_index(self.place.clone(), cur)), + Rvalue::BinaryOp(BinOp::Add, move_(cur.into()), one), + ) }; let drop_block = BasicBlockData { @@ -620,9 +614,9 @@ where let loop_block = BasicBlockData { statements: vec![ - self.assign(can_go, Rvalue::BinaryOp(BinOp::Eq, - copy(&Place::from(cur)), - copy(length_or_end))) + self.assign(&can_go, Rvalue::BinaryOp(BinOp::Eq, + copy(Place::from(cur)), + copy(length_or_end.clone()))) ], is_cleanup: unwind.is_cleanup(), terminator: Some(Terminator { @@ -725,8 +719,6 @@ where let cur = self.new_temp(iter_ty); let length_or_end = if ptr_based { - // FIXME check if we want to make it return a `Place` directly - // if all use sites want a `Place::Base` anyway. Place::from(self.new_temp(iter_ty)) } else { length.clone() @@ -753,23 +745,16 @@ where let drop_block_stmts = if ptr_based { let tmp_ty = tcx.mk_mut_ptr(self.place_ty(self.place)); let tmp = Place::from(self.new_temp(tmp_ty)); - // tmp = &mut P; + // tmp = &raw mut P; // cur = tmp as *mut T; // end = Offset(cur, len); vec![ - self.assign(&tmp, Rvalue::Ref( - tcx.lifetimes.re_erased, - BorrowKind::Mut { allow_two_phase_borrow: false }, - self.place.clone() - )), - self.assign( - &cur, - Rvalue::Cast(CastKind::Misc, Operand::Move(tmp), iter_ty), - ), + self.assign(&tmp, Rvalue::AddressOf(Mutability::Mut, self.place.clone())), + self.assign(&cur, Rvalue::Cast(CastKind::Misc, Operand::Move(tmp), iter_ty)), self.assign( &length_or_end, - Rvalue::BinaryOp(BinOp::Offset, Operand::Copy(cur), Operand::Move(length) - )), + Rvalue::BinaryOp(BinOp::Offset, Operand::Copy(cur), Operand::Move(length)), + ), ] } else { // cur = 0 (length already pushed) diff --git a/src/test/mir-opt/slice-drop-shim.rs b/src/test/mir-opt/slice-drop-shim.rs index f270dec5fe232..5a37b67229c37 100644 --- a/src/test/mir-opt/slice-drop-shim.rs +++ b/src/test/mir-opt/slice-drop-shim.rs @@ -10,15 +10,15 @@ fn main() { // let mut _2: usize; // let mut _3: usize; // let mut _4: usize; -// let mut _5: &mut std::string::String; +// let mut _5: *mut std::string::String; // let mut _6: bool; -// let mut _7: &mut std::string::String; +// let mut _7: *mut std::string::String; // let mut _8: bool; // let mut _9: *mut std::string::String; // let mut _10: *mut std::string::String; -// let mut _11: &mut std::string::String; +// let mut _11: *mut std::string::String; // let mut _12: bool; -// let mut _13: &mut std::string::String; +// let mut _13: *mut std::string::String; // let mut _14: bool; // let mut _15: *mut [std::string::String]; // bb0: { @@ -31,7 +31,7 @@ fn main() { // resume; // } // bb3 (cleanup): { -// _5 = &mut (*_1)[_4]; +// _5 = &raw mut (*_1)[_4]; // _4 = Add(move _4, const 1usize); // drop((*_5)) -> bb4; // } @@ -40,7 +40,7 @@ fn main() { // switchInt(move _6) -> [false: bb3, otherwise: bb2]; // } // bb5: { -// _7 = &mut (*_1)[_4]; +// _7 = &raw mut (*_1)[_4]; // _4 = Add(move _4, const 1usize); // drop((*_7)) -> [return: bb6, unwind: bb4]; // } @@ -56,7 +56,7 @@ fn main() { // goto -> bb7; // } // bb9 (cleanup): { -// _11 = &mut (*_9); +// _11 = _9; // _9 = Offset(move _9, const 1usize); // drop((*_11)) -> bb10; // } @@ -65,7 +65,7 @@ fn main() { // switchInt(move _12) -> [false: bb9, otherwise: bb2]; // } // bb11: { -// _13 = &mut (*_9); +// _13 = _9; // _9 = Offset(move _9, const 1usize); // drop((*_13)) -> [return: bb12, unwind: bb10]; // } @@ -74,7 +74,7 @@ fn main() { // switchInt(move _14) -> [false: bb11, otherwise: bb1]; // } // bb13: { -// _15 = &mut (*_1); +// _15 = &raw mut (*_1); // _9 = move _15 as *mut std::string::String (Misc); // _10 = Offset(_9, move _3); // goto -> bb12; From 7081c79b7eed2c5b36674526d00c604b647027a3 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 20 Apr 2019 18:07:46 +0100 Subject: [PATCH 4/8] Add mir opt test for AddressOf --- src/test/mir-opt/address-of.rs | 112 +++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 src/test/mir-opt/address-of.rs diff --git a/src/test/mir-opt/address-of.rs b/src/test/mir-opt/address-of.rs new file mode 100644 index 0000000000000..bbd1ca68a8672 --- /dev/null +++ b/src/test/mir-opt/address-of.rs @@ -0,0 +1,112 @@ +fn address_of_reborrow() { + let y = &[0; 10]; + let mut z = &mut [0; 10]; + + y as *const _; + y as *const [i32; 10]; + y as *const dyn Send; + y as *const [i32]; + y as *const i32; // This is a cast, not a coercion + + let p: *const _ = y; + let p: *const [i32; 10] = y; + let p: *const dyn Send = y; + let p: *const [i32] = y; + + z as *const _; + z as *const [i32; 10]; + z as *const dyn Send; + z as *const [i32]; + + let p: *const _ = z; + let p: *const [i32; 10] = z; + let p: *const dyn Send = z; + let p: *const [i32] = z; + + z as *mut _; + z as *mut [i32; 10]; + z as *mut dyn Send; + z as *mut [i32]; + + let p: *mut _ = z; + let p: *mut [i32; 10] = z; + let p: *mut dyn Send = z; + let p: *mut [i32] = z; +} + +// The normal borrows here should be preserved +fn borrow_and_cast(mut x: i32) { + let p = &x as *const i32; + let q = &mut x as *const i32; + let r = &mut x as *mut i32; +} + +fn main() {} + +// START rustc.address_of_reborrow.SimplifyCfg-initial.after.mir +// bb0: { +// ... +// _5 = &raw const (*_1); // & to *const casts +// ... +// _7 = &raw const (*_1); +// ... +// _11 = &raw const (*_1); +// ... +// _14 = &raw const (*_1); +// ... +// _16 = &raw const (*_1); +// ... +// _17 = &raw const (*_1); // & to *const coercions +// ... +// _18 = &raw const (*_1); +// ... +// _20 = &raw const (*_1); +// ... +// _22 = &raw const (*_1); +// ... +// _24 = &raw const (*_2); // &mut to *const casts +// ... +// _26 = &raw const (*_2); +// ... +// _30 = &raw const (*_2); +// ... +// _33 = &raw const (*_2); +// ... +// _34 = &raw const (*_2); // &mut to *const coercions +// ... +// _35 = &raw const (*_2); +// ... +// _37 = &raw const (*_2); +// ... +// _39 = &raw const (*_2); +// ... +// _41 = &raw mut (*_2); // &mut to *mut casts +// ... +// _43 = &raw mut (*_2); +// ... +// _47 = &raw mut (*_2); +// ... +// _50 = &raw mut (*_2); +// ... +// _51 = &raw mut (*_2); // &mut to *mut coercions +// ... +// _52 = &raw mut (*_2); +// ... +// _54 = &raw mut (*_2); +// ... +// _56 = &raw mut (*_2); +// ... +// } +// END rustc.address_of_reborrow.SimplifyCfg-initial.after.mir + +// START rustc.borrow_and_cast.EraseRegions.after.mir +// bb0: { +// ... +// _4 = &_1; +// ... +// _7 = &mut _1; +// ... +// _10 = &mut _1; +// ... +// } +// END rustc.borrow_and_cast.EraseRegions.after.mir From 7b0cc6a439d2cf7a9d6dab5b1df2772488cc80a8 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Tue, 17 Sep 2019 19:32:40 +0100 Subject: [PATCH 5/8] Check const-propagation of borrows of unsized places --- src/test/ui/consts/const-prop-ice3.rs | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/test/ui/consts/const-prop-ice3.rs diff --git a/src/test/ui/consts/const-prop-ice3.rs b/src/test/ui/consts/const-prop-ice3.rs new file mode 100644 index 0000000000000..8ab011661e3c5 --- /dev/null +++ b/src/test/ui/consts/const-prop-ice3.rs @@ -0,0 +1,7 @@ +// run-pass (ensure that const-prop is run) + +struct A(T); + +fn main() { + let _x = &(&A([2, 3]) as &A<[i32]>).0 as *const [i32] as *const i32; +} From 15931947f59e0010b73469711cb811f09aaf0cdd Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Tue, 17 Sep 2019 21:18:15 +0100 Subject: [PATCH 6/8] Update test now that reference to pointer casts have more checks --- src/test/ui/consts/const-eval/ub-wide-ptr.rs | 15 +++++- .../ui/consts/const-eval/ub-wide-ptr.stderr | 54 +++++++++++-------- 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs index 1f810c40572c0..a5c2a57c6c886 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -2,7 +2,6 @@ #![allow(unused)] #![allow(const_err)] // make sure we cannot allow away the errors tested here -// normalize-stderr-test "alignment \d+" -> "alignment N" // normalize-stderr-test "offset \d+" -> "offset N" // normalize-stderr-test "allocation \d+" -> "allocation N" // normalize-stderr-test "size \d+" -> "size N" @@ -149,11 +148,23 @@ const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 } //~^ ERROR it is undefined behavior to use this value // # raw trait object -const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust}; +const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.raw_rust}; //~^ ERROR it is undefined behavior to use this value const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust}; //~^ ERROR it is undefined behavior to use this value const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl } as *const _; // ok because raw +// Const eval fails for these, so they need to be statics to error. +static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe { + DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust + //~^ ERROR could not evaluate static initializer +}; +static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe { + DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust + //~^ ERROR could not evaluate static initializer +}; + fn main() { + let _ = RAW_TRAIT_OBJ_VTABLE_NULL; + let _ = RAW_TRAIT_OBJ_VTABLE_INVALID; } diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index 85fb8ac2a4a36..ce57d680dc95d 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:87:1 + --> $DIR/ub-wide-ptr.rs:86:1 | LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) @@ -7,7 +7,7 @@ LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:90:1 + --> $DIR/ub-wide-ptr.rs:89:1 | LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer @@ -15,7 +15,7 @@ LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:93:1 + --> $DIR/ub-wide-ptr.rs:92:1 | LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer @@ -23,7 +23,7 @@ LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRe = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:97:1 + --> $DIR/ub-wide-ptr.rs:96:1 | LL | const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . @@ -31,7 +31,7 @@ LL | const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:100:1 + --> $DIR/ub-wide-ptr.rs:99:1 | LL | const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at ..0 @@ -39,7 +39,7 @@ LL | const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:107:1 + --> $DIR/ub-wide-ptr.rs:106:1 | LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered undefined pointer @@ -47,7 +47,7 @@ LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.sli = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:110:1 + --> $DIR/ub-wide-ptr.rs:109:1 | LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) @@ -55,7 +55,7 @@ LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { p = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:113:1 + --> $DIR/ub-wide-ptr.rs:112:1 | LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer @@ -63,7 +63,7 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:117:1 + --> $DIR/ub-wide-ptr.rs:116:1 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .[0], but expected something less or equal to 1 @@ -71,7 +71,7 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }. = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:123:1 + --> $DIR/ub-wide-ptr.rs:122:1 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..0, but expected something less or equal to 1 @@ -79,7 +79,7 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:126:1 + --> $DIR/ub-wide-ptr.rs:125:1 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..1[0], but expected something less or equal to 1 @@ -87,7 +87,7 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTrans = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:133:1 + --> $DIR/ub-wide-ptr.rs:132:1 | LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered undefined pointer @@ -95,7 +95,7 @@ LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:138:1 + --> $DIR/ub-wide-ptr.rs:137:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -103,7 +103,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:141:1 + --> $DIR/ub-wide-ptr.rs:140:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -111,7 +111,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:144:1 + --> $DIR/ub-wide-ptr.rs:143:1 | LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -119,7 +119,7 @@ LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDy = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:148:1 + --> $DIR/ub-wide-ptr.rs:147:1 | LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected something less or equal to 1 @@ -127,21 +127,33 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:152:1 + --> $DIR/ub-wide-ptr.rs:151:1 | -LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable +LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.raw_rust}; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:154:1 + --> $DIR/ub-wide-ptr.rs:153:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. -error: aborting due to 18 previous errors +error[E0080]: could not evaluate static initializer + --> $DIR/ub-wide-ptr.rs:159:5 + | +LL | DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer + +error[E0080]: could not evaluate static initializer + --> $DIR/ub-wide-ptr.rs:163:5 + | +LL | DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocation N which has size N + +error: aborting due to 20 previous errors For more information about this error, try `rustc --explain E0080`. From 6dcc78997f19822373ed17549004282da82851dc Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 18 Sep 2019 21:31:25 +0100 Subject: [PATCH 7/8] Add more tests for raw_ref_op --- src/librustc_error_codes/error_codes/E0745.md | 2 +- src/test/pretty/raw-address-of.rs | 12 +++ .../borrow-raw-address-of-borrowed.rs | 22 ++++++ .../borrow-raw-address-of-borrowed.stderr | 40 ++++++++++ ...rrow-raw-address-of-deref-mutability-ok.rs | 23 ++++++ .../borrow-raw-address-of-deref-mutability.rs | 17 +++++ ...row-raw-address-of-deref-mutability.stderr | 21 ++++++ .../borrow-raw-address-of-mutability-ok.rs | 44 +++++++++++ .../borrow-raw-address-of-mutability.rs | 42 +++++++++++ .../borrow-raw-address-of-mutability.stderr | 59 +++++++++++++++ .../consts/const-address-of-interior-mut.rs | 16 ++++ .../const-address-of-interior-mut.stderr | 27 +++++++ src/test/ui/consts/const-address-of-mut.rs | 14 ++++ .../ui/consts/const-address-of-mut.stderr | 39 ++++++++++ src/test/ui/consts/const-address-of.rs | 19 +++++ .../const-mut-refs/const_mut_address_of.rs | 30 ++++++++ src/test/ui/consts/min_const_fn/address_of.rs | 17 +++++ .../ui/consts/min_const_fn/address_of.stderr | 21 ++++++ .../consts/min_const_fn/address_of_const.rs | 19 +++++ src/test/ui/lint/lint-unused-mut-variables.rs | 8 +- .../ui/lint/lint-unused-mut-variables.stderr | 14 +++- .../packed-struct-address-of-element.rs | 37 ++++++++++ .../ui/packed/packed-struct-borrow-element.rs | 2 +- src/test/ui/raw-ref-op/raw-ref-op.rs | 6 +- src/test/ui/raw-ref-op/raw-ref-op.stderr | 18 ----- src/test/ui/raw-ref-op/raw-ref-temp-deref.rs | 20 ++--- .../ui/raw-ref-op/raw-ref-temp-deref.stderr | 74 ------------------- src/test/ui/raw-ref-op/raw-ref-temp.rs | 6 +- src/test/ui/raw-ref-op/raw-ref-temp.stderr | 40 +++++----- src/test/ui/raw-ref-op/unusual_locations.rs | 31 ++++---- .../ui/raw-ref-op/unusual_locations.stderr | 18 ----- 31 files changed, 590 insertions(+), 168 deletions(-) create mode 100644 src/test/pretty/raw-address-of.rs create mode 100644 src/test/ui/borrowck/borrow-raw-address-of-borrowed.rs create mode 100644 src/test/ui/borrowck/borrow-raw-address-of-borrowed.stderr create mode 100644 src/test/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs create mode 100644 src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.rs create mode 100644 src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr create mode 100644 src/test/ui/borrowck/borrow-raw-address-of-mutability-ok.rs create mode 100644 src/test/ui/borrowck/borrow-raw-address-of-mutability.rs create mode 100644 src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr create mode 100644 src/test/ui/consts/const-address-of-interior-mut.rs create mode 100644 src/test/ui/consts/const-address-of-interior-mut.stderr create mode 100644 src/test/ui/consts/const-address-of-mut.rs create mode 100644 src/test/ui/consts/const-address-of-mut.stderr create mode 100644 src/test/ui/consts/const-address-of.rs create mode 100644 src/test/ui/consts/const-mut-refs/const_mut_address_of.rs create mode 100644 src/test/ui/consts/min_const_fn/address_of.rs create mode 100644 src/test/ui/consts/min_const_fn/address_of.stderr create mode 100644 src/test/ui/consts/min_const_fn/address_of_const.rs create mode 100644 src/test/ui/packed/packed-struct-address-of-element.rs delete mode 100644 src/test/ui/raw-ref-op/raw-ref-op.stderr delete mode 100644 src/test/ui/raw-ref-op/raw-ref-temp-deref.stderr delete mode 100644 src/test/ui/raw-ref-op/unusual_locations.stderr diff --git a/src/librustc_error_codes/error_codes/E0745.md b/src/librustc_error_codes/error_codes/E0745.md index 39bebdcd3750e..6595691ce786c 100644 --- a/src/librustc_error_codes/error_codes/E0745.md +++ b/src/librustc_error_codes/error_codes/E0745.md @@ -11,7 +11,7 @@ fn temp_address() { To avoid the error, first bind the temporary to a named local variable. -```ignore (not yet implemented) +``` # #![feature(raw_ref_op)] fn temp_address() { let val = 2; diff --git a/src/test/pretty/raw-address-of.rs b/src/test/pretty/raw-address-of.rs new file mode 100644 index 0000000000000..6ccc434a1e79c --- /dev/null +++ b/src/test/pretty/raw-address-of.rs @@ -0,0 +1,12 @@ +// pp-exact +#![feature(raw_ref_op)] + +const C_PTR: () = { let a = 1; &raw const a; }; +static S_PTR: () = { let b = false; &raw const b; }; + +fn main() { + let x = 123; + let mut y = 345; + let c_p = &raw const x; + let parens = unsafe { *(&raw mut (y)) }; +} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-borrowed.rs b/src/test/ui/borrowck/borrow-raw-address-of-borrowed.rs new file mode 100644 index 0000000000000..f25fd7f66b3cc --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-borrowed.rs @@ -0,0 +1,22 @@ +#![feature(raw_ref_op)] + +fn address_of_shared() { + let mut x = 0; + let y = &x; + + let q = &raw mut x; //~ ERROR cannot borrow + + drop(y); +} + +fn address_of_mutably_borrowed() { + let mut x = 0; + let y = &mut x; + + let p = &raw const x; //~ ERROR cannot borrow + let q = &raw mut x; //~ ERROR cannot borrow + + drop(y); +} + +fn main() {} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-borrowed.stderr b/src/test/ui/borrowck/borrow-raw-address-of-borrowed.stderr new file mode 100644 index 0000000000000..ff461b748be88 --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-borrowed.stderr @@ -0,0 +1,40 @@ +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/borrow-raw-address-of-borrowed.rs:7:13 + | +LL | let y = &x; + | -- immutable borrow occurs here +LL | +LL | let q = &raw mut x; + | ^^^^^^^^^^ mutable borrow occurs here +LL | +LL | drop(y); + | - immutable borrow later used here + +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/borrow-raw-address-of-borrowed.rs:16:13 + | +LL | let y = &mut x; + | ------ mutable borrow occurs here +LL | +LL | let p = &raw const x; + | ^^^^^^^^^^^^ immutable borrow occurs here +... +LL | drop(y); + | - mutable borrow later used here + +error[E0499]: cannot borrow `x` as mutable more than once at a time + --> $DIR/borrow-raw-address-of-borrowed.rs:17:13 + | +LL | let y = &mut x; + | ------ first mutable borrow occurs here +... +LL | let q = &raw mut x; + | ^^^^^^^^^^ second mutable borrow occurs here +LL | +LL | drop(y); + | - first borrow later used here + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0499, E0502. +For more information about an error, try `rustc --explain E0499`. diff --git a/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs new file mode 100644 index 0000000000000..e381384fe65ec --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability-ok.rs @@ -0,0 +1,23 @@ +// check-pass + +#![feature(raw_ref_op)] + +fn raw_reborrow() { + let x = &0; + let y = &mut 0; + + let p = &raw const *x; + let r = &raw const *y; + let s = &raw mut *y; +} + +unsafe fn raw_reborrow_of_raw() { + let x = &0 as *const i32; + let y = &mut 0 as *mut i32; + + let p = &raw const *x; + let r = &raw const *y; + let s = &raw mut *y; +} + +fn main() {} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.rs b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.rs new file mode 100644 index 0000000000000..712873528b5f1 --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.rs @@ -0,0 +1,17 @@ +// Check that `&raw mut` cannot be used to turn a `&T` into a `*mut T`. + +#![feature(raw_ref_op)] + +fn raw_reborrow() { + let x = &0; + + let q = &raw mut *x; //~ ERROR cannot borrow +} + +unsafe fn raw_reborrow_of_raw() { + let x = &0 as *const i32; + + let q = &raw mut *x; //~ ERROR cannot borrow +} + +fn main() {} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr new file mode 100644 index 0000000000000..31af38507c7d7 --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-deref-mutability.stderr @@ -0,0 +1,21 @@ +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference + --> $DIR/borrow-raw-address-of-deref-mutability.rs:8:13 + | +LL | let x = &0; + | -- help: consider changing this to be a mutable reference: `&mut 0` +LL | +LL | let q = &raw mut *x; + | ^^^^^^^^^^^ `x` is a `&` reference, so the data it refers to cannot be borrowed as mutable + +error[E0596]: cannot borrow `*x` as mutable, as it is behind a `*const` pointer + --> $DIR/borrow-raw-address-of-deref-mutability.rs:14:13 + | +LL | let x = &0 as *const i32; + | -- help: consider changing this to be a mutable pointer: `&mut 0` +LL | +LL | let q = &raw mut *x; + | ^^^^^^^^^^^ `x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/borrowck/borrow-raw-address-of-mutability-ok.rs b/src/test/ui/borrowck/borrow-raw-address-of-mutability-ok.rs new file mode 100644 index 0000000000000..e1cf2dc53869b --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-mutability-ok.rs @@ -0,0 +1,44 @@ +// check-pass + +#![feature(raw_ref_op)] + +fn mutable_address_of() { + let mut x = 0; + let y = &raw mut x; +} + +fn mutable_address_of_closure() { + let mut x = 0; + let mut f = || { + let y = &raw mut x; + }; + f(); +} + +fn const_address_of_closure() { + let x = 0; + let f = || { + let y = &raw const x; + }; + f(); +} + +fn make_fn(f: F) -> F { f } + +fn const_address_of_fn_closure() { + let x = 0; + let f = make_fn(|| { + let y = &raw const x; + }); + f(); +} + +fn const_address_of_fn_closure_move() { + let x = 0; + let f = make_fn(move || { + let y = &raw const x; + }); + f(); +} + +fn main() {} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-mutability.rs b/src/test/ui/borrowck/borrow-raw-address-of-mutability.rs new file mode 100644 index 0000000000000..320c54b806a72 --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-mutability.rs @@ -0,0 +1,42 @@ +#![feature(raw_ref_op)] + +fn mutable_address_of() { + let x = 0; + let y = &raw mut x; //~ ERROR cannot borrow +} + +fn mutable_address_of_closure() { + let x = 0; + let mut f = || { + let y = &raw mut x; //~ ERROR cannot borrow + }; + f(); +} + +fn mutable_address_of_imm_closure() { + let mut x = 0; + let f = || { + let y = &raw mut x; + }; + f(); //~ ERROR cannot borrow +} + +fn make_fn(f: F) -> F { f } + +fn mutable_address_of_fn_closure() { + let mut x = 0; + let f = make_fn(|| { + let y = &raw mut x; //~ ERROR cannot borrow + }); + f(); +} + +fn mutable_address_of_fn_closure_move() { + let mut x = 0; + let f = make_fn(move || { + let y = &raw mut x; //~ ERROR cannot borrow + }); + f(); +} + +fn main() {} diff --git a/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr new file mode 100644 index 0000000000000..cf01c362d50bc --- /dev/null +++ b/src/test/ui/borrowck/borrow-raw-address-of-mutability.stderr @@ -0,0 +1,59 @@ +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrow-raw-address-of-mutability.rs:5:13 + | +LL | let x = 0; + | - help: consider changing this to be mutable: `mut x` +LL | let y = &raw mut x; + | ^^^^^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/borrow-raw-address-of-mutability.rs:11:17 + | +LL | let x = 0; + | - help: consider changing this to be mutable: `mut x` +LL | let mut f = || { +LL | let y = &raw mut x; + | ^^^^^^^^^^ cannot borrow as mutable + +error[E0596]: cannot borrow `f` as mutable, as it is not declared as mutable + --> $DIR/borrow-raw-address-of-mutability.rs:21:5 + | +LL | let f = || { + | - help: consider changing this to be mutable: `mut f` +... +LL | f(); + | ^ cannot borrow as mutable + +error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure + --> $DIR/borrow-raw-address-of-mutability.rs:29:17 + | +LL | let y = &raw mut x; + | ^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to accept closures that implement `FnMut` + --> $DIR/borrow-raw-address-of-mutability.rs:28:21 + | +LL | let f = make_fn(|| { + | _____________________^ +LL | | let y = &raw mut x; +LL | | }); + | |_____^ + +error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure + --> $DIR/borrow-raw-address-of-mutability.rs:37:17 + | +LL | let y = &raw mut x; + | ^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to accept closures that implement `FnMut` + --> $DIR/borrow-raw-address-of-mutability.rs:36:21 + | +LL | let f = make_fn(move || { + | _____________________^ +LL | | let y = &raw mut x; +LL | | }); + | |_____^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/consts/const-address-of-interior-mut.rs b/src/test/ui/consts/const-address-of-interior-mut.rs new file mode 100644 index 0000000000000..60c7c31daca78 --- /dev/null +++ b/src/test/ui/consts/const-address-of-interior-mut.rs @@ -0,0 +1,16 @@ +#![feature(raw_ref_op)] + +use std::cell::Cell; + +const A: () = { let x = Cell::new(2); &raw const x; }; //~ ERROR interior mutability + +static B: () = { let x = Cell::new(2); &raw const x; }; //~ ERROR interior mutability + +static mut C: () = { let x = Cell::new(2); &raw const x; }; //~ ERROR interior mutability + +const fn foo() { + let x = Cell::new(0); + let y = &raw const x; //~ ERROR interior mutability +} + +fn main() {} diff --git a/src/test/ui/consts/const-address-of-interior-mut.stderr b/src/test/ui/consts/const-address-of-interior-mut.stderr new file mode 100644 index 0000000000000..f15174c33b3a0 --- /dev/null +++ b/src/test/ui/consts/const-address-of-interior-mut.stderr @@ -0,0 +1,27 @@ +error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead + --> $DIR/const-address-of-interior-mut.rs:5:39 + | +LL | const A: () = { let x = Cell::new(2); &raw const x; }; + | ^^^^^^^^^^^^ + +error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead + --> $DIR/const-address-of-interior-mut.rs:7:40 + | +LL | static B: () = { let x = Cell::new(2); &raw const x; }; + | ^^^^^^^^^^^^ + +error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead + --> $DIR/const-address-of-interior-mut.rs:9:44 + | +LL | static mut C: () = { let x = Cell::new(2); &raw const x; }; + | ^^^^^^^^^^^^ + +error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead + --> $DIR/const-address-of-interior-mut.rs:13:13 + | +LL | let y = &raw const x; + | ^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0492`. diff --git a/src/test/ui/consts/const-address-of-mut.rs b/src/test/ui/consts/const-address-of-mut.rs new file mode 100644 index 0000000000000..fe9188cb4904c --- /dev/null +++ b/src/test/ui/consts/const-address-of-mut.rs @@ -0,0 +1,14 @@ +#![feature(raw_ref_op)] + +const A: () = { let mut x = 2; &raw mut x; }; //~ ERROR `&raw mut` is not allowed + +static B: () = { let mut x = 2; &raw mut x; }; //~ ERROR `&raw mut` is not allowed + +static mut C: () = { let mut x = 2; &raw mut x; }; //~ ERROR `&raw mut` is not allowed + +const fn foo() { + let mut x = 0; + let y = &raw mut x; //~ ERROR `&raw mut` is not allowed +} + +fn main() {} diff --git a/src/test/ui/consts/const-address-of-mut.stderr b/src/test/ui/consts/const-address-of-mut.stderr new file mode 100644 index 0000000000000..15f2296c42c25 --- /dev/null +++ b/src/test/ui/consts/const-address-of-mut.stderr @@ -0,0 +1,39 @@ +error[E0658]: `&raw mut` is not allowed in constants + --> $DIR/const-address-of-mut.rs:3:32 + | +LL | const A: () = { let mut x = 2; &raw mut x; }; + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/57349 + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: `&raw mut` is not allowed in statics + --> $DIR/const-address-of-mut.rs:5:33 + | +LL | static B: () = { let mut x = 2; &raw mut x; }; + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/57349 + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: `&raw mut` is not allowed in statics + --> $DIR/const-address-of-mut.rs:7:37 + | +LL | static mut C: () = { let mut x = 2; &raw mut x; }; + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/57349 + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: `&raw mut` is not allowed in constant functions + --> $DIR/const-address-of-mut.rs:11:13 + | +LL | let y = &raw mut x; + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/57349 + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/const-address-of.rs b/src/test/ui/consts/const-address-of.rs new file mode 100644 index 0000000000000..ba162f2a2badf --- /dev/null +++ b/src/test/ui/consts/const-address-of.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(raw_ref_op)] + +const A: *const i32 = &raw const *&2; +static B: () = { &raw const *&2; }; +static mut C: *const i32 = &raw const *&2; +const D: () = { let x = 2; &raw const x; }; +static E: () = { let x = 2; &raw const x; }; +static mut F: () = { let x = 2; &raw const x; }; + +const fn const_ptr() { + let x = 0; + let ptr = &raw const x; + let r = &x; + let ptr2 = &raw const *r; +} + +fn main() {} diff --git a/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs b/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs new file mode 100644 index 0000000000000..130ba9283b1d9 --- /dev/null +++ b/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs @@ -0,0 +1,30 @@ +// check-pass + +#![feature(const_mut_refs)] +#![feature(const_fn)] +#![feature(raw_ref_op)] + +struct Foo { + x: usize +} + +const fn foo() -> Foo { + Foo { x: 0 } +} + +impl Foo { + const fn bar(&mut self) -> *mut usize { + &raw mut self.x + } +} + +const fn baz(foo: &mut Foo)-> *mut usize { + &raw mut foo.x +} + +const _: () = { + foo().bar(); + baz(&mut foo()); +}; + +fn main() {} diff --git a/src/test/ui/consts/min_const_fn/address_of.rs b/src/test/ui/consts/min_const_fn/address_of.rs new file mode 100644 index 0000000000000..f8506d70b2498 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/address_of.rs @@ -0,0 +1,17 @@ +#![feature(raw_ref_op)] + +const fn mutable_address_of_in_const() { + let mut a = 0; + let b = &raw mut a; //~ ERROR `&raw mut` is not allowed +} + +struct X; + +impl X { + const fn inherent_mutable_address_of_in_const() { + let mut a = 0; + let b = &raw mut a; //~ ERROR `&raw mut` is not allowed + } +} + +fn main() {} diff --git a/src/test/ui/consts/min_const_fn/address_of.stderr b/src/test/ui/consts/min_const_fn/address_of.stderr new file mode 100644 index 0000000000000..3554b8112b168 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/address_of.stderr @@ -0,0 +1,21 @@ +error[E0658]: `&raw mut` is not allowed in constant functions + --> $DIR/address_of.rs:5:13 + | +LL | let b = &raw mut a; + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/57349 + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0658]: `&raw mut` is not allowed in constant functions + --> $DIR/address_of.rs:13:17 + | +LL | let b = &raw mut a; + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/57349 + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/min_const_fn/address_of_const.rs b/src/test/ui/consts/min_const_fn/address_of_const.rs new file mode 100644 index 0000000000000..3db19e9cde8f0 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/address_of_const.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(raw_ref_op)] + +const fn const_address_of_in_const() { + let mut a = 0; + let b = &raw const a; +} + +struct X; + +impl X { + const fn inherent_const_address_of_in_const() { + let mut a = 0; + let b = &raw const a; + } +} + +fn main() {} diff --git a/src/test/ui/lint/lint-unused-mut-variables.rs b/src/test/ui/lint/lint-unused-mut-variables.rs index 1af44ecf362bf..dd8dbda6d4303 100644 --- a/src/test/ui/lint/lint-unused-mut-variables.rs +++ b/src/test/ui/lint/lint-unused-mut-variables.rs @@ -3,7 +3,7 @@ // Exercise the unused_mut attribute in some positive and negative cases #![deny(unused_mut)] -#![feature(async_closure)] +#![feature(async_closure, raw_ref_op)] async fn baz_async( mut a: i32, @@ -177,6 +177,12 @@ fn main() { // leading underscore should avoid the warning, just like the // unused variable lint. let mut _allowed = 1; + + let mut raw_address_of_mut = 1; // OK + let mut_ptr = &raw mut raw_address_of_mut; + + let mut raw_address_of_const = 1; //~ ERROR: variable does not need to be mutable + let const_ptr = &raw const raw_address_of_const; } fn callback(f: F) where F: FnOnce() {} diff --git a/src/test/ui/lint/lint-unused-mut-variables.stderr b/src/test/ui/lint/lint-unused-mut-variables.stderr index 92c2b68652dc2..c1ab0ab33d4cc 100644 --- a/src/test/ui/lint/lint-unused-mut-variables.stderr +++ b/src/test/ui/lint/lint-unused-mut-variables.stderr @@ -180,6 +180,14 @@ LL | let mut v : &mut Vec<()> = &mut vec![]; | | | help: remove this `mut` +error: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:184:9 + | +LL | let mut raw_address_of_const = 1; + | ----^^^^^^^^^^^^^^^^^^^^ + | | + | help: remove this `mut` + error: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:106:13 | @@ -197,7 +205,7 @@ LL | fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] { | help: remove this `mut` error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:196:9 + --> $DIR/lint-unused-mut-variables.rs:202:9 | LL | let mut b = vec![2]; | ----^ @@ -205,10 +213,10 @@ LL | let mut b = vec![2]; | help: remove this `mut` | note: lint level defined here - --> $DIR/lint-unused-mut-variables.rs:192:8 + --> $DIR/lint-unused-mut-variables.rs:198:8 | LL | #[deny(unused_mut)] | ^^^^^^^^^^ -error: aborting due to 25 previous errors +error: aborting due to 26 previous errors diff --git a/src/test/ui/packed/packed-struct-address-of-element.rs b/src/test/ui/packed/packed-struct-address-of-element.rs new file mode 100644 index 0000000000000..812d23fb58023 --- /dev/null +++ b/src/test/ui/packed/packed-struct-address-of-element.rs @@ -0,0 +1,37 @@ +// run-pass +#![allow(dead_code)] +#![deny(safe_packed_borrows)] +#![feature(raw_ref_op)] +// ignore-emscripten weird assertion? + +#[repr(packed)] +struct Foo1 { + bar: u8, + baz: usize +} + +#[repr(packed(2))] +struct Foo2 { + bar: u8, + baz: usize +} + +#[repr(C, packed(4))] +struct Foo4C { + bar: u8, + baz: usize +} + +pub fn main() { + let foo = Foo1 { bar: 1, baz: 2 }; + let brw = &raw const foo.baz; + unsafe { assert_eq!(brw.read_unaligned(), 2); } + + let foo = Foo2 { bar: 1, baz: 2 }; + let brw = &raw const foo.baz; + unsafe { assert_eq!(brw.read_unaligned(), 2); } + + let mut foo = Foo4C { bar: 1, baz: 2 }; + let brw = &raw mut foo.baz; + unsafe { assert_eq!(brw.read_unaligned(), 2); } +} diff --git a/src/test/ui/packed/packed-struct-borrow-element.rs b/src/test/ui/packed/packed-struct-borrow-element.rs index 6ac42ed0d471b..0072b6191ebb0 100644 --- a/src/test/ui/packed/packed-struct-borrow-element.rs +++ b/src/test/ui/packed/packed-struct-borrow-element.rs @@ -1,4 +1,4 @@ -// run-pass +// run-pass (note: this is spec-UB, but it works for now) #![allow(dead_code)] // ignore-emscripten weird assertion? diff --git a/src/test/ui/raw-ref-op/raw-ref-op.rs b/src/test/ui/raw-ref-op/raw-ref-op.rs index de847909eb371..0c6e23a00d525 100644 --- a/src/test/ui/raw-ref-op/raw-ref-op.rs +++ b/src/test/ui/raw-ref-op/raw-ref-op.rs @@ -1,11 +1,11 @@ -// FIXME(#64490): make this run-pass +// run-pass #![feature(raw_ref_op)] fn main() { let mut x = 123; - let c_p = &raw const x; //~ ERROR not yet implemented - let m_p = &raw mut x; //~ ERROR not yet implemented + let c_p = &raw const x; + let m_p = &raw mut x; let i_r = &x; assert!(c_p == i_r); assert!(c_p == m_p); diff --git a/src/test/ui/raw-ref-op/raw-ref-op.stderr b/src/test/ui/raw-ref-op/raw-ref-op.stderr deleted file mode 100644 index 04c59c95fca1e..0000000000000 --- a/src/test/ui/raw-ref-op/raw-ref-op.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: raw borrows are not yet implemented - --> $DIR/raw-ref-op.rs:7:15 - | -LL | let c_p = &raw const x; - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-op.rs:8:15 - | -LL | let m_p = &raw mut x; - | ^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs b/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs index d251586de5595..a814003aebf20 100644 --- a/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs +++ b/src/test/ui/raw-ref-op/raw-ref-temp-deref.rs @@ -1,4 +1,4 @@ -// FIXME(#64490) This should be check-pass +// check-pass // Check that taking the address of a place that contains a dereference is // allowed. #![feature(raw_ref_op, type_ascription)] @@ -10,15 +10,15 @@ const SLICE_REF: &[i32] = &[5, 6]; fn main() { // These are all OK, we're not taking the address of the temporary - let deref_ref = &raw const *PAIR_REF; //~ ERROR not yet implemented - let field_deref_ref = &raw const PAIR_REF.0; //~ ERROR not yet implemented - let deref_ref = &raw const *ARRAY_REF; //~ ERROR not yet implemented - let index_deref_ref = &raw const ARRAY_REF[0]; //~ ERROR not yet implemented - let deref_ref = &raw const *SLICE_REF; //~ ERROR not yet implemented - let index_deref_ref = &raw const SLICE_REF[1]; //~ ERROR not yet implemented + let deref_ref = &raw const *PAIR_REF; + let field_deref_ref = &raw const PAIR_REF.0; + let deref_ref = &raw const *ARRAY_REF; + let index_deref_ref = &raw const ARRAY_REF[0]; + let deref_ref = &raw const *SLICE_REF; + let index_deref_ref = &raw const SLICE_REF[1]; let x = 0; - let ascribe_ref = &raw const (x: i32); //~ ERROR not yet implemented - let ascribe_deref = &raw const (*ARRAY_REF: [i32; 2]); //~ ERROR not yet implemented - let ascribe_index_deref = &raw const (ARRAY_REF[0]: i32); //~ ERROR not yet implemented + let ascribe_ref = &raw const (x: i32); + let ascribe_deref = &raw const (*ARRAY_REF: [i32; 2]); + let ascribe_index_deref = &raw const (ARRAY_REF[0]: i32); } diff --git a/src/test/ui/raw-ref-op/raw-ref-temp-deref.stderr b/src/test/ui/raw-ref-op/raw-ref-temp-deref.stderr deleted file mode 100644 index b0bfc74903b0c..0000000000000 --- a/src/test/ui/raw-ref-op/raw-ref-temp-deref.stderr +++ /dev/null @@ -1,74 +0,0 @@ -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:13:21 - | -LL | let deref_ref = &raw const *PAIR_REF; - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:14:27 - | -LL | let field_deref_ref = &raw const PAIR_REF.0; - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:15:21 - | -LL | let deref_ref = &raw const *ARRAY_REF; - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:16:27 - | -LL | let index_deref_ref = &raw const ARRAY_REF[0]; - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:17:21 - | -LL | let deref_ref = &raw const *SLICE_REF; - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:18:27 - | -LL | let index_deref_ref = &raw const SLICE_REF[1]; - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:21:23 - | -LL | let ascribe_ref = &raw const (x: i32); - | ^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:22:25 - | -LL | let ascribe_deref = &raw const (*ARRAY_REF: [i32; 2]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/raw-ref-temp-deref.rs:23:31 - | -LL | let ascribe_index_deref = &raw const (ARRAY_REF[0]: i32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: aborting due to 9 previous errors - diff --git a/src/test/ui/raw-ref-op/raw-ref-temp.rs b/src/test/ui/raw-ref-op/raw-ref-temp.rs index ac2445f049c66..32df56468da17 100644 --- a/src/test/ui/raw-ref-op/raw-ref-temp.rs +++ b/src/test/ui/raw-ref-op/raw-ref-temp.rs @@ -1,6 +1,8 @@ // Ensure that we don't allow taking the address of temporary values #![feature(raw_ref_op, type_ascription)] +const FOUR: u64 = 4; + const PAIR: (i32, i64) = (1, 2); const ARRAY: [i32; 2] = [1, 2]; @@ -8,8 +10,8 @@ const ARRAY: [i32; 2] = [1, 2]; fn main() { let ref_expr = &raw const 2; //~ ERROR cannot take address let mut_ref_expr = &raw mut 3; //~ ERROR cannot take address - let ref_const = &raw const 4; //~ ERROR cannot take address - let mut_ref_const = &raw mut 5; //~ ERROR cannot take address + let ref_const = &raw const FOUR; //~ ERROR cannot take address + let mut_ref_const = &raw mut FOUR; //~ ERROR cannot take address let field_ref_expr = &raw const (1, 2).0; //~ ERROR cannot take address let mut_field_ref_expr = &raw mut (1, 2).0; //~ ERROR cannot take address diff --git a/src/test/ui/raw-ref-op/raw-ref-temp.stderr b/src/test/ui/raw-ref-op/raw-ref-temp.stderr index de07073373506..80dea76d5953b 100644 --- a/src/test/ui/raw-ref-op/raw-ref-temp.stderr +++ b/src/test/ui/raw-ref-op/raw-ref-temp.stderr @@ -1,95 +1,95 @@ error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:9:31 + --> $DIR/raw-ref-temp.rs:11:31 | LL | let ref_expr = &raw const 2; | ^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:10:33 + --> $DIR/raw-ref-temp.rs:12:33 | LL | let mut_ref_expr = &raw mut 3; | ^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:11:32 + --> $DIR/raw-ref-temp.rs:13:32 | -LL | let ref_const = &raw const 4; - | ^ temporary value +LL | let ref_const = &raw const FOUR; + | ^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:12:34 + --> $DIR/raw-ref-temp.rs:14:34 | -LL | let mut_ref_const = &raw mut 5; - | ^ temporary value +LL | let mut_ref_const = &raw mut FOUR; + | ^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:14:37 + --> $DIR/raw-ref-temp.rs:16:37 | LL | let field_ref_expr = &raw const (1, 2).0; | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:15:39 + --> $DIR/raw-ref-temp.rs:17:39 | LL | let mut_field_ref_expr = &raw mut (1, 2).0; | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:16:32 + --> $DIR/raw-ref-temp.rs:18:32 | LL | let field_ref = &raw const PAIR.0; | ^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:17:34 + --> $DIR/raw-ref-temp.rs:19:34 | LL | let mut_field_ref = &raw mut PAIR.0; | ^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:19:37 + --> $DIR/raw-ref-temp.rs:21:37 | LL | let index_ref_expr = &raw const [1, 2][0]; | ^^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:20:39 + --> $DIR/raw-ref-temp.rs:22:39 | LL | let mut_index_ref_expr = &raw mut [1, 2][0]; | ^^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:21:32 + --> $DIR/raw-ref-temp.rs:23:32 | LL | let index_ref = &raw const ARRAY[0]; | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:22:34 + --> $DIR/raw-ref-temp.rs:24:34 | LL | let mut_index_ref = &raw mut ARRAY[1]; | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:24:34 + --> $DIR/raw-ref-temp.rs:26:34 | LL | let ref_ascribe = &raw const (2: i32); | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:25:36 + --> $DIR/raw-ref-temp.rs:27:36 | LL | let mut_ref_ascribe = &raw mut (3: i32); | ^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:27:40 + --> $DIR/raw-ref-temp.rs:29:40 | LL | let ascribe_field_ref = &raw const (PAIR.0: i32); | ^^^^^^^^^^^^^ temporary value error[E0745]: cannot take address of a temporary - --> $DIR/raw-ref-temp.rs:28:38 + --> $DIR/raw-ref-temp.rs:30:38 | LL | let ascribe_index_ref = &raw mut (ARRAY[0]: i32); | ^^^^^^^^^^^^^^^ temporary value diff --git a/src/test/ui/raw-ref-op/unusual_locations.rs b/src/test/ui/raw-ref-op/unusual_locations.rs index f0a6bcce2ac8a..6bf37408a8bbd 100644 --- a/src/test/ui/raw-ref-op/unusual_locations.rs +++ b/src/test/ui/raw-ref-op/unusual_locations.rs @@ -1,25 +1,22 @@ -// FIXME(#64490): make this check-pass +// check-pass #![feature(raw_ref_op)] -const USES_PTR: () = { let u = (); &raw const u; }; //~ ERROR not yet implemented -static ALSO_USES_PTR: () = { let u = (); &raw const u; }; //~ ERROR not yet implemented +const USES_PTR: () = { let u = (); &raw const u; }; +static ALSO_USES_PTR: () = { let u = (); &raw const u; }; fn main() { - #[cfg(FALSE)] - { - let x: [i32; { let u = 2; let x = &raw const u; 4 }] - = [2; { let v = 3; let y = &raw const v; 4 }]; - let mut one = 1; - let two = 2; - if &raw const one == &raw mut one { - match &raw const two { - _ => {} - } + let x: [i32; { let u = 2; let x = &raw const u; 4 }] + = [2; { let v = 3; let y = &raw const v; 4 }]; + let mut one = 1; + let two = 2; + if &raw const one == &raw mut one { + match &raw const two { + _ => {} } - let three = 3; - let mut four = 4; - println!("{:p}", &raw const three); - unsafe { &raw mut four; } } + let three = 3; + let mut four = 4; + println!("{:p}", &raw const three); + unsafe { &raw mut four; } } diff --git a/src/test/ui/raw-ref-op/unusual_locations.stderr b/src/test/ui/raw-ref-op/unusual_locations.stderr deleted file mode 100644 index 3fae5db3d51a1..0000000000000 --- a/src/test/ui/raw-ref-op/unusual_locations.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: raw borrows are not yet implemented - --> $DIR/unusual_locations.rs:5:36 - | -LL | const USES_PTR: () = { let u = (); &raw const u; }; - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: raw borrows are not yet implemented - --> $DIR/unusual_locations.rs:6:42 - | -LL | static ALSO_USES_PTR: () = { let u = (); &raw const u; }; - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/64490 - -error: aborting due to 2 previous errors - From a74911662e8de2c024ea188e4dcac6a494c74455 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 2 Dec 2019 22:20:35 +0000 Subject: [PATCH 8/8] Fix comment ordering --- src/libsyntax/ast.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 92ba071a03d68..274e19ec3e425 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -728,13 +728,13 @@ impl Mutability { #[derive(Clone, Copy, PartialEq, Eq, Debug)] #[derive(RustcEncodable, RustcDecodable, HashStable_Generic)] pub enum BorrowKind { - /// A raw borrow, `&raw const $expr` or `&raw mut $expr`. - /// The resulting type is either `*const T` or `*mut T` - /// where `T = typeof($expr)`. - Ref, /// A normal borrow, `&$expr` or `&mut $expr`. /// The resulting type is either `&'a T` or `&'a mut T` /// where `T = typeof($expr)` and `'a` is some lifetime. + Ref, + /// A raw borrow, `&raw const $expr` or `&raw mut $expr`. + /// The resulting type is either `*const T` or `*mut T` + /// where `T = typeof($expr)`. Raw, }