From 64afc6b51779c32b3d68a45b956b76b8899a135e Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 7 Dec 2018 18:25:55 +0100 Subject: [PATCH 1/2] Differentiate between closure and function bodies --- src/librustc/hir/map/mod.rs | 13 +++++++++++-- src/librustc/hir/mod.rs | 12 ++++++++++++ src/librustc/middle/region.rs | 4 ++-- src/librustc_mir/borrow_check/mod.rs | 5 +---- .../borrow_check/nll/universal_regions.rs | 1 + src/librustc_mir/build/mod.rs | 2 +- src/librustc_mir/build/scope.rs | 1 + src/librustc_mir/hair/cx/mod.rs | 1 + src/librustc_mir/transform/inline.rs | 12 ++++-------- src/librustc_mir/transform/qualify_consts.rs | 1 + src/librustc_mir/util/pretty.rs | 2 ++ src/librustc_passes/rvalue_promotion.rs | 1 + 12 files changed, 38 insertions(+), 17 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index d9ca37c937bc7..c3e4f0c05014c 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -455,11 +455,20 @@ impl<'hir> Map<'hir> { Node::AnonConst(_) => { BodyOwnerKind::Const } + Node::Variant(&Spanned { node: VariantKind { data: VariantData::Tuple(..), .. }, .. }) | + Node::StructCtor(..) | + Node::Item(&Item { node: ItemKind::Fn(..), .. }) | + Node::TraitItem(&TraitItem { node: TraitItemKind::Method(..), .. }) | + Node::ImplItem(&ImplItem { node: ImplItemKind::Method(..), .. }) => { + BodyOwnerKind::Fn + } Node::Item(&Item { node: ItemKind::Static(_, m, _), .. }) => { BodyOwnerKind::Static(m) } - // Default to function if it's not a constant or static. - _ => BodyOwnerKind::Fn + Node::Expr(&Expr { node: ExprKind::Closure(..), .. }) => { + BodyOwnerKind::Closure + } + node => bug!("{:#?} is not a body node", node), } } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 65d9d5a4f363f..b58b1d359f98b 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1270,6 +1270,9 @@ pub enum BodyOwnerKind { /// Functions and methods. Fn, + /// Closures + Closure, + /// Constants and associated constants. Const, @@ -1277,6 +1280,15 @@ pub enum BodyOwnerKind { Static(Mutability), } +impl BodyOwnerKind { + pub fn is_fn_or_closure(self) -> bool { + match self { + BodyOwnerKind::Fn | BodyOwnerKind::Closure => true, + BodyOwnerKind::Const | BodyOwnerKind::Static(_) => false, + } + } +} + /// A constant (expression) that's not an item or associated item, /// but needs its own `DefId` for type-checking, const-eval, etc. /// These are usually found nested inside types (e.g., array lengths) diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 819dd8aa7d53e..31f91a1bae57f 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -1268,8 +1268,8 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionResolutionVisitor<'a, 'tcx> { // The body of the every fn is a root scope. self.cx.parent = self.cx.var_parent; - if let hir::BodyOwnerKind::Fn = self.tcx.hir().body_owner_kind(owner_id) { - self.visit_expr(&body.value); + if self.tcx.hir().body_owner_kind(owner_id).is_fn_or_closure() { + self.visit_expr(&body.value) } else { // Only functions have an outer terminating (drop) scope, while // temporaries in constant initializers may be 'static, but only diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 45632245b61de..9d49814c35a34 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -163,10 +163,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), )); - let locals_are_invalidated_at_exit = match tcx.hir().body_owner_kind(id) { - hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => false, - hir::BodyOwnerKind::Fn => true, - }; + let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(id).is_fn_or_closure(); let borrow_set = Rc::new(BorrowSet::build( tcx, mir, locals_are_invalidated_at_exit, &mdpe.move_data)); diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs index c63d45ce1d272..0a214e60bdd78 100644 --- a/src/librustc_mir/borrow_check/nll/universal_regions.rs +++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs @@ -476,6 +476,7 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> { let closure_base_def_id = tcx.closure_base_def_id(self.mir_def_id); match tcx.hir().body_owner_kind(self.mir_node_id) { + BodyOwnerKind::Closure | BodyOwnerKind::Fn => { let defining_ty = if self.mir_def_id == closure_base_def_id { tcx.type_of(closure_base_def_id) diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 2bf2824d835cc..420ae113ad330 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -75,7 +75,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t let cx = Cx::new(&infcx, id); let mut mir = if cx.tables().tainted_by_errors { build::construct_error(cx, body_id) - } else if let hir::BodyOwnerKind::Fn = cx.body_owner_kind { + } else if cx.body_owner_kind.is_fn_or_closure() { // fetch the fully liberated fn signature (that is, all bound // types/lifetimes replaced) let fn_hir_id = tcx.hir().node_to_hir_id(id); diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index b44c2cc9c166a..78abba5f885b2 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -613,6 +613,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { hir::BodyOwnerKind::Static(_) => // No need to free storage in this context. None, + hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => Some(self.topmost_scope()), } diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 6113d88e09591..f514cac6326be 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -61,6 +61,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { let constness = match body_owner_kind { hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => hir::Constness::Const, + hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => hir::Constness::NotConst, }; diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 8b970c1408e37..9f0907adc9892 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -1,6 +1,5 @@ //! Inlining pass for MIR functions -use rustc::hir; use rustc::hir::CodegenFnAttrFlags; use rustc::hir::def_id::DefId; @@ -74,15 +73,12 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { // Only do inlining into fn bodies. let id = self.tcx.hir().as_local_node_id(self.source.def_id).unwrap(); - let body_owner_kind = self.tcx.hir().body_owner_kind(id); - - if let (hir::BodyOwnerKind::Fn, None) = (body_owner_kind, self.source.promoted) { - + if self.tcx.hir().body_owner_kind(id).is_fn_or_closure() && self.source.promoted.is_none() { for (bb, bb_data) in caller_mir.basic_blocks().iter_enumerated() { if let Some(callsite) = self.get_valid_function_call(bb, - bb_data, - caller_mir, - param_env) { + bb_data, + caller_mir, + param_env) { callsites.push_back(callsite); } } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 78cf7153500c9..2d941902debc3 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1152,6 +1152,7 @@ impl MirPass for QualifyAndPromoteConstants { let id = tcx.hir().as_local_node_id(def_id).unwrap(); let mut const_promoted_temps = None; let mode = match tcx.hir().body_owner_kind(id) { + hir::BodyOwnerKind::Closure => Mode::Fn, hir::BodyOwnerKind::Fn => { if tcx.is_const_fn(def_id) { Mode::ConstFn diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index fca208b340d2a..f4685e0ddc909 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -573,6 +573,7 @@ fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut dyn Write) -> i let body_owner_kind = tcx.hir().body_owner_kind(id); match (body_owner_kind, src.promoted) { (_, Some(i)) => write!(w, "{:?} in", i)?, + (hir::BodyOwnerKind::Closure, _) | (hir::BodyOwnerKind::Fn, _) => write!(w, "fn")?, (hir::BodyOwnerKind::Const, _) => write!(w, "const")?, (hir::BodyOwnerKind::Static(hir::MutImmutable), _) => write!(w, "static")?, @@ -585,6 +586,7 @@ fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut dyn Write) -> i })?; match (body_owner_kind, src.promoted) { + (hir::BodyOwnerKind::Closure, None) | (hir::BodyOwnerKind::Fn, None) => { write!(w, "(")?; diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 49914dc7078fd..c11b1af97766d 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -191,6 +191,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> { self.in_static = false; match self.tcx.hir().body_owner_kind(item_id) { + hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => self.in_fn = true, hir::BodyOwnerKind::Static(_) => self.in_static = true, _ => {} From aedc3a51dfab0fa7205f1c0fd68a4e62dd6df712 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 7 Dec 2018 18:26:46 +0100 Subject: [PATCH 2/2] Declare some unconst operations as unsafe in const fn --- src/librustc_mir/transform/check_unsafety.rs | 97 +++++++++++++++---- src/test/ui/cast/cast-ptr-to-int-const.rs | 8 +- src/test/ui/cast/cast-ptr-to-int-const.stderr | 12 +-- .../ui/consts/const-eval/const_raw_ptr_ops.rs | 8 +- .../const-eval/const_raw_ptr_ops.stderr | 16 +-- .../ui/consts/min_const_fn/cmp_fn_pointers.rs | 2 +- .../min_const_fn/min_const_fn.nll.stderr | 52 ++++++---- .../ui/consts/min_const_fn/min_const_fn.rs | 8 +- .../consts/min_const_fn/min_const_fn.stderr | 50 ++++++---- src/test/ui/error-codes/E0395.rs | 2 +- src/test/ui/error-codes/E0395.stderr | 6 +- src/test/ui/issues/issue-17458.rs | 2 +- src/test/ui/issues/issue-17458.stderr | 6 +- src/test/ui/issues/issue-18294.rs | 2 +- src/test/ui/issues/issue-18294.stderr | 6 +- src/test/ui/issues/issue-25826.rs | 2 +- src/test/ui/issues/issue-25826.stderr | 6 +- 17 files changed, 187 insertions(+), 98 deletions(-) diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index eb151b56bed65..ab8da2f352c1c 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -4,6 +4,7 @@ use rustc_data_structures::sync::Lrc; use rustc::ty::query::Providers; use rustc::ty::{self, TyCtxt}; +use rustc::ty::cast::CastTy; use rustc::hir; use rustc::hir::Node; use rustc::hir::def_id::DefId; @@ -20,6 +21,7 @@ use util; pub struct UnsafetyChecker<'a, 'tcx: 'a> { mir: &'a Mir<'tcx>, + const_context: bool, min_const_fn: bool, source_scope_local_data: &'a IndexVec, violations: Vec, @@ -33,14 +35,20 @@ pub struct UnsafetyChecker<'a, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> UnsafetyChecker<'a, 'tcx> { fn new( + const_context: bool, min_const_fn: bool, mir: &'a Mir<'tcx>, source_scope_local_data: &'a IndexVec, tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Self { + // sanity check + if min_const_fn { + assert!(const_context); + } Self { mir, + const_context, min_const_fn, source_scope_local_data, violations: vec![], @@ -124,29 +132,70 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { rvalue: &Rvalue<'tcx>, location: Location) { - if let &Rvalue::Aggregate(box ref aggregate, _) = rvalue { - match aggregate { - &AggregateKind::Array(..) | - &AggregateKind::Tuple => {} - &AggregateKind::Adt(ref def, ..) => { - match self.tcx.layout_scalar_valid_range(def.did) { - (Bound::Unbounded, Bound::Unbounded) => {}, - _ => self.require_unsafe( - "initializing type with `rustc_layout_scalar_valid_range` attr", - "initializing a layout restricted type's field with a value outside \ - the valid range is undefined behavior", - UnsafetyViolationKind::GeneralAndConstFn, - ), + match rvalue { + Rvalue::Aggregate(box ref aggregate, _) => { + match aggregate { + &AggregateKind::Array(..) | + &AggregateKind::Tuple => {} + &AggregateKind::Adt(ref def, ..) => { + match self.tcx.layout_scalar_valid_range(def.did) { + (Bound::Unbounded, Bound::Unbounded) => {}, + _ => self.require_unsafe( + "initializing type with `rustc_layout_scalar_valid_range` attr", + "initializing a layout restricted type's field with a value \ + outside the valid range is undefined behavior", + UnsafetyViolationKind::GeneralAndConstFn, + ), + } + } + &AggregateKind::Closure(def_id, _) | + &AggregateKind::Generator(def_id, _, _) => { + let UnsafetyCheckResult { + violations, unsafe_blocks + } = self.tcx.unsafety_check_result(def_id); + self.register_violations(&violations, &unsafe_blocks); } } - &AggregateKind::Closure(def_id, _) | - &AggregateKind::Generator(def_id, _, _) => { - let UnsafetyCheckResult { - violations, unsafe_blocks - } = self.tcx.unsafety_check_result(def_id); - self.register_violations(&violations, &unsafe_blocks); + }, + // casting pointers to ints is unsafe in const fn because the const evaluator cannot + // possibly know what the result of various operations like `address / 2` would be + // pointers during const evaluation have no integral address, only an abstract one + Rvalue::Cast(CastKind::Misc, ref operand, cast_ty) + if self.const_context && self.tcx.features().const_raw_ptr_to_usize_cast => { + let operand_ty = operand.ty(self.mir, self.tcx); + let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast"); + let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast"); + match (cast_in, cast_out) { + (CastTy::Ptr(_), CastTy::Int(_)) | + (CastTy::FnPtr, CastTy::Int(_)) => { + self.register_violations(&[UnsafetyViolation { + source_info: self.source_info, + description: Symbol::intern("cast of pointer to int").as_interned_str(), + details: Symbol::intern("casting pointers to integers in constants") + .as_interned_str(), + kind: UnsafetyViolationKind::General, + }], &[]); + }, + _ => {}, } } + // raw pointer and fn pointer operations are unsafe as it is not clear whether one + // pointer would be "less" or "equal" to another, because we cannot know where llvm + // or the linker will place various statics in memory. Without this information the + // result of a comparison of addresses would differ between runtime and compile-time. + Rvalue::BinaryOp(_, ref lhs, _) + if self.const_context && self.tcx.features().const_compare_raw_pointers => { + if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.mir, self.tcx).sty { + self.register_violations(&[UnsafetyViolation { + source_info: self.source_info, + description: Symbol::intern("pointer operation").as_interned_str(), + details: Symbol::intern("operations on pointers in constants") + .as_interned_str(), + kind: UnsafetyViolationKind::General, + }], &[]); + } + } + _ => {}, } self.super_rvalue(rvalue, location); } @@ -484,8 +533,16 @@ fn unsafety_check_result<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) }; let param_env = tcx.param_env(def_id); + + let id = tcx.hir().as_local_node_id(def_id).unwrap(); + let (const_context, min_const_fn) = match tcx.hir().body_owner_kind(id) { + hir::BodyOwnerKind::Closure => (false, false), + hir::BodyOwnerKind::Fn => (tcx.is_const_fn(def_id), tcx.is_min_const_fn(def_id)), + hir::BodyOwnerKind::Const | + hir::BodyOwnerKind::Static(_) => (true, false), + }; let mut checker = UnsafetyChecker::new( - tcx.is_min_const_fn(def_id), + const_context, min_const_fn, mir, source_scope_local_data, tcx, param_env); checker.visit_mir(mir); diff --git a/src/test/ui/cast/cast-ptr-to-int-const.rs b/src/test/ui/cast/cast-ptr-to-int-const.rs index 70b4869ef63ce..ac153cb57423f 100644 --- a/src/test/ui/cast/cast-ptr-to-int-const.rs +++ b/src/test/ui/cast/cast-ptr-to-int-const.rs @@ -1,7 +1,11 @@ // gate-test-const_raw_ptr_to_usize_cast fn main() { - const X: u32 = main as u32; //~ ERROR casting pointers to integers in constants is unstable + const X: u32 = unsafe { + main as u32 //~ ERROR casting pointers to integers in constants is unstable + }; const Y: u32 = 0; - const Z: u32 = &Y as *const u32 as u32; //~ ERROR is unstable + const Z: u32 = unsafe { + &Y as *const u32 as u32 //~ ERROR is unstable + }; } diff --git a/src/test/ui/cast/cast-ptr-to-int-const.stderr b/src/test/ui/cast/cast-ptr-to-int-const.stderr index 3cce07d64ecd0..d04595ee4e887 100644 --- a/src/test/ui/cast/cast-ptr-to-int-const.stderr +++ b/src/test/ui/cast/cast-ptr-to-int-const.stderr @@ -1,16 +1,16 @@ error[E0658]: casting pointers to integers in constants is unstable (see issue #51910) - --> $DIR/cast-ptr-to-int-const.rs:4:20 + --> $DIR/cast-ptr-to-int-const.rs:5:9 | -LL | const X: u32 = main as u32; //~ ERROR casting pointers to integers in constants is unstable - | ^^^^^^^^^^^ +LL | main as u32 //~ ERROR casting pointers to integers in constants is unstable + | ^^^^^^^^^^^ | = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable error[E0658]: casting pointers to integers in constants is unstable (see issue #51910) - --> $DIR/cast-ptr-to-int-const.rs:6:20 + --> $DIR/cast-ptr-to-int-const.rs:9:9 | -LL | const Z: u32 = &Y as *const u32 as u32; //~ ERROR is unstable - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | &Y as *const u32 as u32 //~ ERROR is unstable + | ^^^^^^^^^^^^^^^^^^^^^^^ | = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs b/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs index 63bac17f1c0f3..44266682a5c6c 100644 --- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs @@ -3,13 +3,13 @@ fn main() {} // unconst and bad, will thus error in miri -const X: bool = &1 as *const i32 == &2 as *const i32; //~ ERROR any use of this value will cause +const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR any use of this // unconst and fine -const X2: bool = 42 as *const i32 == 43 as *const i32; +const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; // unconst and fine -const Y: usize = 42usize as *const i32 as usize + 1; +const Y: usize = unsafe { 42usize as *const i32 as usize + 1 }; // unconst and bad, will thus error in miri -const Y2: usize = &1 as *const i32 as usize + 1; //~ ERROR any use of this value will cause +const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; //~ ERROR any use of this // unconst and fine const Z: i32 = unsafe { *(&1 as *const i32) }; // unconst and bad, will thus error in miri diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr index ea11359af85ed..6be54c0bad4f9 100644 --- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr @@ -1,20 +1,20 @@ error: any use of this value will cause an error --> $DIR/const_raw_ptr_ops.rs:6:1 | -LL | const X: bool = &1 as *const i32 == &2 as *const i32; //~ ERROR any use of this value will cause - | ^^^^^^^^^^^^^^^^------------------------------------^ - | | - | "pointer arithmetic or comparison" needs an rfc before being allowed inside constants +LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR any use of this + | ^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^ + | | + | "pointer arithmetic or comparison" needs an rfc before being allowed inside constants | = note: #[deny(const_err)] on by default error: any use of this value will cause an error --> $DIR/const_raw_ptr_ops.rs:12:1 | -LL | const Y2: usize = &1 as *const i32 as usize + 1; //~ ERROR any use of this value will cause - | ^^^^^^^^^^^^^^^^^^-----------------------------^ - | | - | "pointer arithmetic or comparison" needs an rfc before being allowed inside constants +LL | const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; //~ ERROR any use of this + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------------^^^ + | | + | "pointer arithmetic or comparison" needs an rfc before being allowed inside constants error: any use of this value will cause an error --> $DIR/const_raw_ptr_ops.rs:16:1 diff --git a/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs index d8abd97655805..c2600f894dc42 100644 --- a/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs +++ b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs @@ -1,5 +1,5 @@ const fn cmp(x: fn(), y: fn()) -> bool { //~ ERROR function pointers in const fn are unstable - x == y + unsafe { x == y } } fn main() {} diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr index 91b076097b018..763c69e805030 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr @@ -95,97 +95,109 @@ LL | const fn foo30(x: *const u32) -> usize { x as usize } | ^^^^^^^^^^ error: casting pointers to ints is unstable in const fn - --> $DIR/min_const_fn.rs:94:42 + --> $DIR/min_const_fn.rs:94:63 + | +LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } } + | ^^^^^^^^^^ + +error: casting pointers to ints is unstable in const fn + --> $DIR/min_const_fn.rs:96:42 | LL | const fn foo30_2(x: *mut u32) -> usize { x as usize } | ^^^^^^^^^^ +error: casting pointers to ints is unstable in const fn + --> $DIR/min_const_fn.rs:98:63 + | +LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } } + | ^^^^^^^^^^ + error: `if`, `match`, `&&` and `||` are not stable in const fn - --> $DIR/min_const_fn.rs:96:38 + --> $DIR/min_const_fn.rs:100:38 | LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } } | ^^^^^^^^^^^^^^^^^^^^^^ error: `if`, `match`, `&&` and `||` are not stable in const fn - --> $DIR/min_const_fn.rs:98:29 + --> $DIR/min_const_fn.rs:102:29 | LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn | ^^^^^^^^^^^ error: `if`, `match`, `&&` and `||` are not stable in const fn - --> $DIR/min_const_fn.rs:100:44 + --> $DIR/min_const_fn.rs:104:44 | LL | const fn foo36(a: bool, b: bool) -> bool { a && b } | ^^^^^^ error: `if`, `match`, `&&` and `||` are not stable in const fn - --> $DIR/min_const_fn.rs:102:44 + --> $DIR/min_const_fn.rs:106:44 | LL | const fn foo37(a: bool, b: bool) -> bool { a || b } | ^^^^^^ error: mutable references in const fn are unstable - --> $DIR/min_const_fn.rs:104:14 + --> $DIR/min_const_fn.rs:108:14 | LL | const fn inc(x: &mut i32) { *x += 1 } | ^ error: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:109:6 + --> $DIR/min_const_fn.rs:113:6 | LL | impl Foo { | ^ error: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:114:6 + --> $DIR/min_const_fn.rs:118:6 | LL | impl Foo { | ^ error: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:119:6 + --> $DIR/min_const_fn.rs:123:6 | LL | impl Foo { | ^ error: `impl Trait` in const fn is unstable - --> $DIR/min_const_fn.rs:125:24 + --> $DIR/min_const_fn.rs:129:24 | LL | const fn no_rpit2() -> AlanTuring { AlanTuring(0) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:127:34 + --> $DIR/min_const_fn.rs:131:34 | LL | const fn no_apit2(_x: AlanTuring) {} | ^^^^^^^^^^^^^^^^^^^^ error: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:129:22 + --> $DIR/min_const_fn.rs:133:22 | LL | const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized` | ^^^^^^^^^^^^^^^^^^^^ error: `impl Trait` in const fn is unstable - --> $DIR/min_const_fn.rs:130:23 + --> $DIR/min_const_fn.rs:134:23 | LL | const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable | ^^^^^^^^^^^^^^^^^^^^ error: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:131:23 + --> $DIR/min_const_fn.rs:135:23 | LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized` | ^^ error: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:132:32 + --> $DIR/min_const_fn.rs:136:32 | LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning[E0515]: cannot return reference to temporary value - --> $DIR/min_const_fn.rs:132:63 + --> $DIR/min_const_fn.rs:136:63 | LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } | ^-- @@ -197,24 +209,24 @@ LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future error: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:137:41 + --> $DIR/min_const_fn.rs:141:41 | LL | const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: function pointers in const fn are unstable - --> $DIR/min_const_fn.rs:140:21 + --> $DIR/min_const_fn.rs:144:21 | LL | const fn no_fn_ptrs(_x: fn()) {} | ^^ error: function pointers in const fn are unstable - --> $DIR/min_const_fn.rs:142:27 + --> $DIR/min_const_fn.rs:146:27 | LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo } | ^^^^ -error: aborting due to 34 previous errors +error: aborting due to 36 previous errors Some errors occurred: E0493, E0515. For more information about an error, try `rustc --explain E0493`. diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.rs b/src/test/ui/consts/min_const_fn/min_const_fn.rs index 05cf3d5f1f173..ee3ffcd4026d3 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn.rs @@ -90,9 +90,13 @@ static BAR: u32 = 42; const fn foo25() -> u32 { BAR } //~ ERROR cannot access `static` items in const fn const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot access `static` items const fn foo30(x: *const u32) -> usize { x as usize } -//~^ ERROR casting pointers to int +//~^ ERROR casting pointers to ints is unstable +const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } } +//~^ ERROR casting pointers to ints is unstable const fn foo30_2(x: *mut u32) -> usize { x as usize } -//~^ ERROR casting pointers to int +//~^ ERROR casting pointers to ints is unstable +const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } } +//~^ ERROR casting pointers to ints is unstable const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } } //~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr index 2cae714fbf727..52c60c57b8fb3 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr @@ -95,113 +95,125 @@ LL | const fn foo30(x: *const u32) -> usize { x as usize } | ^^^^^^^^^^ error: casting pointers to ints is unstable in const fn - --> $DIR/min_const_fn.rs:94:42 + --> $DIR/min_const_fn.rs:94:63 + | +LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } } + | ^^^^^^^^^^ + +error: casting pointers to ints is unstable in const fn + --> $DIR/min_const_fn.rs:96:42 | LL | const fn foo30_2(x: *mut u32) -> usize { x as usize } | ^^^^^^^^^^ +error: casting pointers to ints is unstable in const fn + --> $DIR/min_const_fn.rs:98:63 + | +LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } } + | ^^^^^^^^^^ + error: `if`, `match`, `&&` and `||` are not stable in const fn - --> $DIR/min_const_fn.rs:96:38 + --> $DIR/min_const_fn.rs:100:38 | LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } } | ^^^^^^^^^^^^^^^^^^^^^^ error: `if`, `match`, `&&` and `||` are not stable in const fn - --> $DIR/min_const_fn.rs:98:29 + --> $DIR/min_const_fn.rs:102:29 | LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn | ^^^^^^^^^^^ error: `if`, `match`, `&&` and `||` are not stable in const fn - --> $DIR/min_const_fn.rs:100:44 + --> $DIR/min_const_fn.rs:104:44 | LL | const fn foo36(a: bool, b: bool) -> bool { a && b } | ^^^^^^ error: `if`, `match`, `&&` and `||` are not stable in const fn - --> $DIR/min_const_fn.rs:102:44 + --> $DIR/min_const_fn.rs:106:44 | LL | const fn foo37(a: bool, b: bool) -> bool { a || b } | ^^^^^^ error: mutable references in const fn are unstable - --> $DIR/min_const_fn.rs:104:14 + --> $DIR/min_const_fn.rs:108:14 | LL | const fn inc(x: &mut i32) { *x += 1 } | ^ error: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:109:6 + --> $DIR/min_const_fn.rs:113:6 | LL | impl Foo { | ^ error: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:114:6 + --> $DIR/min_const_fn.rs:118:6 | LL | impl Foo { | ^ error: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:119:6 + --> $DIR/min_const_fn.rs:123:6 | LL | impl Foo { | ^ error: `impl Trait` in const fn is unstable - --> $DIR/min_const_fn.rs:125:24 + --> $DIR/min_const_fn.rs:129:24 | LL | const fn no_rpit2() -> AlanTuring { AlanTuring(0) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:127:34 + --> $DIR/min_const_fn.rs:131:34 | LL | const fn no_apit2(_x: AlanTuring) {} | ^^^^^^^^^^^^^^^^^^^^ error: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:129:22 + --> $DIR/min_const_fn.rs:133:22 | LL | const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized` | ^^^^^^^^^^^^^^^^^^^^ error: `impl Trait` in const fn is unstable - --> $DIR/min_const_fn.rs:130:23 + --> $DIR/min_const_fn.rs:134:23 | LL | const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable | ^^^^^^^^^^^^^^^^^^^^ error: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:131:23 + --> $DIR/min_const_fn.rs:135:23 | LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized` | ^^ error: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:132:32 + --> $DIR/min_const_fn.rs:136:32 | LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:137:41 + --> $DIR/min_const_fn.rs:141:41 | LL | const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: function pointers in const fn are unstable - --> $DIR/min_const_fn.rs:140:21 + --> $DIR/min_const_fn.rs:144:21 | LL | const fn no_fn_ptrs(_x: fn()) {} | ^^ error: function pointers in const fn are unstable - --> $DIR/min_const_fn.rs:142:27 + --> $DIR/min_const_fn.rs:146:27 | LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo } | ^^^^ -error: aborting due to 34 previous errors +error: aborting due to 36 previous errors For more information about this error, try `rustc --explain E0493`. diff --git a/src/test/ui/error-codes/E0395.rs b/src/test/ui/error-codes/E0395.rs index c2de56c413f05..9657bbdeadc17 100644 --- a/src/test/ui/error-codes/E0395.rs +++ b/src/test/ui/error-codes/E0395.rs @@ -3,6 +3,6 @@ static FOO: i32 = 42; static BAR: i32 = 42; -static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR issue #53020 +static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR issue #53020 fn main() { } diff --git a/src/test/ui/error-codes/E0395.stderr b/src/test/ui/error-codes/E0395.stderr index 45e1ba05ff996..cc7d94e22eb6b 100644 --- a/src/test/ui/error-codes/E0395.stderr +++ b/src/test/ui/error-codes/E0395.stderr @@ -1,8 +1,8 @@ error[E0658]: comparing raw pointers inside static (see issue #53020) - --> $DIR/E0395.rs:6:22 + --> $DIR/E0395.rs:6:29 | -LL | static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR issue #53020 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR issue #53020 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add #![feature(const_compare_raw_pointers)] to the crate attributes to enable diff --git a/src/test/ui/issues/issue-17458.rs b/src/test/ui/issues/issue-17458.rs index d7a1752b96c44..444e94d829bf8 100644 --- a/src/test/ui/issues/issue-17458.rs +++ b/src/test/ui/issues/issue-17458.rs @@ -1,4 +1,4 @@ -static X: usize = 0 as *const usize as usize; +static X: usize = unsafe { 0 as *const usize as usize }; //~^ ERROR: casting pointers to integers in statics is unstable fn main() { diff --git a/src/test/ui/issues/issue-17458.stderr b/src/test/ui/issues/issue-17458.stderr index 04921419ae01a..a1a8ed9f0cdcb 100644 --- a/src/test/ui/issues/issue-17458.stderr +++ b/src/test/ui/issues/issue-17458.stderr @@ -1,8 +1,8 @@ error[E0658]: casting pointers to integers in statics is unstable (see issue #51910) - --> $DIR/issue-17458.rs:1:19 + --> $DIR/issue-17458.rs:1:28 | -LL | static X: usize = 0 as *const usize as usize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | static X: usize = unsafe { 0 as *const usize as usize }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable diff --git a/src/test/ui/issues/issue-18294.rs b/src/test/ui/issues/issue-18294.rs index df4fd1642f2bc..1c2229fb9eae4 100644 --- a/src/test/ui/issues/issue-18294.rs +++ b/src/test/ui/issues/issue-18294.rs @@ -1,5 +1,5 @@ fn main() { const X: u32 = 1; - const Y: usize = &X as *const u32 as usize; //~ ERROR is unstable + const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR is unstable println!("{}", Y); } diff --git a/src/test/ui/issues/issue-18294.stderr b/src/test/ui/issues/issue-18294.stderr index 2af7f45628e37..f3e8ab1a31307 100644 --- a/src/test/ui/issues/issue-18294.stderr +++ b/src/test/ui/issues/issue-18294.stderr @@ -1,8 +1,8 @@ error[E0658]: casting pointers to integers in constants is unstable (see issue #51910) - --> $DIR/issue-18294.rs:3:22 + --> $DIR/issue-18294.rs:3:31 | -LL | const Y: usize = &X as *const u32 as usize; //~ ERROR is unstable - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR is unstable + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable diff --git a/src/test/ui/issues/issue-25826.rs b/src/test/ui/issues/issue-25826.rs index e6022653d9c3b..36a69cf4c22ff 100644 --- a/src/test/ui/issues/issue-25826.rs +++ b/src/test/ui/issues/issue-25826.rs @@ -1,6 +1,6 @@ fn id(t: T) -> T { t } fn main() { - const A: bool = id:: as *const () < id:: as *const (); + const A: bool = unsafe { id:: as *const () < id:: as *const () }; //~^ ERROR comparing raw pointers inside constant println!("{}", A); } diff --git a/src/test/ui/issues/issue-25826.stderr b/src/test/ui/issues/issue-25826.stderr index 73ebf29d08e78..dc547f7c32c94 100644 --- a/src/test/ui/issues/issue-25826.stderr +++ b/src/test/ui/issues/issue-25826.stderr @@ -1,8 +1,8 @@ error[E0658]: comparing raw pointers inside constant (see issue #53020) - --> $DIR/issue-25826.rs:3:21 + --> $DIR/issue-25826.rs:3:30 | -LL | const A: bool = id:: as *const () < id:: as *const (); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | const A: bool = unsafe { id:: as *const () < id:: as *const () }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add #![feature(const_compare_raw_pointers)] to the crate attributes to enable