Skip to content

Commit

Permalink
Rollup merge of rust-lang#69181 - skinny121:const-eval-return, r=oli-obk
Browse files Browse the repository at this point in the history
Change const eval to just return the value

As discussed in rust-lang#68505 (comment), the type of consts shouldn't be returned from const eval queries.

r? @eddyb
cc @nikomatsakis
  • Loading branch information
Dylan-DPC authored Feb 18, 2020
2 parents 6317721 + 8904bdd commit 391e7e2
Show file tree
Hide file tree
Showing 25 changed files with 179 additions and 115 deletions.
3 changes: 2 additions & 1 deletion src/librustc/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::{CheckInAllocMsg, Pointer, RawConst, ScalarMaybeUndef};

use crate::hir::map::definitions::DefPathData;
use crate::mir;
use crate::mir::interpret::ConstValue;
use crate::ty::layout::{Align, LayoutError, Size};
use crate::ty::query::TyCtxtAt;
use crate::ty::{self, layout, Ty};
Expand Down Expand Up @@ -40,7 +41,7 @@ CloneTypeFoldableImpls! {
}

pub type ConstEvalRawResult<'tcx> = Result<RawConst<'tcx>, ErrorHandled>;
pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;
pub type ConstEvalResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;

#[derive(Debug)]
pub struct ConstEvalErr<'tcx> {
Expand Down
38 changes: 37 additions & 1 deletion src/librustc/mir/interpret/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::fmt;

use crate::ty::{
layout::{HasDataLayout, Size},
Ty,
ParamEnv, Ty, TyCtxt,
};

use super::{sign_extend, truncate, AllocId, Allocation, InterpResult, Pointer, PointerArithmetic};
Expand Down Expand Up @@ -66,6 +66,32 @@ impl<'tcx> ConstValue<'tcx> {
ConstValue::Scalar(val) => Some(val),
}
}

pub fn try_to_bits(&self, size: Size) -> Option<u128> {
self.try_to_scalar()?.to_bits(size).ok()
}

pub fn try_to_bits_for_ty(
&self,
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
ty: Ty<'tcx>,
) -> Option<u128> {
let size = tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size;
self.try_to_bits(size)
}

pub fn from_bool(b: bool) -> Self {
ConstValue::Scalar(Scalar::from_bool(b))
}

pub fn from_u64(i: u64) -> Self {
ConstValue::Scalar(Scalar::from_u64(i))
}

pub fn from_machine_usize(i: u64, cx: &impl HasDataLayout) -> Self {
ConstValue::Scalar(Scalar::from_machine_usize(i, cx))
}
}

/// A `Scalar` represents an immediate, primitive value existing outside of a
Expand Down Expand Up @@ -287,6 +313,11 @@ impl<'tcx, Tag> Scalar<Tag> {
Scalar::Raw { data: i as u128, size: 8 }
}

#[inline]
pub fn from_machine_usize(i: u64, cx: &impl HasDataLayout) -> Self {
Self::from_uint(i, cx.data_layout().pointer_size)
}

#[inline]
pub fn try_from_int(i: impl Into<i128>, size: Size) -> Option<Self> {
let i = i.into();
Expand All @@ -306,6 +337,11 @@ impl<'tcx, Tag> Scalar<Tag> {
.unwrap_or_else(|| bug!("Signed value {:#x} does not fit in {} bits", i, size.bits()))
}

#[inline]
pub fn from_machine_isize(i: i64, cx: &impl HasDataLayout) -> Self {
Self::from_int(i, cx.data_layout().pointer_size)
}

#[inline]
pub fn from_f32(f: Single) -> Self {
// We trust apfloat to give us properly truncated data.
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ rustc_queries! {
/// Extracts a field of a (variant of a) const.
query const_field(
key: ty::ParamEnvAnd<'tcx, (&'tcx ty::Const<'tcx>, mir::Field)>
) -> &'tcx ty::Const<'tcx> {
) -> ConstValue<'tcx> {
no_force
desc { "extract field of const" }
}
Expand All @@ -533,7 +533,7 @@ rustc_queries! {
desc { "destructure constant" }
}

query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> &'tcx ty::Const<'tcx> {
query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> {
no_force
desc { "get a &core::panic::Location referring to a span" }
}
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2388,10 +2388,10 @@ impl<'tcx> AdtDef {
let repr_type = self.repr.discr_type();
match tcx.const_eval_poly(expr_did) {
Ok(val) => {
// FIXME: Find the right type and use it instead of `val.ty` here
if let Some(b) = val.try_eval_bits(tcx, param_env, val.ty) {
let ty = repr_type.to_ty(tcx);
if let Some(b) = val.try_to_bits_for_ty(tcx, param_env, ty) {
trace!("discriminants: {} ({:?})", b, repr_type);
Some(Discr { val: b, ty: val.ty })
Some(Discr { val: b, ty })
} else {
info!("invalid enum discriminant: {:#?}", val);
crate::mir::interpret::struct_error(
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::middle::resolve_lifetime::{ObjectLifetimeDefault, Region, ResolveLife
use crate::middle::stability::{self, DeprecationEntry};
use crate::mir;
use crate::mir::interpret::GlobalId;
use crate::mir::interpret::{ConstEvalRawResult, ConstEvalResult};
use crate::mir::interpret::{ConstEvalRawResult, ConstEvalResult, ConstValue};
use crate::mir::interpret::{LitToConstError, LitToConstInput};
use crate::mir::mono::CodegenUnit;
use crate::session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
Expand Down
11 changes: 9 additions & 2 deletions src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2417,9 +2417,14 @@ pub struct Const<'tcx> {
static_assert_size!(Const<'_>, 48);

impl<'tcx> Const<'tcx> {
#[inline]
pub fn from_value(tcx: TyCtxt<'tcx>, val: ConstValue<'tcx>, ty: Ty<'tcx>) -> &'tcx Self {
tcx.mk_const(Self { val: ConstKind::Value(val), ty })
}

#[inline]
pub fn from_scalar(tcx: TyCtxt<'tcx>, val: Scalar, ty: Ty<'tcx>) -> &'tcx Self {
tcx.mk_const(Self { val: ConstKind::Value(ConstValue::Scalar(val)), ty })
Self::from_value(tcx, ConstValue::Scalar(val), ty)
}

#[inline]
Expand Down Expand Up @@ -2473,7 +2478,9 @@ impl<'tcx> Const<'tcx> {

// try to resolve e.g. associated constants to their definition on an impl, and then
// evaluate the const.
tcx.const_eval_resolve(param_env, did, substs, promoted, None).ok()
tcx.const_eval_resolve(param_env, did, substs, promoted, None)
.ok()
.map(|val| Const::from_value(tcx, val, self.ty))
};

match self.val {
Expand Down
8 changes: 3 additions & 5 deletions src/librustc_codegen_llvm/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,9 @@ pub fn codegen_static_initializer(
cx: &CodegenCx<'ll, 'tcx>,
def_id: DefId,
) -> Result<(&'ll Value, &'tcx Allocation), ErrorHandled> {
let static_ = cx.tcx.const_eval_poly(def_id)?;

let alloc = match static_.val {
ty::ConstKind::Value(ConstValue::ByRef { alloc, offset }) if offset.bytes() == 0 => alloc,
_ => bug!("static const eval returned {:#?}", static_),
let alloc = match cx.tcx.const_eval_poly(def_id)? {
ConstValue::ByRef { alloc, offset } if offset.bytes() == 0 => alloc,
val => bug!("static const eval returned {:#?}", val),
};
Ok((const_alloc_to_llvm(cx, alloc), alloc))
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_codegen_llvm/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
.tcx
.const_eval_instance(ty::ParamEnv::reveal_all(), instance, None)
.unwrap();
OperandRef::from_const(self, ty_name).immediate_or_packed_pair(self)
OperandRef::from_const(self, ty_name, ret_ty).immediate_or_packed_pair(self)
}
"init" => {
let ty = substs.type_at(0);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_codegen_ssa/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -991,7 +991,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
caller.line as u32,
caller.col_display as u32 + 1,
));
OperandRef::from_const(bx, const_loc)
OperandRef::from_const(bx, const_loc, bx.tcx().caller_location_ty())
})
}

Expand Down
30 changes: 20 additions & 10 deletions src/librustc_codegen_ssa/mir/constant.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::mir::operand::OperandRef;
use crate::traits::*;
use rustc::mir;
use rustc::mir::interpret::ErrorHandled;
use rustc::mir::interpret::{ConstValue, ErrorHandled};
use rustc::ty::layout::{self, HasTyCtxt};
use rustc::ty::{self, Ty};
use rustc_index::vec::Idx;
Expand Down Expand Up @@ -30,15 +30,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
_ => {
let val = self.eval_mir_constant(constant)?;
Ok(OperandRef::from_const(bx, val))
let ty = self.monomorphize(&constant.literal.ty);
Ok(OperandRef::from_const(bx, val.clone(), ty))
}
}
}

pub fn eval_mir_constant(
&mut self,
constant: &mir::Constant<'tcx>,
) -> Result<&'tcx ty::Const<'tcx>, ErrorHandled> {
) -> Result<ConstValue<'tcx>, ErrorHandled> {
match constant.literal.val {
ty::ConstKind::Unevaluated(def_id, substs, promoted) => {
let substs = self.monomorphize(&substs);
Expand All @@ -55,7 +56,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
err
})
}
_ => Ok(self.monomorphize(&constant.literal)),
ty::ConstKind::Value(value) => Ok(value),
_ => {
let const_ = self.monomorphize(&constant.literal);
if let ty::ConstKind::Value(value) = const_.val {
Ok(value)
} else {
span_bug!(constant.span, "encountered bad ConstKind in codegen: {:?}", const_);
}
}
}
}

Expand All @@ -65,21 +74,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
bx: &Bx,
span: Span,
ty: Ty<'tcx>,
constant: Result<&'tcx ty::Const<'tcx>, ErrorHandled>,
constant: Result<ConstValue<'tcx>, ErrorHandled>,
) -> (Bx::Value, Ty<'tcx>) {
constant
.map(|c| {
let field_ty = c.ty.builtin_index().unwrap();
let fields = match c.ty.kind {
.map(|val| {
let field_ty = ty.builtin_index().unwrap();
let fields = match ty.kind {
ty::Array(_, n) => n.eval_usize(bx.tcx(), ty::ParamEnv::reveal_all()),
_ => bug!("invalid simd shuffle type: {}", c.ty),
_ => bug!("invalid simd shuffle type: {}", ty),
};
let c = ty::Const::from_value(bx.tcx(), val, ty);
let values: Vec<_> = (0..fields)
.map(|field| {
let field = bx.tcx().const_field(
ty::ParamEnv::reveal_all().and((&c, mir::Field::new(field as usize))),
);
if let Some(prim) = field.val.try_to_scalar() {
if let Some(prim) = field.try_to_scalar() {
let layout = bx.layout_of(field_ty);
let scalar = match layout.abi {
layout::Abi::Scalar(ref x) => x,
Expand Down
14 changes: 5 additions & 9 deletions src/librustc_codegen_ssa/mir/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use crate::MemFlags;

use rustc::mir;
use rustc::mir::interpret::{ConstValue, ErrorHandled, Pointer, Scalar};
use rustc::ty;
use rustc::ty::layout::{self, Align, LayoutOf, Size, TyLayout};
use rustc::ty::Ty;

use std::fmt;

Expand Down Expand Up @@ -66,20 +66,16 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {

pub fn from_const<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
bx: &mut Bx,
val: &'tcx ty::Const<'tcx>,
val: ConstValue<'tcx>,
ty: Ty<'tcx>,
) -> Self {
let layout = bx.layout_of(val.ty);
let layout = bx.layout_of(ty);

if layout.is_zst() {
return OperandRef::new_zst(bx, layout);
}

let val_val = match val.val {
ty::ConstKind::Value(val_val) => val_val,
_ => bug!("encountered bad ConstKind in codegen"),
};

let val = match val_val {
let val = match val {
ConstValue::Scalar(x) => {
let scalar = match layout.abi {
layout::Abi::Scalar(ref x) => x,
Expand Down
15 changes: 5 additions & 10 deletions src/librustc_mir/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub(crate) fn const_field<'tcx>(
variant: Option<VariantIdx>,
field: mir::Field,
value: &'tcx ty::Const<'tcx>,
) -> &'tcx ty::Const<'tcx> {
) -> ConstValue<'tcx> {
trace!("const_field: {:?}, {:?}", field, value);
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
// get the operand again
Expand All @@ -46,19 +46,13 @@ pub(crate) fn const_field<'tcx>(
pub(crate) fn const_caller_location<'tcx>(
tcx: TyCtxt<'tcx>,
(file, line, col): (Symbol, u32, u32),
) -> &'tcx ty::Const<'tcx> {
) -> ConstValue<'tcx> {
trace!("const_caller_location: {}:{}:{}", file, line, col);
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false);

let loc_ty = tcx.caller_location_ty();
let loc_place = ecx.alloc_caller_location(file, line, col);
intern_const_alloc_recursive(&mut ecx, InternKind::Constant, loc_place, false).unwrap();
let loc_const = ty::Const {
ty: loc_ty,
val: ty::ConstKind::Value(ConstValue::Scalar(loc_place.ptr.into())),
};

tcx.mk_const(loc_const)
ConstValue::Scalar(loc_place.ptr.into())
}

// this function uses `unwrap` copiously, because an already validated constant
Expand All @@ -84,7 +78,8 @@ pub(crate) fn destructure_const<'tcx>(
let down = ecx.operand_downcast(op, variant).unwrap();
let fields_iter = (0..field_count).map(|i| {
let field_op = ecx.operand_field(down, i).unwrap();
op_to_const(&ecx, field_op)
let val = op_to_const(&ecx, field_op);
ty::Const::from_value(tcx, val, field_op.layout.ty)
});
let fields = tcx.arena.alloc_from_iter(fields_iter);

Expand Down
18 changes: 7 additions & 11 deletions src/librustc_mir/const_eval/eval_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>(
pub(super) fn op_to_const<'tcx>(
ecx: &CompileTimeEvalContext<'_, 'tcx>,
op: OpTy<'tcx>,
) -> &'tcx ty::Const<'tcx> {
) -> ConstValue<'tcx> {
// We do not have value optimizations for everything.
// Only scalars and slices, since they are very common.
// Note that further down we turn scalars of undefined bits back to `ByRef`. These can result
Expand Down Expand Up @@ -144,7 +144,7 @@ pub(super) fn op_to_const<'tcx>(
ConstValue::Scalar(Scalar::zst())
}
};
let val = match immediate {
match immediate {
Ok(mplace) => to_const_value(mplace),
// see comment on `let try_as_immediate` above
Err(ImmTy { imm: Immediate::Scalar(x), .. }) => match x {
Expand All @@ -166,8 +166,7 @@ pub(super) fn op_to_const<'tcx>(
let len: usize = len.try_into().unwrap();
ConstValue::Slice { data, start, end: start + len }
}
};
ecx.tcx.mk_const(ty::Const { val: ty::ConstKind::Value(val), ty: op.layout.ty })
}
}

fn validate_and_turn_into_const<'tcx>(
Expand Down Expand Up @@ -195,13 +194,10 @@ fn validate_and_turn_into_const<'tcx>(
// whether they become immediates.
if is_static || cid.promoted.is_some() {
let ptr = mplace.ptr.assert_ptr();
Ok(tcx.mk_const(ty::Const {
val: ty::ConstKind::Value(ConstValue::ByRef {
alloc: ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id),
offset: ptr.offset,
}),
ty: mplace.layout.ty,
}))
Ok(ConstValue::ByRef {
alloc: ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id),
offset: ptr.offset,
})
} else {
Ok(op_to_const(&ecx, mplace.into()))
}
Expand Down
4 changes: 3 additions & 1 deletion src/librustc_mir/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
pub(super) fn const_eval(
&self,
gid: GlobalId<'tcx>,
ty: Ty<'tcx>,
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
// For statics we pick `ParamEnv::reveal_all`, because statics don't have generics
// and thus don't care about the parameter environment. While we could just use
Expand All @@ -777,7 +778,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// recursion deeper than one level, because the `tcx.const_eval` above is guaranteed to not
// return `ConstValue::Unevaluated`, which is the only way that `eval_const_to_op` will call
// `ecx.const_eval`.
self.eval_const_to_op(val, None)
let const_ = ty::Const { val: ty::ConstKind::Value(val), ty };
self.eval_const_to_op(&const_, None)
}

pub fn const_eval_raw(
Expand Down
Loading

0 comments on commit 391e7e2

Please sign in to comment.