Skip to content

Commit

Permalink
Auto merge of rust-lang#104646 - matthiaskrgr:rollup-7xnhzf0, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

Rollup of 6 pull requests

Successful merges:

 - rust-lang#104537 (fix std::thread docs are unclear regarding stack sizes)
 - rust-lang#104558 (Don't assume `FILE_ID_BOTH_DIR_INFO` will be aligned)
 - rust-lang#104564 (interpret: use Either over Result when it is not representing an error condition)
 - rust-lang#104568 (clarify that realloc refreshes pointer provenance even when the allocation remains in-place)
 - rust-lang#104611 (rustdoc: use real buttons for scrape examples controls)
 - rust-lang#104640 (Migrate kdb style to CSS variables)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Nov 20, 2022
2 parents 911cbf8 + 2aa7f54 commit a28f3c8
Show file tree
Hide file tree
Showing 36 changed files with 291 additions and 145 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3433,6 +3433,7 @@ dependencies = [
name = "rustc_const_eval"
version = "0.0.0"
dependencies = [
"either",
"rustc_apfloat",
"rustc_ast",
"rustc_attr",
Expand Down Expand Up @@ -3927,6 +3928,7 @@ dependencies = [
name = "rustc_mir_build"
version = "0.0.0"
dependencies = [
"either",
"rustc_apfloat",
"rustc_arena",
"rustc_ast",
Expand Down Expand Up @@ -3973,6 +3975,7 @@ name = "rustc_mir_transform"
version = "0.0.0"
dependencies = [
"coverage_test_macros",
"either",
"itertools",
"rustc_ast",
"rustc_attr",
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_const_eval/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ edition = "2021"

[dependencies]
tracing = "0.1"
either = "1"
rustc_apfloat = { path = "../rustc_apfloat" }
rustc_ast = { path = "../rustc_ast" }
rustc_attr = { path = "../rustc_attr" }
Expand Down
29 changes: 16 additions & 13 deletions compiler/rustc_const_eval/src/const_eval/eval_queries.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
use super::{CompileTimeEvalContext, CompileTimeInterpreter, ConstEvalErr};
use crate::interpret::eval_nullary_intrinsic;
use crate::interpret::{
intern_const_alloc_recursive, Allocation, ConstAlloc, ConstValue, CtfeValidationMode, GlobalId,
Immediate, InternKind, InterpCx, InterpError, InterpResult, MPlaceTy, MemoryKind, OpTy,
RefTracking, StackPopCleanup,
};
use std::borrow::Cow;
use std::convert::TryInto;

use either::{Left, Right};

use rustc_hir::def::DefKind;
use rustc_middle::mir;
Expand All @@ -16,8 +13,14 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::source_map::Span;
use rustc_target::abi::{self, Abi};
use std::borrow::Cow;
use std::convert::TryInto;

use super::{CompileTimeEvalContext, CompileTimeInterpreter, ConstEvalErr};
use crate::interpret::eval_nullary_intrinsic;
use crate::interpret::{
intern_const_alloc_recursive, Allocation, ConstAlloc, ConstValue, CtfeValidationMode, GlobalId,
Immediate, InternKind, InterpCx, InterpError, InterpResult, MPlaceTy, MemoryKind, OpTy,
RefTracking, StackPopCleanup,
};

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

debug!(?immediate);
Expand All @@ -168,9 +171,9 @@ pub(super) fn op_to_const<'tcx>(
}
};
match immediate {
Ok(ref mplace) => to_const_value(mplace),
Left(ref mplace) => to_const_value(mplace),
// see comment on `let try_as_immediate` above
Err(imm) => match *imm {
Right(imm) => match *imm {
_ if imm.layout.is_zst() => ConstValue::ZeroSized,
Immediate::Scalar(x) => ConstValue::Scalar(x),
Immediate::ScalarPair(a, b) => {
Expand Down
32 changes: 16 additions & 16 deletions compiler/rustc_const_eval/src/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use std::cell::Cell;
use std::fmt;
use std::mem;

use either::{Either, Left, Right};

use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData};
use rustc_index::vec::IndexVec;
use rustc_middle::mir;
Expand Down Expand Up @@ -121,13 +123,12 @@ pub struct Frame<'mir, 'tcx, Prov: Provenance = AllocId, Extra = ()> {
////////////////////////////////////////////////////////////////////////////////
// Current position within the function
////////////////////////////////////////////////////////////////////////////////
/// If this is `Err`, we are not currently executing any particular statement in
/// If this is `Right`, we are not currently executing any particular statement in
/// this frame (can happen e.g. during frame initialization, and during unwinding on
/// frames without cleanup code).
/// We basically abuse `Result` as `Either`.
///
/// Needs to be public because ConstProp does unspeakable things to it.
pub loc: Result<mir::Location, Span>,
pub loc: Either<mir::Location, Span>,
}

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

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

pub fn current_span(&self) -> Span {
match self.loc {
Ok(loc) => self.body.source_info(loc).span,
Err(span) => span,
Left(loc) => self.body.source_info(loc).span,
Right(span) => span,
}
}
}
Expand Down Expand Up @@ -679,7 +679,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// first push a stack frame so we have access to the local substs
let pre_frame = Frame {
body,
loc: Err(body.span), // Span used for errors caused during preamble.
loc: Right(body.span), // Span used for errors caused during preamble.
return_to_block,
return_place: return_place.clone(),
// empty local array, we fill it in below, after we are inside the stack frame and
Expand Down Expand Up @@ -713,7 +713,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// done
self.frame_mut().locals = locals;
M::after_stack_push(self)?;
self.frame_mut().loc = Ok(mir::Location::START);
self.frame_mut().loc = Left(mir::Location::START);

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

/// *Return* to the given `target` basic block.
Expand All @@ -750,8 +750,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// unwinding, and doing so is UB.
pub fn unwind_to_block(&mut self, target: StackPopUnwind) -> InterpResult<'tcx> {
self.frame_mut().loc = match target {
StackPopUnwind::Cleanup(block) => Ok(mir::Location { block, statement_index: 0 }),
StackPopUnwind::Skip => Err(self.frame_mut().body.span),
StackPopUnwind::Cleanup(block) => Left(mir::Location { block, statement_index: 0 }),
StackPopUnwind::Skip => Right(self.frame_mut().body.span),
StackPopUnwind::NotAllowed => {
throw_ub_format!("unwinding past a stack frame that does not allow unwinding")
}
Expand Down Expand Up @@ -783,8 +783,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
assert_eq!(
unwinding,
match self.frame().loc {
Ok(loc) => self.body().basic_blocks[loc.block].is_cleanup,
Err(_) => true,
Left(loc) => self.body().basic_blocks[loc.block].is_cleanup,
Right(_) => true,
}
);
if unwinding && self.frame_idx() == 0 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
debug!("find_closest_untracked_caller_location: checking frame {:?}", frame.instance);

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

// This could be a non-`Call` terminator (such as `Drop`), or not a terminator at all
// (such as `box`). Use the normal span by default.
Expand Down
32 changes: 17 additions & 15 deletions compiler/rustc_const_eval/src/interpret/operand.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Functions concerning immediate values and operands, and reading from operands.
//! All high-level functions to read from memory work on operands as sources.
use either::{Either, Left, Right};

use rustc_hir::def::Namespace;
use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout};
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter};
Expand Down Expand Up @@ -261,9 +263,9 @@ impl<'tcx, Prov: Provenance> OpTy<'tcx, Prov> {
layout: TyAndLayout<'tcx>,
cx: &impl HasDataLayout,
) -> InterpResult<'tcx, Self> {
match self.try_as_mplace() {
Ok(mplace) => Ok(mplace.offset_with_meta(offset, meta, layout, cx)?.into()),
Err(imm) => {
match self.as_mplace_or_imm() {
Left(mplace) => Ok(mplace.offset_with_meta(offset, meta, layout, cx)?.into()),
Right(imm) => {
assert!(
matches!(*imm, Immediate::Uninit),
"Scalar/ScalarPair cannot be offset into"
Expand Down Expand Up @@ -353,25 +355,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {

/// Try returning an immediate for the operand. If the layout does not permit loading this as an
/// immediate, return where in memory we can find the data.
/// Note that for a given layout, this operation will either always fail or always
/// succeed! Whether it succeeds depends on whether the layout can be represented
/// Note that for a given layout, this operation will either always return Left or Right!
/// succeed! Whether it returns Left depends on whether the layout can be represented
/// in an `Immediate`, not on which data is stored there currently.
///
/// This is an internal function that should not usually be used; call `read_immediate` instead.
/// ConstProp needs it, though.
pub fn read_immediate_raw(
&self,
src: &OpTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx, Result<ImmTy<'tcx, M::Provenance>, MPlaceTy<'tcx, M::Provenance>>> {
Ok(match src.try_as_mplace() {
Ok(ref mplace) => {
) -> InterpResult<'tcx, Either<MPlaceTy<'tcx, M::Provenance>, ImmTy<'tcx, M::Provenance>>> {
Ok(match src.as_mplace_or_imm() {
Left(ref mplace) => {
if let Some(val) = self.read_immediate_from_mplace_raw(mplace)? {
Ok(val)
Right(val)
} else {
Err(*mplace)
Left(*mplace)
}
}
Err(val) => Ok(val),
Right(val) => Right(val),
})
}

Expand All @@ -390,7 +392,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
) {
span_bug!(self.cur_span(), "primitive read not possible for type: {:?}", op.layout.ty);
}
let imm = self.read_immediate_raw(op)?.unwrap();
let imm = self.read_immediate_raw(op)?.right().unwrap();
if matches!(*imm, Immediate::Uninit) {
throw_ub!(InvalidUninitBytes(None));
}
Expand Down Expand Up @@ -432,9 +434,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// Basically we just transmute this place into an array following simd_size_and_type.
// This only works in memory, but repr(simd) types should never be immediates anyway.
assert!(op.layout.ty.is_simd());
match op.try_as_mplace() {
Ok(mplace) => self.mplace_to_simd(&mplace),
Err(imm) => match *imm {
match op.as_mplace_or_imm() {
Left(mplace) => self.mplace_to_simd(&mplace),
Right(imm) => match *imm {
Immediate::Uninit => {
throw_ub!(InvalidUninitBytes(None))
}
Expand Down
28 changes: 15 additions & 13 deletions compiler/rustc_const_eval/src/interpret/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
//! into a place.
//! All high-level functions to write to memory work on places as destinations.
use either::{Either, Left, Right};

use rustc_ast::Mutability;
use rustc_middle::mir;
use rustc_middle::ty;
Expand Down Expand Up @@ -252,36 +254,36 @@ impl<'tcx, Prov: Provenance> MPlaceTy<'tcx, Prov> {
// These are defined here because they produce a place.
impl<'tcx, Prov: Provenance> OpTy<'tcx, Prov> {
#[inline(always)]
pub fn try_as_mplace(&self) -> Result<MPlaceTy<'tcx, Prov>, ImmTy<'tcx, Prov>> {
pub fn as_mplace_or_imm(&self) -> Either<MPlaceTy<'tcx, Prov>, ImmTy<'tcx, Prov>> {
match **self {
Operand::Indirect(mplace) => {
Ok(MPlaceTy { mplace, layout: self.layout, align: self.align.unwrap() })
Left(MPlaceTy { mplace, layout: self.layout, align: self.align.unwrap() })
}
Operand::Immediate(imm) => Err(ImmTy::from_immediate(imm, self.layout)),
Operand::Immediate(imm) => Right(ImmTy::from_immediate(imm, self.layout)),
}
}

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

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

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

Expand Down Expand Up @@ -569,9 +571,9 @@ where
}

pub fn write_uninit(&mut self, dest: &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx> {
let mplace = match dest.try_as_mplace() {
Ok(mplace) => mplace,
Err((frame, local)) => {
let mplace = match dest.as_mplace_or_local() {
Left(mplace) => mplace,
Right((frame, local)) => {
match M::access_local_mut(self, frame, local)? {
Operand::Immediate(local) => {
*local = Immediate::Uninit;
Expand Down Expand Up @@ -639,7 +641,7 @@ where
// Let us see if the layout is simple so we take a shortcut,
// avoid force_allocation.
let src = match self.read_immediate_raw(src)? {
Ok(src_val) => {
Right(src_val) => {
// FIXME(const_prop): Const-prop can possibly evaluate an
// unsized copy operation when it thinks that the type is
// actually sized, due to a trivially false where-clause
Expand Down Expand Up @@ -669,7 +671,7 @@ where
)
};
}
Err(mplace) => mplace,
Left(mplace) => mplace,
};
// Slow path, this does not fit into an immediate. Just memcpy.
trace!("copy_op: {:?} <- {:?}: {}", *dest, src, dest.layout.ty);
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_const_eval/src/interpret/projection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
//! but we still need to do bounds checking and adjust the layout. To not duplicate that with MPlaceTy, we actually
//! implement the logic on OpTy, and MPlaceTy calls that.
use either::{Left, Right};

use rustc_middle::mir;
use rustc_middle::ty;
use rustc_middle::ty::layout::LayoutOf;
Expand Down Expand Up @@ -84,13 +86,13 @@ where
base: &OpTy<'tcx, M::Provenance>,
field: usize,
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
let base = match base.try_as_mplace() {
Ok(ref mplace) => {
let base = match base.as_mplace_or_imm() {
Left(ref mplace) => {
// We can reuse the mplace field computation logic for indirect operands.
let field = self.mplace_field(mplace, field)?;
return Ok(field.into());
}
Err(value) => value,
Right(value) => value,
};

let field_layout = base.layout.field(self, field);
Expand Down
Loading

0 comments on commit a28f3c8

Please sign in to comment.