Skip to content

Commit 9245ba8

Browse files
committed
Remove the const_raw_ptr_comparison feature gate.
We can never supply a meaningful implementation of this. Instead, the follow up commits will create two intrinsics that approximate comparisons: * `ptr_maybe_eq` * `ptr_maybe_ne` The fact that `ptr_maybe_eq(a, b)` is not necessarily the same value as `!ptr_maybe_ne(a, b)` is a symptom of this entire problem.
1 parent 72417d8 commit 9245ba8

27 files changed

+165
-190
lines changed

src/librustc_feature/active.rs

-3
Original file line numberDiff line numberDiff line change
@@ -401,9 +401,6 @@ declare_features! (
401401
/// Allows dereferencing raw pointers during const eval.
402402
(active, const_raw_ptr_deref, "1.27.0", Some(51911), None),
403403

404-
/// Allows comparing raw pointers during const eval.
405-
(active, const_compare_raw_pointers, "1.27.0", Some(53020), None),
406-
407404
/// Allows `#[doc(alias = "...")]`.
408405
(active, doc_alias, "1.27.0", Some(50146), None),
409406

src/librustc_feature/removed.rs

+5
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,11 @@ declare_features! (
113113
Some("removed in favor of `#![feature(marker_trait_attr)]`")),
114114
/// Allows `#[no_debug]`.
115115
(removed, no_debug, "1.43.0", Some(29721), None, Some("removed due to lack of demand")),
116+
117+
/// Allows comparing raw pointers during const eval.
118+
(removed, const_compare_raw_pointers, "1.46.0", Some(53020), None,
119+
Some("cannot be allowed in const eval in any meaningful way")),
120+
116121
// -------------------------------------------------------------------------
117122
// feature-group-end: removed features
118123
// -------------------------------------------------------------------------

src/librustc_mir/transform/check_consts/ops.rs

+16-10
Original file line numberDiff line numberDiff line change
@@ -284,18 +284,24 @@ impl NonConstOp for Panic {
284284
#[derive(Debug)]
285285
pub struct RawPtrComparison;
286286
impl NonConstOp for RawPtrComparison {
287-
fn feature_gate() -> Option<Symbol> {
288-
Some(sym::const_compare_raw_pointers)
289-
}
290-
291287
fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
292-
feature_err(
293-
&ccx.tcx.sess.parse_sess,
294-
sym::const_compare_raw_pointers,
288+
let mut err = ccx.tcx.sess.struct_span_err(
295289
span,
296-
&format!("comparing raw pointers inside {}", ccx.const_kind()),
297-
)
298-
.emit();
290+
"pointers cannot be compared in a meaningful way during const eval.",
291+
);
292+
err.note(
293+
"It is conceptually impossible for const eval to know in all cases whether two \
294+
pointers are equal. While sometimes it is clear (the address of a static item \
295+
is never equal to the address of another static item), comparing an integer \
296+
address with any allocation's address is impossible to do at compile-time.",
297+
);
298+
err.note(
299+
"That said, there's the `ptr_maybe_eq` intrinsic which returns `true` for all \
300+
comparisons where CTFE isn't sure whether two addresses are equal. The mirror \
301+
intrinsic `ptr_maybe_ne` returns `true` for all comparisons where CTFE isn't \
302+
sure whether two addresses are inequal.",
303+
);
304+
err.emit();
299305
}
300306
}
301307

src/librustc_mir/transform/check_unsafety.rs

-15
Original file line numberDiff line numberDiff line change
@@ -171,21 +171,6 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
171171
_ => {}
172172
}
173173
}
174-
// raw pointer and fn pointer operations are unsafe as it is not clear whether one
175-
// pointer would be "less" or "equal" to another, because we cannot know where llvm
176-
// or the linker will place various statics in memory. Without this information the
177-
// result of a comparison of addresses would differ between runtime and compile-time.
178-
Rvalue::BinaryOp(_, ref lhs, _)
179-
if self.const_context && self.tcx.features().const_compare_raw_pointers =>
180-
{
181-
if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).kind {
182-
self.require_unsafe(
183-
"pointer operation",
184-
"operations on pointers in constants",
185-
UnsafetyViolationKind::General,
186-
);
187-
}
188-
}
189174
_ => {}
190175
}
191176
self.super_rvalue(rvalue, location);

src/librustc_typeck/collect/type_of.rs

+11-15
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ use rustc_middle::hir::map::Map;
1010
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
1111
use rustc_middle::ty::util::IntTypeExt;
1212
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable};
13-
use rustc_session::parse::feature_err;
14-
use rustc_span::symbol::{sym, Ident};
13+
use rustc_span::symbol::Ident;
1514
use rustc_span::{Span, DUMMY_SP};
1615
use rustc_trait_selection::traits;
1716

@@ -303,25 +302,22 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
303302
GenericParamKind::Type { default: Some(ref ty), .. } => icx.to_ty(ty),
304303
GenericParamKind::Const { ty: ref hir_ty, .. } => {
305304
let ty = icx.to_ty(hir_ty);
306-
if !tcx.features().const_compare_raw_pointers {
307-
let err = match ty.peel_refs().kind {
308-
ty::FnPtr(_) => Some("function pointers"),
309-
ty::RawPtr(_) => Some("raw pointers"),
310-
_ => None,
311-
};
312-
if let Some(unsupported_type) = err {
313-
feature_err(
314-
&tcx.sess.parse_sess,
315-
sym::const_compare_raw_pointers,
305+
let err = match ty.peel_refs().kind {
306+
ty::FnPtr(_) => Some("function pointers"),
307+
ty::RawPtr(_) => Some("raw pointers"),
308+
_ => None,
309+
};
310+
if let Some(unsupported_type) = err {
311+
tcx.sess
312+
.struct_span_err(
316313
hir_ty.span,
317314
&format!(
318-
"using {} as const generic parameters is unstable",
315+
"using {} as const generic parameters is forbidden",
319316
unsupported_type
320317
),
321318
)
322319
.emit();
323-
};
324-
}
320+
};
325321
if traits::search_for_structural_match_violation(param.hir_id, param.span, tcx, ty)
326322
.is_some()
327323
{

src/test/ui/const-generics/fn-const-param-call.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
// run-pass
2-
3-
#![feature(const_generics, const_compare_raw_pointers)]
1+
#![feature(const_generics)]
42
//~^ WARN the feature `const_generics` is incomplete
53

64
fn function() -> u32 {
75
17
86
}
97

10-
struct Wrapper<const F: fn() -> u32>;
8+
struct Wrapper<const F: fn() -> u32>; //~ ERROR: using function pointers as const generic parameters
119

1210
impl<const F: fn() -> u32> Wrapper<F> {
11+
//~^ ERROR: using function pointers as const generic parameters
1312
fn call() -> u32 {
1413
F()
1514
}
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,23 @@
11
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
2-
--> $DIR/fn-const-param-call.rs:3:12
2+
--> $DIR/fn-const-param-call.rs:1:12
33
|
4-
LL | #![feature(const_generics, const_compare_raw_pointers)]
4+
LL | #![feature(const_generics)]
55
| ^^^^^^^^^^^^^^
66
|
77
= note: `#[warn(incomplete_features)]` on by default
88
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
99

10-
warning: 1 warning emitted
10+
error: using function pointers as const generic parameters is forbidden
11+
--> $DIR/fn-const-param-call.rs:8:25
12+
|
13+
LL | struct Wrapper<const F: fn() -> u32>;
14+
| ^^^^^^^^^^^
15+
16+
error: using function pointers as const generic parameters is forbidden
17+
--> $DIR/fn-const-param-call.rs:10:15
18+
|
19+
LL | impl<const F: fn() -> u32> Wrapper<F> {
20+
| ^^^^^^^^^^^
21+
22+
error: aborting due to 2 previous errors; 1 warning emitted
1123

Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
#![feature(const_generics, const_compare_raw_pointers)]
1+
#![feature(const_generics)]
22
//~^ WARN the feature `const_generics` is incomplete
33

44
struct Checked<const F: fn(usize) -> bool>;
5+
//~^ ERROR: using function pointers as const generic parameters
56

67
fn not_one(val: usize) -> bool { val != 1 }
78
fn not_two(val: usize) -> bool { val != 2 }
@@ -13,14 +14,14 @@ fn generic<T>(val: usize) -> bool { val != 1 }
1314
fn main() {
1415
let _: Option<Checked<not_one>> = None;
1516
let _: Checked<not_one> = Checked::<not_one>;
16-
let _: Checked<not_one> = Checked::<not_two>; //~ mismatched types
17+
let _: Checked<not_one> = Checked::<not_two>;
1718

1819
let _ = Checked::<generic_arg>;
1920
let _ = Checked::<{generic_arg::<usize>}>;
20-
let _ = Checked::<{generic_arg::<u32>}>; //~ mismatched types
21+
let _ = Checked::<{generic_arg::<u32>}>;
2122

22-
let _ = Checked::<generic>; //~ type annotations needed
23+
let _ = Checked::<generic>;
2324
let _ = Checked::<{generic::<u16>}>;
2425
let _: Checked<{generic::<u16>}> = Checked::<{generic::<u16>}>;
25-
let _: Checked<{generic::<u32>}> = Checked::<{generic::<u16>}>; //~ mismatched types
26+
let _: Checked<{generic::<u32>}> = Checked::<{generic::<u16>}>;
2627
}
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,17 @@
11
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
22
--> $DIR/fn-const-param-infer.rs:1:12
33
|
4-
LL | #![feature(const_generics, const_compare_raw_pointers)]
4+
LL | #![feature(const_generics)]
55
| ^^^^^^^^^^^^^^
66
|
77
= note: `#[warn(incomplete_features)]` on by default
88
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
99

10-
error[E0308]: mismatched types
11-
--> $DIR/fn-const-param-infer.rs:16:31
10+
error: using function pointers as const generic parameters is forbidden
11+
--> $DIR/fn-const-param-infer.rs:4:25
1212
|
13-
LL | let _: Checked<not_one> = Checked::<not_two>;
14-
| ^^^^^^^^^^^^^^^^^^ expected `{not_one as fn(usize) -> bool}`, found `{not_two as fn(usize) -> bool}`
15-
|
16-
= note: expected type `{not_one as fn(usize) -> bool}`
17-
found type `{not_two as fn(usize) -> bool}`
18-
19-
error[E0308]: mismatched types
20-
--> $DIR/fn-const-param-infer.rs:20:24
21-
|
22-
LL | let _ = Checked::<{generic_arg::<u32>}>;
23-
| ^^^^^^^^^^^^^^^^^^ expected `usize`, found `u32`
24-
|
25-
= note: expected fn pointer `fn(usize) -> _`
26-
found fn item `fn(u32) -> _ {generic_arg::<u32>}`
27-
28-
error[E0282]: type annotations needed
29-
--> $DIR/fn-const-param-infer.rs:22:23
30-
|
31-
LL | let _ = Checked::<generic>;
32-
| ^^^^^^^ cannot infer type for type parameter `T` declared on the function `generic`
33-
34-
error[E0308]: mismatched types
35-
--> $DIR/fn-const-param-infer.rs:25:40
36-
|
37-
LL | let _: Checked<{generic::<u32>}> = Checked::<{generic::<u16>}>;
38-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{generic::<u32> as fn(usize) -> bool}`, found `{generic::<u16> as fn(usize) -> bool}`
39-
|
40-
= note: expected type `{generic::<u32> as fn(usize) -> bool}`
41-
found type `{generic::<u16> as fn(usize) -> bool}`
13+
LL | struct Checked<const F: fn(usize) -> bool>;
14+
| ^^^^^^^^^^^^^^^^^
4215

43-
error: aborting due to 4 previous errors; 1 warning emitted
16+
error: aborting due to previous error; 1 warning emitted
4417

45-
Some errors have detailed explanations: E0282, E0308.
46-
For more information about an error, try `rustc --explain E0282`.

src/test/ui/const-generics/raw-ptr-const-param-deref.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
// run-pass
2-
#![feature(const_generics, const_compare_raw_pointers)]
1+
#![feature(const_generics)]
32
//~^ WARN the feature `const_generics` is incomplete
43

54
const A: u32 = 3;
65

7-
struct Const<const P: *const u32>;
6+
struct Const<const P: *const u32>; //~ ERROR: using raw pointers as const generic parameters
87

9-
impl<const P: *const u32> Const<P> {
8+
impl<const P: *const u32> Const<P> { //~ ERROR: using raw pointers as const generic parameters
109
fn get() -> u32 {
1110
unsafe {
1211
*P
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,23 @@
11
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
2-
--> $DIR/raw-ptr-const-param-deref.rs:2:12
2+
--> $DIR/raw-ptr-const-param-deref.rs:1:12
33
|
4-
LL | #![feature(const_generics, const_compare_raw_pointers)]
4+
LL | #![feature(const_generics)]
55
| ^^^^^^^^^^^^^^
66
|
77
= note: `#[warn(incomplete_features)]` on by default
88
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
99

10-
warning: 1 warning emitted
10+
error: using raw pointers as const generic parameters is forbidden
11+
--> $DIR/raw-ptr-const-param-deref.rs:6:23
12+
|
13+
LL | struct Const<const P: *const u32>;
14+
| ^^^^^^^^^^
15+
16+
error: using raw pointers as const generic parameters is forbidden
17+
--> $DIR/raw-ptr-const-param-deref.rs:8:15
18+
|
19+
LL | impl<const P: *const u32> Const<P> {
20+
| ^^^^^^^^^^
21+
22+
error: aborting due to 2 previous errors; 1 warning emitted
1123

Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
#![feature(const_generics, const_compare_raw_pointers)]
1+
#![feature(const_generics)]
22
//~^ WARN the feature `const_generics` is incomplete
33

4-
struct Const<const P: *const u32>;
4+
struct Const<const P: *const u32>; //~ ERROR: using raw pointers as const generic parameters
55

66
fn main() {
7-
let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>; //~ mismatched types
7+
let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>;
88
let _: Const<{ 10 as *const _ }> = Const::<{ 10 as *const _ }>;
99
}
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
22
--> $DIR/raw-ptr-const-param.rs:1:12
33
|
4-
LL | #![feature(const_generics, const_compare_raw_pointers)]
4+
LL | #![feature(const_generics)]
55
| ^^^^^^^^^^^^^^
66
|
77
= note: `#[warn(incomplete_features)]` on by default
88
= note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
99

10-
error[E0308]: mismatched types
11-
--> $DIR/raw-ptr-const-param.rs:7:40
10+
error: using raw pointers as const generic parameters is forbidden
11+
--> $DIR/raw-ptr-const-param.rs:4:23
1212
|
13-
LL | let _: Const<{ 15 as *const _ }> = Const::<{ 10 as *const _ }>;
14-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{0xf as *const u32}`, found `{0xa as *const u32}`
15-
|
16-
= note: expected type `{0xf as *const u32}`
17-
found type `{0xa as *const u32}`
13+
LL | struct Const<const P: *const u32>;
14+
| ^^^^^^^^^^
1815

1916
error: aborting due to previous error; 1 warning emitted
2017

21-
For more information about this error, try `rustc --explain E0308`.
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,6 @@
1-
#![feature(const_raw_ptr_to_usize_cast, const_compare_raw_pointers, const_raw_ptr_deref)]
2-
31
fn main() {}
42

53
// unconst and bad, will thus error in miri
6-
const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR any use of this
7-
// unconst and bad, will thus error in miri
8-
const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; //~ ERROR any use of this
9-
// unconst and fine
10-
const Y: usize = unsafe { 42usize as *const i32 as usize + 1 };
11-
// unconst and bad, will thus error in miri
12-
const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; //~ ERROR any use of this
13-
// unconst and fine
14-
const Z: i32 = unsafe { *(&1 as *const i32) };
4+
const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR cannot be compared
155
// unconst and bad, will thus error in miri
16-
const Z2: i32 = unsafe { *(42 as *const i32) }; //~ ERROR any use of this value will cause
17-
const Z3: i32 = unsafe { *(44 as *const i32) }; //~ ERROR any use of this value will cause
6+
const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; //~ ERROR cannot be compared

0 commit comments

Comments
 (0)