Skip to content

Commit a28f3c8

Browse files
committed
Auto merge of #104646 - matthiaskrgr:rollup-7xnhzf0, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #104537 (fix std::thread docs are unclear regarding stack sizes) - #104558 (Don't assume `FILE_ID_BOTH_DIR_INFO` will be aligned) - #104564 (interpret: use Either over Result when it is not representing an error condition) - #104568 (clarify that realloc refreshes pointer provenance even when the allocation remains in-place) - #104611 (rustdoc: use real buttons for scrape examples controls) - #104640 (Migrate kdb style to CSS variables) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 911cbf8 + 2aa7f54 commit a28f3c8

File tree

36 files changed

+291
-145
lines changed

36 files changed

+291
-145
lines changed

Cargo.lock

+3
Original file line numberDiff line numberDiff line change
@@ -3433,6 +3433,7 @@ dependencies = [
34333433
name = "rustc_const_eval"
34343434
version = "0.0.0"
34353435
dependencies = [
3436+
"either",
34363437
"rustc_apfloat",
34373438
"rustc_ast",
34383439
"rustc_attr",
@@ -3927,6 +3928,7 @@ dependencies = [
39273928
name = "rustc_mir_build"
39283929
version = "0.0.0"
39293930
dependencies = [
3931+
"either",
39303932
"rustc_apfloat",
39313933
"rustc_arena",
39323934
"rustc_ast",
@@ -3973,6 +3975,7 @@ name = "rustc_mir_transform"
39733975
version = "0.0.0"
39743976
dependencies = [
39753977
"coverage_test_macros",
3978+
"either",
39763979
"itertools",
39773980
"rustc_ast",
39783981
"rustc_attr",

compiler/rustc_const_eval/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ edition = "2021"
77

88
[dependencies]
99
tracing = "0.1"
10+
either = "1"
1011
rustc_apfloat = { path = "../rustc_apfloat" }
1112
rustc_ast = { path = "../rustc_ast" }
1213
rustc_attr = { path = "../rustc_attr" }

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

+16-13
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
use super::{CompileTimeEvalContext, CompileTimeInterpreter, ConstEvalErr};
2-
use crate::interpret::eval_nullary_intrinsic;
3-
use crate::interpret::{
4-
intern_const_alloc_recursive, Allocation, ConstAlloc, ConstValue, CtfeValidationMode, GlobalId,
5-
Immediate, InternKind, InterpCx, InterpError, InterpResult, MPlaceTy, MemoryKind, OpTy,
6-
RefTracking, StackPopCleanup,
7-
};
1+
use std::borrow::Cow;
2+
use std::convert::TryInto;
3+
4+
use either::{Left, Right};
85

96
use rustc_hir::def::DefKind;
107
use rustc_middle::mir;
@@ -16,8 +13,14 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
1613
use rustc_middle::ty::{self, TyCtxt};
1714
use rustc_span::source_map::Span;
1815
use rustc_target::abi::{self, Abi};
19-
use std::borrow::Cow;
20-
use std::convert::TryInto;
16+
17+
use super::{CompileTimeEvalContext, CompileTimeInterpreter, ConstEvalErr};
18+
use crate::interpret::eval_nullary_intrinsic;
19+
use crate::interpret::{
20+
intern_const_alloc_recursive, Allocation, ConstAlloc, ConstValue, CtfeValidationMode, GlobalId,
21+
Immediate, InternKind, InterpCx, InterpError, InterpResult, MPlaceTy, MemoryKind, OpTy,
22+
RefTracking, StackPopCleanup,
23+
};
2124

2225
const NOTE_ON_UNDEFINED_BEHAVIOR_ERROR: &str = "The rules on what exactly is undefined behavior aren't clear, \
2326
so this check might be overzealous. Please open an issue on the rustc \
@@ -135,14 +138,14 @@ pub(super) fn op_to_const<'tcx>(
135138
_ => false,
136139
};
137140
let immediate = if try_as_immediate {
138-
Err(ecx.read_immediate(op).expect("normalization works on validated constants"))
141+
Right(ecx.read_immediate(op).expect("normalization works on validated constants"))
139142
} else {
140143
// It is guaranteed that any non-slice scalar pair is actually ByRef here.
141144
// When we come back from raw const eval, we are always by-ref. The only way our op here is
142145
// by-val is if we are in destructure_mir_constant, i.e., if this is (a field of) something that we
143146
// "tried to make immediate" before. We wouldn't do that for non-slice scalar pairs or
144147
// structs containing such.
145-
op.try_as_mplace()
148+
op.as_mplace_or_imm()
146149
};
147150

148151
debug!(?immediate);
@@ -168,9 +171,9 @@ pub(super) fn op_to_const<'tcx>(
168171
}
169172
};
170173
match immediate {
171-
Ok(ref mplace) => to_const_value(mplace),
174+
Left(ref mplace) => to_const_value(mplace),
172175
// see comment on `let try_as_immediate` above
173-
Err(imm) => match *imm {
176+
Right(imm) => match *imm {
174177
_ if imm.layout.is_zst() => ConstValue::ZeroSized,
175178
Immediate::Scalar(x) => ConstValue::Scalar(x),
176179
Immediate::ScalarPair(a, b) => {

compiler/rustc_const_eval/src/interpret/eval_context.rs

+16-16
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use std::cell::Cell;
22
use std::fmt;
33
use std::mem;
44

5+
use either::{Either, Left, Right};
6+
57
use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData};
68
use rustc_index::vec::IndexVec;
79
use rustc_middle::mir;
@@ -121,13 +123,12 @@ pub struct Frame<'mir, 'tcx, Prov: Provenance = AllocId, Extra = ()> {
121123
////////////////////////////////////////////////////////////////////////////////
122124
// Current position within the function
123125
////////////////////////////////////////////////////////////////////////////////
124-
/// If this is `Err`, we are not currently executing any particular statement in
126+
/// If this is `Right`, we are not currently executing any particular statement in
125127
/// this frame (can happen e.g. during frame initialization, and during unwinding on
126128
/// frames without cleanup code).
127-
/// We basically abuse `Result` as `Either`.
128129
///
129130
/// Needs to be public because ConstProp does unspeakable things to it.
130-
pub loc: Result<mir::Location, Span>,
131+
pub loc: Either<mir::Location, Span>,
131132
}
132133

133134
/// What we store about a frame in an interpreter backtrace.
@@ -227,25 +228,24 @@ impl<'mir, 'tcx, Prov: Provenance> Frame<'mir, 'tcx, Prov> {
227228
impl<'mir, 'tcx, Prov: Provenance, Extra> Frame<'mir, 'tcx, Prov, Extra> {
228229
/// Get the current location within the Frame.
229230
///
230-
/// If this is `Err`, we are not currently executing any particular statement in
231+
/// If this is `Left`, we are not currently executing any particular statement in
231232
/// this frame (can happen e.g. during frame initialization, and during unwinding on
232233
/// frames without cleanup code).
233-
/// We basically abuse `Result` as `Either`.
234234
///
235235
/// Used by priroda.
236-
pub fn current_loc(&self) -> Result<mir::Location, Span> {
236+
pub fn current_loc(&self) -> Either<mir::Location, Span> {
237237
self.loc
238238
}
239239

240240
/// Return the `SourceInfo` of the current instruction.
241241
pub fn current_source_info(&self) -> Option<&mir::SourceInfo> {
242-
self.loc.ok().map(|loc| self.body.source_info(loc))
242+
self.loc.left().map(|loc| self.body.source_info(loc))
243243
}
244244

245245
pub fn current_span(&self) -> Span {
246246
match self.loc {
247-
Ok(loc) => self.body.source_info(loc).span,
248-
Err(span) => span,
247+
Left(loc) => self.body.source_info(loc).span,
248+
Right(span) => span,
249249
}
250250
}
251251
}
@@ -679,7 +679,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
679679
// first push a stack frame so we have access to the local substs
680680
let pre_frame = Frame {
681681
body,
682-
loc: Err(body.span), // Span used for errors caused during preamble.
682+
loc: Right(body.span), // Span used for errors caused during preamble.
683683
return_to_block,
684684
return_place: return_place.clone(),
685685
// empty local array, we fill it in below, after we are inside the stack frame and
@@ -713,7 +713,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
713713
// done
714714
self.frame_mut().locals = locals;
715715
M::after_stack_push(self)?;
716-
self.frame_mut().loc = Ok(mir::Location::START);
716+
self.frame_mut().loc = Left(mir::Location::START);
717717

718718
let span = info_span!("frame", "{}", instance);
719719
self.frame_mut().tracing_span.enter(span);
@@ -724,7 +724,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
724724
/// Jump to the given block.
725725
#[inline]
726726
pub fn go_to_block(&mut self, target: mir::BasicBlock) {
727-
self.frame_mut().loc = Ok(mir::Location { block: target, statement_index: 0 });
727+
self.frame_mut().loc = Left(mir::Location { block: target, statement_index: 0 });
728728
}
729729

730730
/// *Return* to the given `target` basic block.
@@ -750,8 +750,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
750750
/// unwinding, and doing so is UB.
751751
pub fn unwind_to_block(&mut self, target: StackPopUnwind) -> InterpResult<'tcx> {
752752
self.frame_mut().loc = match target {
753-
StackPopUnwind::Cleanup(block) => Ok(mir::Location { block, statement_index: 0 }),
754-
StackPopUnwind::Skip => Err(self.frame_mut().body.span),
753+
StackPopUnwind::Cleanup(block) => Left(mir::Location { block, statement_index: 0 }),
754+
StackPopUnwind::Skip => Right(self.frame_mut().body.span),
755755
StackPopUnwind::NotAllowed => {
756756
throw_ub_format!("unwinding past a stack frame that does not allow unwinding")
757757
}
@@ -783,8 +783,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
783783
assert_eq!(
784784
unwinding,
785785
match self.frame().loc {
786-
Ok(loc) => self.body().basic_blocks[loc.block].is_cleanup,
787-
Err(_) => true,
786+
Left(loc) => self.body().basic_blocks[loc.block].is_cleanup,
787+
Right(_) => true,
788788
}
789789
);
790790
if unwinding && self.frame_idx() == 0 {

compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
1919
debug!("find_closest_untracked_caller_location: checking frame {:?}", frame.instance);
2020

2121
// Assert that the frame we look at is actually executing code currently
22-
// (`loc` is `Err` when we are unwinding and the frame does not require cleanup).
23-
let loc = frame.loc.unwrap();
22+
// (`loc` is `Right` when we are unwinding and the frame does not require cleanup).
23+
let loc = frame.loc.left().unwrap();
2424

2525
// This could be a non-`Call` terminator (such as `Drop`), or not a terminator at all
2626
// (such as `box`). Use the normal span by default.

compiler/rustc_const_eval/src/interpret/operand.rs

+17-15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! Functions concerning immediate values and operands, and reading from operands.
22
//! All high-level functions to read from memory work on operands as sources.
33
4+
use either::{Either, Left, Right};
5+
46
use rustc_hir::def::Namespace;
57
use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout};
68
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter};
@@ -261,9 +263,9 @@ impl<'tcx, Prov: Provenance> OpTy<'tcx, Prov> {
261263
layout: TyAndLayout<'tcx>,
262264
cx: &impl HasDataLayout,
263265
) -> InterpResult<'tcx, Self> {
264-
match self.try_as_mplace() {
265-
Ok(mplace) => Ok(mplace.offset_with_meta(offset, meta, layout, cx)?.into()),
266-
Err(imm) => {
266+
match self.as_mplace_or_imm() {
267+
Left(mplace) => Ok(mplace.offset_with_meta(offset, meta, layout, cx)?.into()),
268+
Right(imm) => {
267269
assert!(
268270
matches!(*imm, Immediate::Uninit),
269271
"Scalar/ScalarPair cannot be offset into"
@@ -353,25 +355,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
353355

354356
/// Try returning an immediate for the operand. If the layout does not permit loading this as an
355357
/// immediate, return where in memory we can find the data.
356-
/// Note that for a given layout, this operation will either always fail or always
357-
/// succeed! Whether it succeeds depends on whether the layout can be represented
358+
/// Note that for a given layout, this operation will either always return Left or Right!
359+
/// succeed! Whether it returns Left depends on whether the layout can be represented
358360
/// in an `Immediate`, not on which data is stored there currently.
359361
///
360362
/// This is an internal function that should not usually be used; call `read_immediate` instead.
361363
/// ConstProp needs it, though.
362364
pub fn read_immediate_raw(
363365
&self,
364366
src: &OpTy<'tcx, M::Provenance>,
365-
) -> InterpResult<'tcx, Result<ImmTy<'tcx, M::Provenance>, MPlaceTy<'tcx, M::Provenance>>> {
366-
Ok(match src.try_as_mplace() {
367-
Ok(ref mplace) => {
367+
) -> InterpResult<'tcx, Either<MPlaceTy<'tcx, M::Provenance>, ImmTy<'tcx, M::Provenance>>> {
368+
Ok(match src.as_mplace_or_imm() {
369+
Left(ref mplace) => {
368370
if let Some(val) = self.read_immediate_from_mplace_raw(mplace)? {
369-
Ok(val)
371+
Right(val)
370372
} else {
371-
Err(*mplace)
373+
Left(*mplace)
372374
}
373375
}
374-
Err(val) => Ok(val),
376+
Right(val) => Right(val),
375377
})
376378
}
377379

@@ -390,7 +392,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
390392
) {
391393
span_bug!(self.cur_span(), "primitive read not possible for type: {:?}", op.layout.ty);
392394
}
393-
let imm = self.read_immediate_raw(op)?.unwrap();
395+
let imm = self.read_immediate_raw(op)?.right().unwrap();
394396
if matches!(*imm, Immediate::Uninit) {
395397
throw_ub!(InvalidUninitBytes(None));
396398
}
@@ -432,9 +434,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
432434
// Basically we just transmute this place into an array following simd_size_and_type.
433435
// This only works in memory, but repr(simd) types should never be immediates anyway.
434436
assert!(op.layout.ty.is_simd());
435-
match op.try_as_mplace() {
436-
Ok(mplace) => self.mplace_to_simd(&mplace),
437-
Err(imm) => match *imm {
437+
match op.as_mplace_or_imm() {
438+
Left(mplace) => self.mplace_to_simd(&mplace),
439+
Right(imm) => match *imm {
438440
Immediate::Uninit => {
439441
throw_ub!(InvalidUninitBytes(None))
440442
}

compiler/rustc_const_eval/src/interpret/place.rs

+15-13
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
//! into a place.
33
//! All high-level functions to write to memory work on places as destinations.
44
5+
use either::{Either, Left, Right};
6+
57
use rustc_ast::Mutability;
68
use rustc_middle::mir;
79
use rustc_middle::ty;
@@ -252,36 +254,36 @@ impl<'tcx, Prov: Provenance> MPlaceTy<'tcx, Prov> {
252254
// These are defined here because they produce a place.
253255
impl<'tcx, Prov: Provenance> OpTy<'tcx, Prov> {
254256
#[inline(always)]
255-
pub fn try_as_mplace(&self) -> Result<MPlaceTy<'tcx, Prov>, ImmTy<'tcx, Prov>> {
257+
pub fn as_mplace_or_imm(&self) -> Either<MPlaceTy<'tcx, Prov>, ImmTy<'tcx, Prov>> {
256258
match **self {
257259
Operand::Indirect(mplace) => {
258-
Ok(MPlaceTy { mplace, layout: self.layout, align: self.align.unwrap() })
260+
Left(MPlaceTy { mplace, layout: self.layout, align: self.align.unwrap() })
259261
}
260-
Operand::Immediate(imm) => Err(ImmTy::from_immediate(imm, self.layout)),
262+
Operand::Immediate(imm) => Right(ImmTy::from_immediate(imm, self.layout)),
261263
}
262264
}
263265

264266
#[inline(always)]
265267
#[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980)
266268
pub fn assert_mem_place(&self) -> MPlaceTy<'tcx, Prov> {
267-
self.try_as_mplace().unwrap()
269+
self.as_mplace_or_imm().left().unwrap()
268270
}
269271
}
270272

271273
impl<'tcx, Prov: Provenance> PlaceTy<'tcx, Prov> {
272274
/// A place is either an mplace or some local.
273275
#[inline]
274-
pub fn try_as_mplace(&self) -> Result<MPlaceTy<'tcx, Prov>, (usize, mir::Local)> {
276+
pub fn as_mplace_or_local(&self) -> Either<MPlaceTy<'tcx, Prov>, (usize, mir::Local)> {
275277
match **self {
276-
Place::Ptr(mplace) => Ok(MPlaceTy { mplace, layout: self.layout, align: self.align }),
277-
Place::Local { frame, local } => Err((frame, local)),
278+
Place::Ptr(mplace) => Left(MPlaceTy { mplace, layout: self.layout, align: self.align }),
279+
Place::Local { frame, local } => Right((frame, local)),
278280
}
279281
}
280282

281283
#[inline(always)]
282284
#[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980)
283285
pub fn assert_mem_place(&self) -> MPlaceTy<'tcx, Prov> {
284-
self.try_as_mplace().unwrap()
286+
self.as_mplace_or_local().left().unwrap()
285287
}
286288
}
287289

@@ -569,9 +571,9 @@ where
569571
}
570572

571573
pub fn write_uninit(&mut self, dest: &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx> {
572-
let mplace = match dest.try_as_mplace() {
573-
Ok(mplace) => mplace,
574-
Err((frame, local)) => {
574+
let mplace = match dest.as_mplace_or_local() {
575+
Left(mplace) => mplace,
576+
Right((frame, local)) => {
575577
match M::access_local_mut(self, frame, local)? {
576578
Operand::Immediate(local) => {
577579
*local = Immediate::Uninit;
@@ -639,7 +641,7 @@ where
639641
// Let us see if the layout is simple so we take a shortcut,
640642
// avoid force_allocation.
641643
let src = match self.read_immediate_raw(src)? {
642-
Ok(src_val) => {
644+
Right(src_val) => {
643645
// FIXME(const_prop): Const-prop can possibly evaluate an
644646
// unsized copy operation when it thinks that the type is
645647
// actually sized, due to a trivially false where-clause
@@ -669,7 +671,7 @@ where
669671
)
670672
};
671673
}
672-
Err(mplace) => mplace,
674+
Left(mplace) => mplace,
673675
};
674676
// Slow path, this does not fit into an immediate. Just memcpy.
675677
trace!("copy_op: {:?} <- {:?}: {}", *dest, src, dest.layout.ty);

compiler/rustc_const_eval/src/interpret/projection.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
//! but we still need to do bounds checking and adjust the layout. To not duplicate that with MPlaceTy, we actually
88
//! implement the logic on OpTy, and MPlaceTy calls that.
99
10+
use either::{Left, Right};
11+
1012
use rustc_middle::mir;
1113
use rustc_middle::ty;
1214
use rustc_middle::ty::layout::LayoutOf;
@@ -84,13 +86,13 @@ where
8486
base: &OpTy<'tcx, M::Provenance>,
8587
field: usize,
8688
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
87-
let base = match base.try_as_mplace() {
88-
Ok(ref mplace) => {
89+
let base = match base.as_mplace_or_imm() {
90+
Left(ref mplace) => {
8991
// We can reuse the mplace field computation logic for indirect operands.
9092
let field = self.mplace_field(mplace, field)?;
9193
return Ok(field.into());
9294
}
93-
Err(value) => value,
95+
Right(value) => value,
9496
};
9597

9698
let field_layout = base.layout.field(self, field);

0 commit comments

Comments
 (0)