Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove const_raw_ptr_to_usize_cast feature #87020

Merged
merged 3 commits into from Jul 10, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 0 additions & 3 deletions compiler/rustc_feature/src/active.rs
Expand Up @@ -416,9 +416,6 @@ declare_features! (
/// Allows accessing fields of unions inside `const` functions.
(active, const_fn_union, "1.27.0", Some(51909), None),

/// Allows casting raw pointers to `usize` during const eval.
(active, const_raw_ptr_to_usize_cast, "1.27.0", Some(51910), None),

/// Allows dereferencing raw pointers during const eval.
(active, const_raw_ptr_deref, "1.27.0", Some(51911), None),

Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_feature/src/removed.rs
Expand Up @@ -144,6 +144,10 @@ declare_features! (
(removed, external_doc, "1.54.0", Some(44732), None,
Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations")),

/// Allows casting raw pointers to `usize` during const eval.
(removed, const_raw_ptr_to_usize_cast, "1.55.0", Some(51910), None,
Some("at compile-time, pointers do not have an integer value, so these casts cannot be properly supported")),

// -------------------------------------------------------------------------
// feature-group-end: removed features
// -------------------------------------------------------------------------
Expand Down
25 changes: 15 additions & 10 deletions compiler/rustc_mir/src/transform/check_consts/ops.rs
Expand Up @@ -397,6 +397,9 @@ impl NonConstOp for PanicNonStr {
}
}

/// Comparing raw pointers for equality.
/// Not currently intended to ever be allowed, even behind a feature gate: operation depends on
/// allocation base addresses that are not known at compile-time.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any other "ops" that should get a comment like this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well... there are similarly unallowable things. thread local statics, static mut, inline asm, ... they aren't really different, just more obvious?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm yeah those are less subtle.

#[derive(Debug)]
pub struct RawPtrComparison;
impl NonConstOp for RawPtrComparison {
Expand Down Expand Up @@ -430,20 +433,22 @@ impl NonConstOp for RawPtrDeref {
}
}

/// Casting raw pointer or function pointer to an integer.
/// Not currently intended to ever be allowed, even behind a feature gate: operation depends on
/// allocation base addresses that are not known at compile-time.
#[derive(Debug)]
pub struct RawPtrToIntCast;
impl NonConstOp for RawPtrToIntCast {
fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
Status::Unstable(sym::const_raw_ptr_to_usize_cast)
}

fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_raw_ptr_to_usize_cast,
span,
&format!("casting pointers to integers in {}s is unstable", ccx.const_kind(),),
)
let mut err = ccx
.tcx
.sess
.struct_span_err(span, "pointers cannot be cast to integers during const eval.");
err.note("at compile-time, pointers do not have an integer value");
err.note(
"avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior",
);
err
}
}

Expand Down
31 changes: 1 addition & 30 deletions compiler/rustc_mir/src/transform/check_unsafety.rs
Expand Up @@ -7,7 +7,6 @@ use rustc_hir::intravisit;
use rustc_hir::Node;
use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::cast::CastTy;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
Expand All @@ -18,7 +17,6 @@ use std::ops::Bound;
pub struct UnsafetyChecker<'a, 'tcx> {
body: &'a Body<'tcx>,
body_did: LocalDefId,
const_context: bool,
violations: Vec<UnsafetyViolation>,
source_info: SourceInfo,
tcx: TyCtxt<'tcx>,
Expand All @@ -30,7 +28,6 @@ pub struct UnsafetyChecker<'a, 'tcx> {

impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
fn new(
const_context: bool,
body: &'a Body<'tcx>,
body_did: LocalDefId,
tcx: TyCtxt<'tcx>,
Expand All @@ -39,7 +36,6 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
Self {
body,
body_did,
const_context,
violations: vec![],
source_info: SourceInfo::outermost(body.span),
tcx,
Expand Down Expand Up @@ -136,25 +132,6 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
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.body, 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::FnPtr, CastTy::Int(_)) => {
self.require_unsafe(
UnsafetyViolationKind::General,
UnsafetyViolationDetails::CastOfPointerToInt,
);
}
_ => {}
}
}
_ => {}
}
self.super_rvalue(rvalue, location);
Expand Down Expand Up @@ -469,13 +446,7 @@ fn unsafety_check_result<'tcx>(

let param_env = tcx.param_env(def.did);

let id = tcx.hir().local_def_id_to_hir_id(def.did);
let const_context = match tcx.hir().body_owner_kind(id) {
hir::BodyOwnerKind::Closure => false,
hir::BodyOwnerKind::Fn => tcx.is_const_fn_raw(def.did.to_def_id()),
hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => true,
};
let mut checker = UnsafetyChecker::new(const_context, body, def.did, tcx, param_env);
let mut checker = UnsafetyChecker::new(body, def.did, tcx, param_env);
checker.visit_body(&body);

check_unused_unsafe(tcx, def.did, &checker.used_unsafe, &mut checker.inherited_blocks);
Expand Down
21 changes: 0 additions & 21 deletions compiler/rustc_mir_build/src/check_unsafety.rs
Expand Up @@ -25,7 +25,6 @@ struct UnsafetyVisitor<'a, 'tcx> {
/// The `#[target_feature]` attributes of the body. Used for checking
/// calls to functions with `#[target_feature]` (RFC 2396).
body_target_features: &'tcx Vec<Symbol>,
is_const: bool,
in_possible_lhs_union_assign: bool,
in_union_destructure: bool,
}
Expand Down Expand Up @@ -315,16 +314,6 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
(Bound::Unbounded, Bound::Unbounded) => {}
_ => self.requires_unsafe(expr.span, InitializingTypeWith),
},
ExprKind::Cast { source } => {
let source = &self.thir[source];
if self.tcx.features().const_raw_ptr_to_usize_cast
&& self.is_const
&& (source.ty.is_unsafe_ptr() || source.ty.is_fn_ptr())
&& expr.ty.is_integral()
{
self.requires_unsafe(expr.span, CastOfPointerToInt);
}
}
ExprKind::Closure {
closure_id,
substs: _,
Expand Down Expand Up @@ -413,7 +402,6 @@ enum UnsafeOpKind {
CallToUnsafeFunction,
UseOfInlineAssembly,
InitializingTypeWith,
CastOfPointerToInt,
UseOfMutableStatic,
UseOfExternStatic,
DerefOfRawPointer,
Expand Down Expand Up @@ -446,9 +434,6 @@ impl UnsafeOpKind {
"initializing a layout restricted type's field with a value outside the valid \
range is undefined behavior",
),
CastOfPointerToInt => {
("cast of pointer to int", "casting pointers to integers in constants")
}
UseOfMutableStatic => (
"use of mutable static",
"mutable statics can be mutated by multiple threads: aliasing violations or data \
Expand Down Expand Up @@ -526,19 +511,13 @@ pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalD
let body_target_features = &tcx.codegen_fn_attrs(def.did).target_features;
let safety_context =
if body_unsafety.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe };
let is_const = match tcx.hir().body_owner_kind(hir_id) {
hir::BodyOwnerKind::Closure => false,
hir::BodyOwnerKind::Fn => tcx.is_const_fn_raw(def.did.to_def_id()),
hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => true,
};
let mut visitor = UnsafetyVisitor {
tcx,
thir,
safety_context,
hir_context: hir_id,
body_unsafety,
body_target_features,
is_const,
in_possible_lhs_union_assign: false,
in_union_destructure: false,
};
Expand Down
19 changes: 0 additions & 19 deletions src/test/ui/cast/cast-ptr-to-int-const.mir.stderr

This file was deleted.

19 changes: 0 additions & 19 deletions src/test/ui/cast/cast-ptr-to-int-const.rs

This file was deleted.

19 changes: 0 additions & 19 deletions src/test/ui/cast/cast-ptr-to-int-const.thir.stderr

This file was deleted.

13 changes: 0 additions & 13 deletions src/test/ui/cast/feature-gate-const_raw_ptr_to_usize_cast.rs

This file was deleted.

30 changes: 0 additions & 30 deletions src/test/ui/cast/feature-gate-const_raw_ptr_to_usize_cast.stderr

This file was deleted.

13 changes: 0 additions & 13 deletions src/test/ui/const-ptr/ptr_to_usize_cast.rs

This file was deleted.

14 changes: 0 additions & 14 deletions src/test/ui/const-ptr/ptr_to_usize_cast.stderr

This file was deleted.

12 changes: 4 additions & 8 deletions src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs
@@ -1,15 +1,11 @@
#![feature(const_raw_ptr_to_usize_cast, const_raw_ptr_deref)]
#![feature(const_raw_ptr_deref)]

fn main() {}

// unconst and fine
const Y: usize = unsafe { 42usize as *const i32 as usize + 1 };
// unconst and bad, will thus error in miri
const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; //~ ERROR any use of this
//~| WARN this was previously accepted by the compiler but is being phased out
// unconst and fine
// fine
const Z: i32 = unsafe { *(&1 as *const i32) };
// unconst and bad, will thus error in miri

// bad, will thus error in miri
const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR any use of this value will cause
//~| WARN this was previously accepted by the compiler but is being phased out
const Z3: i32 = unsafe { *(44 as *const i32) }; //~ ERROR any use of this value will cause
Expand Down
19 changes: 4 additions & 15 deletions src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr
@@ -1,28 +1,17 @@
error: any use of this value will cause an error
--> $DIR/const_raw_ptr_ops2.rs:8:28
|
LL | const Y2: usize = unsafe { &1 as *const i32 as usize + 1 };
| ---------------------------^^^^^^^^^^^^^^^^^^^^^^^^^-------
| |
| cannot cast pointer to integer because it was not created by cast from integer
|
= note: `#[deny(const_err)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>

error: any use of this value will cause an error
--> $DIR/const_raw_ptr_ops2.rs:13:26
--> $DIR/const_raw_ptr_ops2.rs:9:26
|
LL | const Z2: i32 = unsafe { *(42 as *const i32) };
| -------------------------^^^^^^^^^^^^^^^^^^^---
| |
| unable to turn bytes into a pointer
|
= note: `#[deny(const_err)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>

error: any use of this value will cause an error
--> $DIR/const_raw_ptr_ops2.rs:15:26
--> $DIR/const_raw_ptr_ops2.rs:11:26
|
LL | const Z3: i32 = unsafe { *(44 as *const i32) };
| -------------------------^^^^^^^^^^^^^^^^^^^---
Expand All @@ -32,5 +21,5 @@ LL | const Z3: i32 = unsafe { *(44 as *const i32) };
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>

error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

2 changes: 1 addition & 1 deletion src/test/ui/consts/const-eval/issue-52442.rs
@@ -1,4 +1,4 @@
fn main() {
[(); { &loop { break } as *const _ as usize } ];
//~^ ERROR casting pointers to integers in constants is unstable
//~^ ERROR pointers cannot be cast to integers during const eval
RalfJung marked this conversation as resolved.
Show resolved Hide resolved
}