Rollup merge of #73398 - oli-obk:const_raw_ptr_cmp, r=varkor,RalfJung,nagisa
A way forward for pointer equality in const eval r? @varkor on the first commit and @RalfJung on the second commit cc #53020
This commit is contained in:
commit
ae38698e7f
39 changed files with 358 additions and 201 deletions
|
@ -60,7 +60,7 @@ impl<T> RawVec<T, Global> {
|
||||||
/// `#[rustc_force_min_const_fn]` attribute which requires conformance
|
/// `#[rustc_force_min_const_fn]` attribute which requires conformance
|
||||||
/// with `min_const_fn` but does not necessarily allow calling it in
|
/// with `min_const_fn` but does not necessarily allow calling it in
|
||||||
/// `stable(...) const fn` / user code not enabling `foo` when
|
/// `stable(...) const fn` / user code not enabling `foo` when
|
||||||
/// `#[rustc_const_unstable(feature = "foo", ..)]` is present.
|
/// `#[rustc_const_unstable(feature = "foo", issue = "01234")]` is present.
|
||||||
pub const NEW: Self = Self::new();
|
pub const NEW: Self = Self::new();
|
||||||
|
|
||||||
/// Creates the biggest possible `RawVec` (on the system heap)
|
/// Creates the biggest possible `RawVec` (on the system heap)
|
||||||
|
|
|
@ -1012,7 +1012,7 @@ extern "rust-intrinsic" {
|
||||||
///
|
///
|
||||||
/// The stabilized version of this intrinsic is
|
/// The stabilized version of this intrinsic is
|
||||||
/// [`std::any::type_name`](../../std/any/fn.type_name.html)
|
/// [`std::any::type_name`](../../std/any/fn.type_name.html)
|
||||||
#[rustc_const_unstable(feature = "const_type_name", issue = "none")]
|
#[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
|
||||||
pub fn type_name<T: ?Sized>() -> &'static str;
|
pub fn type_name<T: ?Sized>() -> &'static str;
|
||||||
|
|
||||||
/// Gets an identifier which is globally unique to the specified type. This
|
/// Gets an identifier which is globally unique to the specified type. This
|
||||||
|
@ -1021,7 +1021,7 @@ extern "rust-intrinsic" {
|
||||||
///
|
///
|
||||||
/// The stabilized version of this intrinsic is
|
/// The stabilized version of this intrinsic is
|
||||||
/// [`std::any::TypeId::of`](../../std/any/struct.TypeId.html#method.of)
|
/// [`std::any::TypeId::of`](../../std/any/struct.TypeId.html#method.of)
|
||||||
#[rustc_const_unstable(feature = "const_type_id", issue = "none")]
|
#[rustc_const_unstable(feature = "const_type_id", issue = "41875")]
|
||||||
pub fn type_id<T: ?Sized + 'static>() -> u64;
|
pub fn type_id<T: ?Sized + 'static>() -> u64;
|
||||||
|
|
||||||
/// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
|
/// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
|
||||||
|
@ -1931,7 +1931,7 @@ extern "rust-intrinsic" {
|
||||||
pub fn nontemporal_store<T>(ptr: *mut T, val: T);
|
pub fn nontemporal_store<T>(ptr: *mut T, val: T);
|
||||||
|
|
||||||
/// See documentation of `<*const T>::offset_from` for details.
|
/// See documentation of `<*const T>::offset_from` for details.
|
||||||
#[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "none")]
|
#[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "41079")]
|
||||||
pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
|
pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
|
||||||
|
|
||||||
/// Internal hook used by Miri to implement unwinding.
|
/// Internal hook used by Miri to implement unwinding.
|
||||||
|
@ -1948,6 +1948,16 @@ extern "rust-intrinsic" {
|
||||||
#[cfg(not(bootstrap))]
|
#[cfg(not(bootstrap))]
|
||||||
#[lang = "count_code_region"]
|
#[lang = "count_code_region"]
|
||||||
pub fn count_code_region(index: u32);
|
pub fn count_code_region(index: u32);
|
||||||
|
|
||||||
|
/// See documentation of `<*const T>::guaranteed_eq` for details.
|
||||||
|
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
pub fn ptr_guaranteed_eq<T>(ptr: *const T, other: *const T) -> bool;
|
||||||
|
|
||||||
|
/// See documentation of `<*const T>::guaranteed_ne` for details.
|
||||||
|
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
pub fn ptr_guaranteed_ne<T>(ptr: *const T, other: *const T) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some functions are defined here because they accidentally got made
|
// Some functions are defined here because they accidentally got made
|
||||||
|
|
|
@ -87,6 +87,7 @@
|
||||||
#![feature(const_generics)]
|
#![feature(const_generics)]
|
||||||
#![feature(const_ptr_offset)]
|
#![feature(const_ptr_offset)]
|
||||||
#![feature(const_ptr_offset_from)]
|
#![feature(const_ptr_offset_from)]
|
||||||
|
#![cfg_attr(not(bootstrap), feature(const_raw_ptr_comparison))]
|
||||||
#![feature(const_result)]
|
#![feature(const_result)]
|
||||||
#![feature(const_slice_from_raw_parts)]
|
#![feature(const_slice_from_raw_parts)]
|
||||||
#![feature(const_slice_ptr_len)]
|
#![feature(const_slice_ptr_len)]
|
||||||
|
|
|
@ -295,6 +295,72 @@ impl<T: ?Sized> *const T {
|
||||||
intrinsics::ptr_offset_from(self, origin)
|
intrinsics::ptr_offset_from(self, origin)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns whether two pointers are guaranteed to be equal.
|
||||||
|
///
|
||||||
|
/// At runtime this function behaves like `self == other`.
|
||||||
|
/// However, in some contexts (e.g., compile-time evaluation),
|
||||||
|
/// it is not always possible to determine equality of two pointers, so this function may
|
||||||
|
/// spuriously return `false` for pointers that later actually turn out to be equal.
|
||||||
|
/// But when it returns `true`, the pointers are guaranteed to be equal.
|
||||||
|
///
|
||||||
|
/// This function is the mirror of [`guaranteed_ne`], but not its inverse. There are pointer
|
||||||
|
/// comparisons for which both functions return `false`.
|
||||||
|
///
|
||||||
|
/// [`guaranteed_ne`]: #method.guaranteed_ne
|
||||||
|
///
|
||||||
|
/// The return value may change depending on the compiler version and unsafe code may not
|
||||||
|
/// rely on the result of this function for soundness. It is suggested to only use this function
|
||||||
|
/// for performance optimizations where spurious `false` return values by this function do not
|
||||||
|
/// affect the outcome, but just the performance.
|
||||||
|
/// The consequences of using this method to make runtime and compile-time code behave
|
||||||
|
/// differently have not been explored. This method should not be used to introduce such
|
||||||
|
/// differences, and it should also not be stabilized before we have a better understanding
|
||||||
|
/// of this issue.
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
|
||||||
|
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
|
||||||
|
#[inline]
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
pub const fn guaranteed_eq(self, other: *const T) -> bool
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
|
intrinsics::ptr_guaranteed_eq(self, other)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether two pointers are guaranteed to be inequal.
|
||||||
|
///
|
||||||
|
/// At runtime this function behaves like `self != other`.
|
||||||
|
/// However, in some contexts (e.g., compile-time evaluation),
|
||||||
|
/// it is not always possible to determine the inequality of two pointers, so this function may
|
||||||
|
/// spuriously return `false` for pointers that later actually turn out to be inequal.
|
||||||
|
/// But when it returns `true`, the pointers are guaranteed to be inequal.
|
||||||
|
///
|
||||||
|
/// This function is the mirror of [`guaranteed_eq`], but not its inverse. There are pointer
|
||||||
|
/// comparisons for which both functions return `false`.
|
||||||
|
///
|
||||||
|
/// [`guaranteed_eq`]: #method.guaranteed_eq
|
||||||
|
///
|
||||||
|
/// The return value may change depending on the compiler version and unsafe code may not
|
||||||
|
/// rely on the result of this function for soundness. It is suggested to only use this function
|
||||||
|
/// for performance optimizations where spurious `false` return values by this function do not
|
||||||
|
/// affect the outcome, but just the performance.
|
||||||
|
/// The consequences of using this method to make runtime and compile-time code behave
|
||||||
|
/// differently have not been explored. This method should not be used to introduce such
|
||||||
|
/// differences, and it should also not be stabilized before we have a better understanding
|
||||||
|
/// of this issue.
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
|
||||||
|
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
|
||||||
|
#[inline]
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
pub const fn guaranteed_ne(self, other: *const T) -> bool
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
|
intrinsics::ptr_guaranteed_ne(self, other)
|
||||||
|
}
|
||||||
|
|
||||||
/// Calculates the distance between two pointers. The returned value is in
|
/// Calculates the distance between two pointers. The returned value is in
|
||||||
/// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
|
/// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
|
||||||
///
|
///
|
||||||
|
|
|
@ -273,6 +273,72 @@ impl<T: ?Sized> *mut T {
|
||||||
if self.is_null() { None } else { Some(&mut *self) }
|
if self.is_null() { None } else { Some(&mut *self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns whether two pointers are guaranteed to be equal.
|
||||||
|
///
|
||||||
|
/// At runtime this function behaves like `self == other`.
|
||||||
|
/// However, in some contexts (e.g., compile-time evaluation),
|
||||||
|
/// it is not always possible to determine equality of two pointers, so this function may
|
||||||
|
/// spuriously return `false` for pointers that later actually turn out to be equal.
|
||||||
|
/// But when it returns `true`, the pointers are guaranteed to be equal.
|
||||||
|
///
|
||||||
|
/// This function is the mirror of [`guaranteed_ne`], but not its inverse. There are pointer
|
||||||
|
/// comparisons for which both functions return `false`.
|
||||||
|
///
|
||||||
|
/// [`guaranteed_ne`]: #method.guaranteed_ne
|
||||||
|
///
|
||||||
|
/// The return value may change depending on the compiler version and unsafe code may not
|
||||||
|
/// rely on the result of this function for soundness. It is suggested to only use this function
|
||||||
|
/// for performance optimizations where spurious `false` return values by this function do not
|
||||||
|
/// affect the outcome, but just the performance.
|
||||||
|
/// The consequences of using this method to make runtime and compile-time code behave
|
||||||
|
/// differently have not been explored. This method should not be used to introduce such
|
||||||
|
/// differences, and it should also not be stabilized before we have a better understanding
|
||||||
|
/// of this issue.
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
|
||||||
|
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
|
||||||
|
#[inline]
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
pub const fn guaranteed_eq(self, other: *mut T) -> bool
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
|
intrinsics::ptr_guaranteed_eq(self as *const _, other as *const _)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether two pointers are guaranteed to be inequal.
|
||||||
|
///
|
||||||
|
/// At runtime this function behaves like `self != other`.
|
||||||
|
/// However, in some contexts (e.g., compile-time evaluation),
|
||||||
|
/// it is not always possible to determine the inequality of two pointers, so this function may
|
||||||
|
/// spuriously return `false` for pointers that later actually turn out to be inequal.
|
||||||
|
/// But when it returns `true`, the pointers are guaranteed to be inequal.
|
||||||
|
///
|
||||||
|
/// This function is the mirror of [`guaranteed_eq`], but not its inverse. There are pointer
|
||||||
|
/// comparisons for which both functions return `false`.
|
||||||
|
///
|
||||||
|
/// [`guaranteed_eq`]: #method.guaranteed_eq
|
||||||
|
///
|
||||||
|
/// The return value may change depending on the compiler version and unsafe code may not
|
||||||
|
/// rely on the result of this function for soundness. It is suggested to only use this function
|
||||||
|
/// for performance optimizations where spurious `false` return values by this function do not
|
||||||
|
/// affect the outcome, but just the performance.
|
||||||
|
/// The consequences of using this method to make runtime and compile-time code behave
|
||||||
|
/// differently have not been explored. This method should not be used to introduce such
|
||||||
|
/// differences, and it should also not be stabilized before we have a better understanding
|
||||||
|
/// of this issue.
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
|
||||||
|
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
|
||||||
|
#[inline]
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
pub const unsafe fn guaranteed_ne(self, other: *mut T) -> bool
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
|
intrinsics::ptr_guaranteed_ne(self as *const _, other as *const _)
|
||||||
|
}
|
||||||
|
|
||||||
/// Calculates the distance between two pointers. The returned value is in
|
/// Calculates the distance between two pointers. The returned value is in
|
||||||
/// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
|
/// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
|
||||||
///
|
///
|
||||||
|
|
|
@ -5956,10 +5956,18 @@ where
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(bootstrap)]
|
||||||
if self.as_ptr() == other.as_ptr() {
|
if self.as_ptr() == other.as_ptr() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// While performance would suffer if `guaranteed_eq` just returned `false`
|
||||||
|
// for all arguments, correctness and return value of this function are not affected.
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
if self.as_ptr().guaranteed_eq(other.as_ptr()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
self.iter().zip(other.iter()).all(|(x, y)| x == y)
|
self.iter().zip(other.iter()).all(|(x, y)| x == y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5973,9 +5981,18 @@ where
|
||||||
if self.len() != other.len() {
|
if self.len() != other.len() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(bootstrap)]
|
||||||
if self.as_ptr() == other.as_ptr() {
|
if self.as_ptr() == other.as_ptr() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// While performance would suffer if `guaranteed_eq` just returned `false`
|
||||||
|
// for all arguments, correctness and return value of this function are not affected.
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
if self.as_ptr().guaranteed_eq(other.as_ptr()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
let size = mem::size_of_val(self);
|
let size = mem::size_of_val(self);
|
||||||
memcmp(self.as_ptr() as *const u8, other.as_ptr() as *const u8, size) == 0
|
memcmp(self.as_ptr() as *const u8, other.as_ptr() as *const u8, size) == 0
|
||||||
|
|
|
@ -12,7 +12,7 @@ use log::debug;
|
||||||
use rustc_ast::ast;
|
use rustc_ast::ast;
|
||||||
use rustc_codegen_ssa::base::{compare_simd_types, to_immediate, wants_msvc_seh};
|
use rustc_codegen_ssa::base::{compare_simd_types, to_immediate, wants_msvc_seh};
|
||||||
use rustc_codegen_ssa::common::span_invalid_monomorphization_error;
|
use rustc_codegen_ssa::common::span_invalid_monomorphization_error;
|
||||||
use rustc_codegen_ssa::common::TypeKind;
|
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
|
||||||
use rustc_codegen_ssa::glue;
|
use rustc_codegen_ssa::glue;
|
||||||
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
|
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
|
||||||
use rustc_codegen_ssa::mir::place::PlaceRef;
|
use rustc_codegen_ssa::mir::place::PlaceRef;
|
||||||
|
@ -731,6 +731,16 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"ptr_guaranteed_eq" | "ptr_guaranteed_ne" => {
|
||||||
|
let a = args[0].immediate();
|
||||||
|
let b = args[1].immediate();
|
||||||
|
if name == "ptr_guaranteed_eq" {
|
||||||
|
self.icmp(IntPredicate::IntEQ, a, b)
|
||||||
|
} else {
|
||||||
|
self.icmp(IntPredicate::IntNE, a, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
"ptr_offset_from" => {
|
"ptr_offset_from" => {
|
||||||
let ty = substs.type_at(0);
|
let ty = substs.type_at(0);
|
||||||
let pointee_size = self.size_of(ty);
|
let pointee_size = self.size_of(ty);
|
||||||
|
|
|
@ -401,9 +401,6 @@ declare_features! (
|
||||||
/// Allows dereferencing raw pointers during const eval.
|
/// Allows dereferencing raw pointers during const eval.
|
||||||
(active, const_raw_ptr_deref, "1.27.0", Some(51911), None),
|
(active, const_raw_ptr_deref, "1.27.0", Some(51911), None),
|
||||||
|
|
||||||
/// Allows comparing raw pointers during const eval.
|
|
||||||
(active, const_compare_raw_pointers, "1.27.0", Some(53020), None),
|
|
||||||
|
|
||||||
/// Allows `#[doc(alias = "...")]`.
|
/// Allows `#[doc(alias = "...")]`.
|
||||||
(active, doc_alias, "1.27.0", Some(50146), None),
|
(active, doc_alias, "1.27.0", Some(50146), None),
|
||||||
|
|
||||||
|
|
|
@ -113,6 +113,11 @@ declare_features! (
|
||||||
Some("removed in favor of `#![feature(marker_trait_attr)]`")),
|
Some("removed in favor of `#![feature(marker_trait_attr)]`")),
|
||||||
/// Allows `#[no_debug]`.
|
/// Allows `#[no_debug]`.
|
||||||
(removed, no_debug, "1.43.0", Some(29721), None, Some("removed due to lack of demand")),
|
(removed, no_debug, "1.43.0", Some(29721), None, Some("removed due to lack of demand")),
|
||||||
|
|
||||||
|
/// Allows comparing raw pointers during const eval.
|
||||||
|
(removed, const_compare_raw_pointers, "1.46.0", Some(53020), None,
|
||||||
|
Some("cannot be allowed in const eval in any meaningful way")),
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// feature-group-end: removed features
|
// feature-group-end: removed features
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
|
@ -296,6 +296,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
let offset_ptr = ptr.ptr_wrapping_signed_offset(offset_bytes, self);
|
let offset_ptr = ptr.ptr_wrapping_signed_offset(offset_bytes, self);
|
||||||
self.write_scalar(offset_ptr, dest)?;
|
self.write_scalar(offset_ptr, dest)?;
|
||||||
}
|
}
|
||||||
|
sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => {
|
||||||
|
// FIXME: return `true` for at least some comparisons where we can reliably
|
||||||
|
// determine the result of runtime (in)equality tests at compile-time.
|
||||||
|
self.write_scalar(Scalar::from_bool(false), dest)?;
|
||||||
|
}
|
||||||
sym::ptr_offset_from => {
|
sym::ptr_offset_from => {
|
||||||
let a = self.read_immediate(args[0])?.to_scalar()?;
|
let a = self.read_immediate(args[0])?.to_scalar()?;
|
||||||
let b = self.read_immediate(args[1])?.to_scalar()?;
|
let b = self.read_immediate(args[1])?.to_scalar()?;
|
||||||
|
|
|
@ -296,18 +296,16 @@ impl NonConstOp for Panic {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RawPtrComparison;
|
pub struct RawPtrComparison;
|
||||||
impl NonConstOp for RawPtrComparison {
|
impl NonConstOp for RawPtrComparison {
|
||||||
fn feature_gate() -> Option<Symbol> {
|
|
||||||
Some(sym::const_compare_raw_pointers)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
|
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
|
||||||
feature_err(
|
let mut err = ccx
|
||||||
&ccx.tcx.sess.parse_sess,
|
.tcx
|
||||||
sym::const_compare_raw_pointers,
|
.sess
|
||||||
span,
|
.struct_span_err(span, "pointers cannot be reliably compared during const eval.");
|
||||||
&format!("comparing raw pointers inside {}", ccx.const_kind()),
|
err.note(
|
||||||
)
|
"see issue #53020 <https://github.com/rust-lang/rust/issues/53020> \
|
||||||
.emit();
|
for more information",
|
||||||
|
);
|
||||||
|
err.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -171,21 +171,6 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 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.body, self.tcx).kind {
|
|
||||||
self.require_unsafe(
|
|
||||||
"pointer operation",
|
|
||||||
"operations on pointers in constants",
|
|
||||||
UnsafetyViolationKind::General,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
self.super_rvalue(rvalue, location);
|
self.super_rvalue(rvalue, location);
|
||||||
|
|
|
@ -588,6 +588,8 @@ symbols! {
|
||||||
proc_macro_non_items,
|
proc_macro_non_items,
|
||||||
proc_macro_path_invoc,
|
proc_macro_path_invoc,
|
||||||
profiler_runtime,
|
profiler_runtime,
|
||||||
|
ptr_guaranteed_eq,
|
||||||
|
ptr_guaranteed_ne,
|
||||||
ptr_offset_from,
|
ptr_offset_from,
|
||||||
pub_restricted,
|
pub_restricted,
|
||||||
pure,
|
pure,
|
||||||
|
|
|
@ -74,9 +74,8 @@ pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety {
|
||||||
| "wrapping_add" | "wrapping_sub" | "wrapping_mul" | "saturating_add"
|
| "wrapping_add" | "wrapping_sub" | "wrapping_mul" | "saturating_add"
|
||||||
| "saturating_sub" | "rotate_left" | "rotate_right" | "ctpop" | "ctlz" | "cttz"
|
| "saturating_sub" | "rotate_left" | "rotate_right" | "ctpop" | "ctlz" | "cttz"
|
||||||
| "bswap" | "bitreverse" | "discriminant_value" | "type_id" | "likely" | "unlikely"
|
| "bswap" | "bitreverse" | "discriminant_value" | "type_id" | "likely" | "unlikely"
|
||||||
| "minnumf32" | "minnumf64" | "maxnumf32" | "maxnumf64" | "type_name" => {
|
| "ptr_guaranteed_eq" | "ptr_guaranteed_ne" | "minnumf32" | "minnumf64" | "maxnumf32"
|
||||||
hir::Unsafety::Normal
|
| "maxnumf64" | "type_name" => hir::Unsafety::Normal,
|
||||||
}
|
|
||||||
_ => hir::Unsafety::Unsafe,
|
_ => hir::Unsafety::Unsafe,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -258,6 +257,10 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
|
||||||
(1, vec![param(0), param(0)], tcx.intern_tup(&[param(0), tcx.types.bool]))
|
(1, vec![param(0), param(0)], tcx.intern_tup(&[param(0), tcx.types.bool]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"ptr_guaranteed_eq" | "ptr_guaranteed_ne" => {
|
||||||
|
(1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.bool)
|
||||||
|
}
|
||||||
|
|
||||||
"ptr_offset_from" => {
|
"ptr_offset_from" => {
|
||||||
(1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.isize)
|
(1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.isize)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,7 @@ use rustc_middle::hir::map::Map;
|
||||||
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
|
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
|
||||||
use rustc_middle::ty::util::IntTypeExt;
|
use rustc_middle::ty::util::IntTypeExt;
|
||||||
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable};
|
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable};
|
||||||
use rustc_session::parse::feature_err;
|
use rustc_span::symbol::Ident;
|
||||||
use rustc_span::symbol::{sym, Ident};
|
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
use rustc_trait_selection::traits;
|
use rustc_trait_selection::traits;
|
||||||
|
|
||||||
|
@ -303,25 +302,22 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||||
GenericParamKind::Type { default: Some(ref ty), .. } => icx.to_ty(ty),
|
GenericParamKind::Type { default: Some(ref ty), .. } => icx.to_ty(ty),
|
||||||
GenericParamKind::Const { ty: ref hir_ty, .. } => {
|
GenericParamKind::Const { ty: ref hir_ty, .. } => {
|
||||||
let ty = icx.to_ty(hir_ty);
|
let ty = icx.to_ty(hir_ty);
|
||||||
if !tcx.features().const_compare_raw_pointers {
|
let err = match ty.peel_refs().kind {
|
||||||
let err = match ty.peel_refs().kind {
|
ty::FnPtr(_) => Some("function pointers"),
|
||||||
ty::FnPtr(_) => Some("function pointers"),
|
ty::RawPtr(_) => Some("raw pointers"),
|
||||||
ty::RawPtr(_) => Some("raw pointers"),
|
_ => None,
|
||||||
_ => None,
|
};
|
||||||
};
|
if let Some(unsupported_type) = err {
|
||||||
if let Some(unsupported_type) = err {
|
tcx.sess
|
||||||
feature_err(
|
.struct_span_err(
|
||||||
&tcx.sess.parse_sess,
|
|
||||||
sym::const_compare_raw_pointers,
|
|
||||||
hir_ty.span,
|
hir_ty.span,
|
||||||
&format!(
|
&format!(
|
||||||
"using {} as const generic parameters is unstable",
|
"using {} as const generic parameters is forbidden",
|
||||||
unsupported_type
|
unsupported_type
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
};
|
};
|
||||||
}
|
|
||||||
if traits::search_for_structural_match_violation(param.hir_id, param.span, tcx, ty)
|
if traits::search_for_structural_match_violation(param.hir_id, param.span, tcx, ty)
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
// run-pass
|
#![feature(const_generics)]
|
||||||
|
|
||||||
#![feature(const_generics, const_compare_raw_pointers)]
|
|
||||||
//~^ WARN the feature `const_generics` is incomplete
|
//~^ WARN the feature `const_generics` is incomplete
|
||||||
|
|
||||||
fn function() -> u32 {
|
fn function() -> u32 {
|
||||||
17
|
17
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Wrapper<const F: fn() -> u32>;
|
struct Wrapper<const F: fn() -> u32>; //~ ERROR: using function pointers as const generic parameters
|
||||||
|
|
||||||
impl<const F: fn() -> u32> Wrapper<F> {
|
impl<const F: fn() -> u32> Wrapper<F> {
|
||||||
|
//~^ ERROR: using function pointers as const generic parameters
|
||||||
fn call() -> u32 {
|
fn call() -> u32 {
|
||||||
F()
|
F()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,23 @@
|
||||||
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
--> $DIR/fn-const-param-call.rs:3:12
|
--> $DIR/fn-const-param-call.rs:1:12
|
||||||
|
|
|
|
||||||
LL | #![feature(const_generics, const_compare_raw_pointers)]
|
LL | #![feature(const_generics)]
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: `#[warn(incomplete_features)]` on by default
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||||
|
|
||||||
warning: 1 warning emitted
|
error: using function pointers as const generic parameters is forbidden
|
||||||
|
--> $DIR/fn-const-param-call.rs:8:25
|
||||||
|
|
|
||||||
|
LL | struct Wrapper<const F: fn() -> u32>;
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: using function pointers as const generic parameters is forbidden
|
||||||
|
--> $DIR/fn-const-param-call.rs:10:15
|
||||||
|
|
|
||||||
|
LL | impl<const F: fn() -> u32> Wrapper<F> {
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors; 1 warning emitted
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#![feature(const_generics, const_compare_raw_pointers)]
|
#![feature(const_generics)]
|
||||||
//~^ WARN the feature `const_generics` is incomplete
|
//~^ WARN the feature `const_generics` is incomplete
|
||||||
|
|
||||||
struct Checked<const F: fn(usize) -> bool>;
|
struct Checked<const F: fn(usize) -> bool>;
|
||||||
|
//~^ ERROR: using function pointers as const generic parameters
|
||||||
|
|
||||||
fn not_one(val: usize) -> bool { val != 1 }
|
fn not_one(val: usize) -> bool { val != 1 }
|
||||||
fn not_two(val: usize) -> bool { val != 2 }
|
fn not_two(val: usize) -> bool { val != 2 }
|
||||||
|
@ -13,14 +14,14 @@ fn generic<T>(val: usize) -> bool { val != 1 }
|
||||||
fn main() {
|
fn main() {
|
||||||
let _: Option<Checked<not_one>> = None;
|
let _: Option<Checked<not_one>> = None;
|
||||||
let _: Checked<not_one> = Checked::<not_one>;
|
let _: Checked<not_one> = Checked::<not_one>;
|
||||||
let _: Checked<not_one> = Checked::<not_two>; //~ mismatched types
|
let _: Checked<not_one> = Checked::<not_two>;
|
||||||
|
|
||||||
let _ = Checked::<generic_arg>;
|
let _ = Checked::<generic_arg>;
|
||||||
let _ = Checked::<{generic_arg::<usize>}>;
|
let _ = Checked::<{generic_arg::<usize>}>;
|
||||||
let _ = Checked::<{generic_arg::<u32>}>; //~ mismatched types
|
let _ = Checked::<{generic_arg::<u32>}>;
|
||||||
|
|
||||||
let _ = Checked::<generic>; //~ type annotations needed
|
let _ = Checked::<generic>;
|
||||||
let _ = Checked::<{generic::<u16>}>;
|
let _ = Checked::<{generic::<u16>}>;
|
||||||
let _: Checked<{generic::<u16>}> = Checked::<{generic::<u16>}>;
|
let _: Checked<{generic::<u16>}> = Checked::<{generic::<u16>}>;
|
||||||
let _: Checked<{generic::<u32>}> = Checked::<{generic::<u16>}>; //~ mismatched types
|
let _: Checked<{generic::<u32>}> = Checked::<{generic::<u16>}>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,46 +1,17 @@
|
||||||
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
--> $DIR/fn-const-param-infer.rs:1:12
|
--> $DIR/fn-const-param-infer.rs:1:12
|
||||||
|
|
|
|
||||||
LL | #![feature(const_generics, const_compare_raw_pointers)]
|
LL | #![feature(const_generics)]
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: `#[warn(incomplete_features)]` on by default
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error: using function pointers as const generic parameters is forbidden
|
||||||
--> $DIR/fn-const-param-infer.rs:16:31
|
--> $DIR/fn-const-param-infer.rs:4:25
|
||||||
|
|
|
|
||||||
LL | let _: Checked<not_one> = Checked::<not_two>;
|
LL | struct Checked<const F: fn(usize) -> bool>;
|
||||||
| ^^^^^^^^^^^^^^^^^^ expected `{not_one as fn(usize) -> bool}`, found `{not_two as fn(usize) -> bool}`
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
= note: expected type `{not_one as fn(usize) -> bool}`
|
|
||||||
found type `{not_two as fn(usize) -> bool}`
|
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error: aborting due to previous error; 1 warning emitted
|
||||||
--> $DIR/fn-const-param-infer.rs:20:24
|
|
||||||
|
|
|
||||||
LL | let _ = Checked::<{generic_arg::<u32>}>;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^ expected `usize`, found `u32`
|
|
||||||
|
|
|
||||||
= note: expected fn pointer `fn(usize) -> _`
|
|
||||||
found fn item `fn(u32) -> _ {generic_arg::<u32>}`
|
|
||||||
|
|
||||||
error[E0282]: type annotations needed
|
|
||||||
--> $DIR/fn-const-param-infer.rs:22:23
|
|
||||||
|
|
|
||||||
LL | let _ = Checked::<generic>;
|
|
||||||
| ^^^^^^^ cannot infer type for type parameter `T` declared on the function `generic`
|
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
|
||||||
--> $DIR/fn-const-param-infer.rs:25:40
|
|
||||||
|
|
|
||||||
LL | let _: Checked<{generic::<u32>}> = Checked::<{generic::<u16>}>;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{generic::<u32> as fn(usize) -> bool}`, found `{generic::<u16> as fn(usize) -> bool}`
|
|
||||||
|
|
|
||||||
= note: expected type `{generic::<u32> as fn(usize) -> bool}`
|
|
||||||
found type `{generic::<u16> as fn(usize) -> bool}`
|
|
||||||
|
|
||||||
error: aborting due to 4 previous errors; 1 warning emitted
|
|
||||||
|
|
||||||
Some errors have detailed explanations: E0282, E0308.
|
|
||||||
For more information about an error, try `rustc --explain E0282`.
|
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
// run-pass
|
#![feature(const_generics)]
|
||||||
#![feature(const_generics, const_compare_raw_pointers)]
|
|
||||||
//~^ WARN the feature `const_generics` is incomplete
|
//~^ WARN the feature `const_generics` is incomplete
|
||||||
|
|
||||||
const A: u32 = 3;
|
const A: u32 = 3;
|
||||||
|
|
||||||
struct Const<const P: *const u32>;
|
struct Const<const P: *const u32>; //~ ERROR: using raw pointers as const generic parameters
|
||||||
|
|
||||||
impl<const P: *const u32> Const<P> {
|
impl<const P: *const u32> Const<P> { //~ ERROR: using raw pointers as const generic parameters
|
||||||
fn get() -> u32 {
|
fn get() -> u32 {
|
||||||
unsafe {
|
unsafe {
|
||||||
*P
|
*P
|
||||||
|
|
|
@ -1,11 +1,23 @@
|
||||||
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
--> $DIR/raw-ptr-const-param-deref.rs:2:12
|
--> $DIR/raw-ptr-const-param-deref.rs:1:12
|
||||||
|
|
|
|
||||||
LL | #![feature(const_generics, const_compare_raw_pointers)]
|
LL | #![feature(const_generics)]
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: `#[warn(incomplete_features)]` on by default
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||||
|
|
||||||
warning: 1 warning emitted
|
error: using raw pointers as const generic parameters is forbidden
|
||||||
|
--> $DIR/raw-ptr-const-param-deref.rs:6:23
|
||||||
|
|
|
||||||
|
LL | struct Const<const P: *const u32>;
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
error: using raw pointers as const generic parameters is forbidden
|
||||||
|
--> $DIR/raw-ptr-const-param-deref.rs:8:15
|
||||||
|
|
|
||||||
|
LL | impl<const P: *const u32> Const<P> {
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors; 1 warning emitted
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#![feature(const_generics, const_compare_raw_pointers)]
|
#![feature(const_generics)]
|
||||||
//~^ WARN the feature `const_generics` is incomplete
|
//~^ WARN the feature `const_generics` is incomplete
|
||||||
|
|
||||||
struct Const<const P: *const u32>;
|
struct Const<const P: *const u32>; //~ ERROR: using raw pointers as const generic parameters
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>; //~ mismatched types
|
let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>;
|
||||||
let _: Const<{ 10 as *const _ }> = Const::<{ 10 as *const _ }>;
|
let _: Const<{ 10 as *const _ }> = Const::<{ 10 as *const _ }>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,17 @@
|
||||||
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||||
--> $DIR/raw-ptr-const-param.rs:1:12
|
--> $DIR/raw-ptr-const-param.rs:1:12
|
||||||
|
|
|
|
||||||
LL | #![feature(const_generics, const_compare_raw_pointers)]
|
LL | #![feature(const_generics)]
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: `#[warn(incomplete_features)]` on by default
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error: using raw pointers as const generic parameters is forbidden
|
||||||
--> $DIR/raw-ptr-const-param.rs:7:40
|
--> $DIR/raw-ptr-const-param.rs:4:23
|
||||||
|
|
|
|
||||||
LL | let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>;
|
LL | struct Const<const P: *const u32>;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{0xf as *const u32}`, found `{0xa as *const u32}`
|
| ^^^^^^^^^^
|
||||||
|
|
|
||||||
= note: expected type `{0xf as *const u32}`
|
|
||||||
found type `{0xa as *const u32}`
|
|
||||||
|
|
||||||
error: aborting due to previous error; 1 warning emitted
|
error: aborting due to previous error; 1 warning emitted
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
|
||||||
|
|
|
@ -1,17 +1,6 @@
|
||||||
#![feature(const_raw_ptr_to_usize_cast, const_compare_raw_pointers, const_raw_ptr_deref)]
|
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
||||||
// unconst and bad, will thus error in miri
|
// unconst and bad, will thus error in miri
|
||||||
const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR any use of this
|
const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR cannot be reliably
|
||||||
// unconst and bad, will thus error in miri
|
// unconst and bad, will thus error in miri
|
||||||
const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; //~ ERROR any use of this
|
const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; //~ ERROR cannot be reliably
|
||||||
// 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
|
|
||||||
// unconst and fine
|
|
||||||
const Z: i32 = unsafe { *(&1 as *const i32) };
|
|
||||||
// unconst and bad, will thus error in miri
|
|
||||||
const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR any use of this value will cause
|
|
||||||
const Z3: i32 = unsafe { *(44 as *const i32) }; //~ ERROR any use of this value will cause
|
|
||||||
|
|
|
@ -1,44 +1,18 @@
|
||||||
error: any use of this value will cause an error
|
error: pointers cannot be reliably compared during const eval.
|
||||||
--> $DIR/const_raw_ptr_ops.rs:6:26
|
--> $DIR/const_raw_ptr_ops.rs:4:26
|
||||||
|
|
|
|
||||||
LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 };
|
LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 };
|
||||||
| -------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
| |
|
|
||||||
| "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
|
|
||||||
|
|
|
|
||||||
= note: `#[deny(const_err)]` on by default
|
= note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
|
||||||
|
|
||||||
error: any use of this value will cause an error
|
error: pointers cannot be reliably compared during const eval.
|
||||||
--> $DIR/const_raw_ptr_ops.rs:8:27
|
--> $DIR/const_raw_ptr_ops.rs:6:27
|
||||||
|
|
|
|
||||||
LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 };
|
LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 };
|
||||||
| --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
| |
|
|
||||||
| "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:12:28
|
|
||||||
|
|
|
|
||||||
LL | const Y2: usize = unsafe { &1 as *const i32 as usize + 1 };
|
= note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
|
||||||
| ---------------------------^^^^^^^^^^^^^^^^^^^^^^^^^-------
|
|
||||||
| |
|
|
||||||
| "pointer-to-integer cast" needs an rfc before being allowed inside constants
|
|
||||||
|
|
||||||
error: any use of this value will cause an error
|
error: aborting due to 2 previous errors
|
||||||
--> $DIR/const_raw_ptr_ops.rs:16:26
|
|
||||||
|
|
|
||||||
LL | const Z2: i32 = unsafe { *(42 as *const i32) };
|
|
||||||
| -------------------------^^^^^^^^^^^^^^^^^^^---
|
|
||||||
| |
|
|
||||||
| unable to turn bytes into a pointer
|
|
||||||
|
|
||||||
error: any use of this value will cause an error
|
|
||||||
--> $DIR/const_raw_ptr_ops.rs:17:26
|
|
||||||
|
|
|
||||||
LL | const Z3: i32 = unsafe { *(44 as *const i32) };
|
|
||||||
| -------------------------^^^^^^^^^^^^^^^^^^^---
|
|
||||||
| |
|
|
||||||
| unable to turn bytes into a pointer
|
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
|
||||||
|
|
||||||
|
|
13
src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs
Normal file
13
src/test/ui/consts/const-eval/const_raw_ptr_ops2.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#![feature(const_raw_ptr_to_usize_cast, 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
|
||||||
|
// unconst and fine
|
||||||
|
const Z: i32 = unsafe { *(&1 as *const i32) };
|
||||||
|
// unconst and bad, will thus error in miri
|
||||||
|
const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR any use of this value will cause
|
||||||
|
const Z3: i32 = unsafe { *(44 as *const i32) }; //~ ERROR any use of this value will cause
|
28
src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr
Normal file
28
src/test/ui/consts/const-eval/const_raw_ptr_ops2.stderr
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
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 };
|
||||||
|
| ---------------------------^^^^^^^^^^^^^^^^^^^^^^^^^-------
|
||||||
|
| |
|
||||||
|
| "pointer-to-integer cast" 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_ops2.rs:12:26
|
||||||
|
|
|
||||||
|
LL | const Z2: i32 = unsafe { *(42 as *const i32) };
|
||||||
|
| -------------------------^^^^^^^^^^^^^^^^^^^---
|
||||||
|
| |
|
||||||
|
| unable to turn bytes into a pointer
|
||||||
|
|
||||||
|
error: any use of this value will cause an error
|
||||||
|
--> $DIR/const_raw_ptr_ops2.rs:13:26
|
||||||
|
|
|
||||||
|
LL | const Z3: i32 = unsafe { *(44 as *const i32) };
|
||||||
|
| -------------------------^^^^^^^^^^^^^^^^^^^---
|
||||||
|
| |
|
||||||
|
| unable to turn bytes into a pointer
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(const_raw_ptr_to_usize_cast, const_compare_raw_pointers, const_raw_ptr_deref)]
|
#![feature(const_raw_ptr_to_usize_cast, const_raw_ptr_deref)]
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x: &'static bool = &(42 as *const i32 == 43 as *const i32);
|
let x: &'static bool = &(42 as *const i32 == 43 as *const i32);
|
||||||
|
|
|
@ -12,7 +12,7 @@ LL | let _v = x + 0;
|
||||||
|
|
||||||
warning: skipping const checks
|
warning: skipping const checks
|
||||||
|
|
|
|
||||||
help: skipping check for `const_compare_raw_pointers` feature
|
help: skipping check that does not even have a feature gate
|
||||||
--> $DIR/ptr_arith.rs:9:14
|
--> $DIR/ptr_arith.rs:9:14
|
||||||
|
|
|
|
||||||
LL | let _v = x == x;
|
LL | let _v = x == x;
|
||||||
|
|
17
src/test/ui/consts/miri_unleashed/slice_eq.rs
Normal file
17
src/test/ui/consts/miri_unleashed/slice_eq.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
// compile-flags: -Zunleash-the-miri-inside-of-you
|
||||||
|
// run-pass
|
||||||
|
|
||||||
|
#![feature(const_raw_ptr_comparison)]
|
||||||
|
|
||||||
|
const EMPTY_SLICE: &[i32] = &[];
|
||||||
|
const EMPTY_EQ: bool = EMPTY_SLICE.as_ptr().guaranteed_eq(&[] as *const _);
|
||||||
|
const EMPTY_EQ2: bool = EMPTY_SLICE.as_ptr().guaranteed_ne(&[] as *const _);
|
||||||
|
const EMPTY_NE: bool = EMPTY_SLICE.as_ptr().guaranteed_ne(&[1] as *const _);
|
||||||
|
const EMPTY_NE2: bool = EMPTY_SLICE.as_ptr().guaranteed_eq(&[1] as *const _);
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert!(!EMPTY_EQ);
|
||||||
|
assert!(!EMPTY_EQ2);
|
||||||
|
assert!(!EMPTY_NE);
|
||||||
|
assert!(!EMPTY_NE2);
|
||||||
|
}
|
|
@ -1,10 +1,8 @@
|
||||||
// gate-test-const_compare_raw_pointers
|
|
||||||
|
|
||||||
static FOO: i32 = 42;
|
static FOO: i32 = 42;
|
||||||
static BAR: i32 = 42;
|
static BAR: i32 = 42;
|
||||||
|
|
||||||
static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) };
|
static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) };
|
||||||
//~^ ERROR comparing raw pointers inside static
|
//~^ ERROR pointers cannot be reliably compared during const eval
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
error[E0658]: comparing raw pointers inside static
|
error: pointers cannot be reliably compared during const eval.
|
||||||
--> $DIR/E0395.rs:6:29
|
--> $DIR/E0395.rs:4:29
|
||||||
|
|
|
|
||||||
LL | static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) };
|
LL | static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
|
= note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
|
||||||
= help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0658`.
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
struct ConstFn<const F: fn()>;
|
struct ConstFn<const F: fn()>;
|
||||||
//~^ ERROR const generics are unstable
|
//~^ ERROR const generics are unstable
|
||||||
//~^^ ERROR using function pointers as const generic parameters is unstable
|
//~^^ ERROR using function pointers as const generic parameters is forbidden
|
||||||
|
|
||||||
struct ConstPtr<const P: *const u32>;
|
struct ConstPtr<const P: *const u32>;
|
||||||
//~^ ERROR const generics are unstable
|
//~^ ERROR const generics are unstable
|
||||||
//~^^ ERROR using raw pointers as const generic parameters is unstable
|
//~^^ ERROR using raw pointers as const generic parameters is forbidden
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -16,23 +16,17 @@ LL | struct ConstPtr<const P: *const u32>;
|
||||||
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
|
||||||
= help: add `#![feature(const_generics)]` to the crate attributes to enable
|
= help: add `#![feature(const_generics)]` to the crate attributes to enable
|
||||||
|
|
||||||
error[E0658]: using function pointers as const generic parameters is unstable
|
error: using function pointers as const generic parameters is forbidden
|
||||||
--> $DIR/feature-gate-const_generics-ptr.rs:1:25
|
--> $DIR/feature-gate-const_generics-ptr.rs:1:25
|
||||||
|
|
|
|
||||||
LL | struct ConstFn<const F: fn()>;
|
LL | struct ConstFn<const F: fn()>;
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
|
||||||
= note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
|
|
||||||
= help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable
|
|
||||||
|
|
||||||
error[E0658]: using raw pointers as const generic parameters is unstable
|
error: using raw pointers as const generic parameters is forbidden
|
||||||
--> $DIR/feature-gate-const_generics-ptr.rs:5:26
|
--> $DIR/feature-gate-const_generics-ptr.rs:5:26
|
||||||
|
|
|
|
||||||
LL | struct ConstPtr<const P: *const u32>;
|
LL | struct ConstPtr<const P: *const u32>;
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
|
||||||
= note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
|
|
||||||
= help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable
|
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
fn id<T>(t: T) -> T { t }
|
fn id<T>(t: T) -> T { t }
|
||||||
fn main() {
|
fn main() {
|
||||||
const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
|
const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
|
||||||
//~^ ERROR comparing raw pointers inside constant
|
//~^ ERROR pointers cannot be reliably compared during const eval
|
||||||
println!("{}", A);
|
println!("{}", A);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
error[E0658]: comparing raw pointers inside constant
|
error: pointers cannot be reliably compared during const eval.
|
||||||
--> $DIR/issue-25826.rs:3:30
|
--> $DIR/issue-25826.rs:3:30
|
||||||
|
|
|
|
||||||
LL | const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
|
LL | const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
|
= note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
|
||||||
= help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0658`.
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
#![stable(feature = "foo", since = "1.33.0")]
|
#![stable(feature = "foo", since = "1.33.0")]
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
#![feature(const_compare_raw_pointers)]
|
#![feature(const_raw_ptr_deref)]
|
||||||
#![feature(const_fn)]
|
#![feature(const_fn)]
|
||||||
|
|
||||||
#[stable(feature = "foo", since = "1.33.0")]
|
#[stable(feature = "foo", since = "1.33.0")]
|
||||||
#[rustc_const_unstable(feature = "const_foo", issue = "none")]
|
#[rustc_const_unstable(feature = "const_foo", issue = "none")]
|
||||||
const fn unstable(a: *const i32, b: *const i32) -> bool {
|
const fn unstable(a: *const i32, b: i32) -> bool {
|
||||||
a == b
|
*a == b
|
||||||
//~^ pointer operation is unsafe
|
//~^ dereference of raw pointer is unsafe
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
error[E0133]: pointer operation is unsafe and requires unsafe function or block
|
error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
|
||||||
--> $DIR/unsafe-unstable-const-fn.rs:9:5
|
--> $DIR/unsafe-unstable-const-fn.rs:9:5
|
||||||
|
|
|
|
||||||
LL | a == b
|
LL | *a == b
|
||||||
| ^^^^^^ pointer operation
|
| ^^ dereference of raw pointer
|
||||||
|
|
|
|
||||||
= note: operations on pointers in constants
|
= note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -444,10 +444,7 @@ fn map_lib_features(
|
||||||
level: Status::Unstable,
|
level: Status::Unstable,
|
||||||
since: None,
|
since: None,
|
||||||
has_gate_test: false,
|
has_gate_test: false,
|
||||||
// FIXME(#57563): #57563 is now used as a common tracking issue,
|
tracking_issue: find_attr_val(line, "issue").and_then(handle_issue_none),
|
||||||
// although we would like to have specific tracking issues for each
|
|
||||||
// `rustc_const_unstable` in the future.
|
|
||||||
tracking_issue: NonZeroU32::new(57563),
|
|
||||||
};
|
};
|
||||||
mf(Ok((feature_name, feature)), file, i + 1);
|
mf(Ok((feature_name, feature)), file, i + 1);
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue