Skip to content

Commit 3313e76

Browse files
Rollup merge of #132423 - RalfJung:const-eval-align-offset, r=dtolnay
remove const-support for align_offset and is_aligned As part of the recent discussion to stabilize `ptr.is_null()` in const context, the general vibe was that it's okay for a const function to panic when the same operation would work at runtime (that's just a case of "dynamically detecting that something is not supported as a const operation"), but it is *not* okay for a const function to just return a different result. Following that, `is_aligned` and `is_aligned_to` have their const status revoked in this PR, since they do return actively wrong results at const time. In the future we can consider having a new intrinsic or so that can check whether a pointer is "guaranteed to be aligned", but the current implementation based on `align_offset` does not have the behavior we want. In fact `align_offset` itself behaves quite strangely in const, and that support needs a bunch of special hacks. That doesn't seem worth it. Instead, the users that can fall back to a different implementation should just use const_eval_select directly, and everything else should not be made const-callable. So this PR does exactly that, and entirely removes const support for align_offset. Closes some tracking issues by removing the associated features: Closes #90962 Closes #104203 Cc `@rust-lang/wg-const-eval` `@rust-lang/libs-api`
2 parents f35433e + 19e2870 commit 3313e76

File tree

16 files changed

+183
-1020
lines changed

16 files changed

+183
-1020
lines changed

Diff for: compiler/rustc_const_eval/messages.ftl

-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
const_eval_address_space_full =
22
there are no more free addresses in the address space
33
4-
const_eval_align_offset_invalid_align =
5-
`align_offset` called with non-power-of-two align: {$target_align}
6-
74
const_eval_alignment_check_failed =
85
{$msg ->
96
[AccessedPtr] accessing memory

Diff for: compiler/rustc_const_eval/src/const_eval/machine.rs

+6-82
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use std::borrow::{Borrow, Cow};
22
use std::fmt;
33
use std::hash::Hash;
4-
use std::ops::ControlFlow;
54

65
use rustc_abi::{Align, ExternAbi, Size};
76
use rustc_ast::Mutability;
@@ -10,7 +9,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
109
use rustc_hir::{self as hir, CRATE_HIR_ID, LangItem};
1110
use rustc_middle::mir::AssertMessage;
1211
use rustc_middle::query::TyCtxtAt;
13-
use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout};
12+
use rustc_middle::ty::layout::TyAndLayout;
1413
use rustc_middle::ty::{self, Ty, TyCtxt};
1514
use rustc_middle::{bug, mir};
1615
use rustc_span::Span;
@@ -22,9 +21,9 @@ use crate::errors::{LongRunning, LongRunningWarn};
2221
use crate::fluent_generated as fluent;
2322
use crate::interpret::{
2423
self, AllocId, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, GlobalAlloc, ImmTy,
25-
InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic, RangeSet, Scalar,
26-
StackPopCleanup, compile_time_machine, interp_ok, throw_exhaust, throw_inval, throw_ub,
27-
throw_ub_custom, throw_unsup, throw_unsup_format,
24+
InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, RangeSet, Scalar, compile_time_machine,
25+
interp_ok, throw_exhaust, throw_inval, throw_ub, throw_ub_custom, throw_unsup,
26+
throw_unsup_format,
2827
};
2928

3029
/// When hitting this many interpreted terminators we emit a deny by default lint
@@ -226,8 +225,8 @@ impl<'tcx> CompileTimeInterpCx<'tcx> {
226225
&mut self,
227226
instance: ty::Instance<'tcx>,
228227
args: &[FnArg<'tcx>],
229-
dest: &MPlaceTy<'tcx>,
230-
ret: Option<mir::BasicBlock>,
228+
_dest: &MPlaceTy<'tcx>,
229+
_ret: Option<mir::BasicBlock>,
231230
) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
232231
let def_id = instance.def_id();
233232

@@ -259,85 +258,10 @@ impl<'tcx> CompileTimeInterpCx<'tcx> {
259258
);
260259

261260
return interp_ok(Some(new_instance));
262-
} else if self.tcx.is_lang_item(def_id, LangItem::AlignOffset) {
263-
let args = self.copy_fn_args(args);
264-
// For align_offset, we replace the function call if the pointer has no address.
265-
match self.align_offset(instance, &args, dest, ret)? {
266-
ControlFlow::Continue(()) => return interp_ok(Some(instance)),
267-
ControlFlow::Break(()) => return interp_ok(None),
268-
}
269261
}
270262
interp_ok(Some(instance))
271263
}
272264

273-
/// `align_offset(ptr, target_align)` needs special handling in const eval, because the pointer
274-
/// may not have an address.
275-
///
276-
/// If `ptr` does have a known address, then we return `Continue(())` and the function call should
277-
/// proceed as normal.
278-
///
279-
/// If `ptr` doesn't have an address, but its underlying allocation's alignment is at most
280-
/// `target_align`, then we call the function again with an dummy address relative to the
281-
/// allocation.
282-
///
283-
/// If `ptr` doesn't have an address and `target_align` is stricter than the underlying
284-
/// allocation's alignment, then we return `usize::MAX` immediately.
285-
fn align_offset(
286-
&mut self,
287-
instance: ty::Instance<'tcx>,
288-
args: &[OpTy<'tcx>],
289-
dest: &MPlaceTy<'tcx>,
290-
ret: Option<mir::BasicBlock>,
291-
) -> InterpResult<'tcx, ControlFlow<()>> {
292-
assert_eq!(args.len(), 2);
293-
294-
let ptr = self.read_pointer(&args[0])?;
295-
let target_align = self.read_scalar(&args[1])?.to_target_usize(self)?;
296-
297-
if !target_align.is_power_of_two() {
298-
throw_ub_custom!(
299-
fluent::const_eval_align_offset_invalid_align,
300-
target_align = target_align,
301-
);
302-
}
303-
304-
match self.ptr_try_get_alloc_id(ptr, 0) {
305-
Ok((alloc_id, offset, _extra)) => {
306-
let (_size, alloc_align, _kind) = self.get_alloc_info(alloc_id);
307-
308-
if target_align <= alloc_align.bytes() {
309-
// Extract the address relative to the allocation base that is definitely
310-
// sufficiently aligned and call `align_offset` again.
311-
let addr = ImmTy::from_uint(offset.bytes(), args[0].layout).into();
312-
let align = ImmTy::from_uint(target_align, args[1].layout).into();
313-
let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?;
314-
315-
// Push the stack frame with our own adjusted arguments.
316-
self.init_stack_frame(
317-
instance,
318-
self.load_mir(instance.def, None)?,
319-
fn_abi,
320-
&[FnArg::Copy(addr), FnArg::Copy(align)],
321-
/* with_caller_location = */ false,
322-
dest,
323-
StackPopCleanup::Goto { ret, unwind: mir::UnwindAction::Unreachable },
324-
)?;
325-
interp_ok(ControlFlow::Break(()))
326-
} else {
327-
// Not alignable in const, return `usize::MAX`.
328-
let usize_max = Scalar::from_target_usize(self.target_usize_max(), self);
329-
self.write_scalar(usize_max, dest)?;
330-
self.return_to_block(ret)?;
331-
interp_ok(ControlFlow::Break(()))
332-
}
333-
}
334-
Err(_addr) => {
335-
// The pointer has an address, continue with function call.
336-
interp_ok(ControlFlow::Continue(()))
337-
}
338-
}
339-
}
340-
341265
/// See documentation on the `ptr_guaranteed_cmp` intrinsic.
342266
fn guaranteed_cmp(&mut self, a: Scalar, b: Scalar) -> InterpResult<'tcx, u8> {
343267
interp_ok(match (a, b) {

Diff for: compiler/rustc_hir/src/lang_items.rs

-3
Original file line numberDiff line numberDiff line change
@@ -348,9 +348,6 @@ language_item_table! {
348348

349349
MaybeUninit, sym::maybe_uninit, maybe_uninit, Target::Union, GenericRequirement::None;
350350

351-
/// Align offset for stride != 1; must not panic.
352-
AlignOffset, sym::align_offset, align_offset_fn, Target::Fn, GenericRequirement::None;
353-
354351
Termination, sym::termination, termination, Target::Trait, GenericRequirement::None;
355352

356353
Try, sym::Try, try_trait, Target::Trait, GenericRequirement::None;

Diff for: compiler/rustc_span/src/symbol.rs

-1
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,6 @@ symbols! {
378378
aggregate_raw_ptr,
379379
alias,
380380
align,
381-
align_offset,
382381
alignment,
383382
all,
384383
alloc,

Diff for: library/core/src/lib.rs

-2
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,6 @@
112112
#![feature(asm_experimental_arch)]
113113
#![feature(const_align_of_val)]
114114
#![feature(const_align_of_val_raw)]
115-
#![feature(const_align_offset)]
116115
#![feature(const_alloc_layout)]
117116
#![feature(const_black_box)]
118117
#![feature(const_char_encode_utf16)]
@@ -123,7 +122,6 @@
123122
#![feature(const_nonnull_new)]
124123
#![feature(const_option_ext)]
125124
#![feature(const_pin_2)]
126-
#![feature(const_pointer_is_aligned)]
127125
#![feature(const_ptr_is_null)]
128126
#![feature(const_ptr_sub_ptr)]
129127
#![feature(const_raw_ptr_comparison)]

0 commit comments

Comments
 (0)