Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 5 pull requests #69262

Merged
merged 21 commits into from
Feb 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
c423a86
Change const eval to return `ConstValue`, instead of `Const` as the t…
skinnyBat Feb 14, 2020
c7aadcf
Change `const_field` and `const_caller_location` to return `ConstValu…
skinnyBat Feb 14, 2020
99a864b
Fix emulate intrinsics return type.
skinnyBat Feb 15, 2020
821f4a9
Monomorphize const type during codegen.
skinnyBat Feb 15, 2020
6351bfd
Add test for issue-39618
JohnTitor Feb 15, 2020
f32447d
Add test for issue-51798
JohnTitor Feb 15, 2020
ecb8bf0
Add test for issue-62894
JohnTitor Feb 15, 2020
426dcf0
Add test for issue-63952
JohnTitor Feb 15, 2020
9478503
Add test for issue-68653
JohnTitor Feb 15, 2020
2f39ec2
Add FIXME note
JohnTitor Feb 15, 2020
774a029
Code review changes.
skinnyBat Feb 15, 2020
8904bdd
Determine type of intrinsics instead of assuming the destination type…
skinnyBat Feb 15, 2020
759526e
Fix printing of `Yield` terminator
jonas-schievink Feb 15, 2020
bb482eb
suspend -> yield
jonas-schievink Feb 16, 2020
d1a7ae7
Allow whitespaces in revision flags
JohnTitor Feb 16, 2020
73283f1
Clean up E0310 explanation
GuillaumeGomez Feb 17, 2020
391e7e2
Rollup merge of #69181 - skinny121:const-eval-return, r=oli-obk
Dylan-DPC Feb 18, 2020
d1f175b
Rollup merge of #69192 - JohnTitor:add-tests, r=Centril
Dylan-DPC Feb 18, 2020
8b93e67
Rollup merge of #69200 - jonas-schievink:yield-print, r=eddyb,Zoxc
Dylan-DPC Feb 18, 2020
bea18c7
Rollup merge of #69205 - JohnTitor:allow-whitespaces, r=Mark-Simulacrum
Dylan-DPC Feb 18, 2020
210b181
Rollup merge of #69233 - GuillaumeGomez:cleanup-e0310, r=Dylan-DPC
Dylan-DPC Feb 18, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
16 changes: 8 additions & 8 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1468,21 +1468,21 @@ impl<'tcx> TerminatorKind<'tcx> {
/// successors, which may be rendered differently between the text and the graphviz format.
pub fn fmt_head<W: Write>(&self, fmt: &mut W) -> fmt::Result {
use self::TerminatorKind::*;
match *self {
match self {
Goto { .. } => write!(fmt, "goto"),
SwitchInt { discr: ref place, .. } => write!(fmt, "switchInt({:?})", place),
SwitchInt { discr, .. } => write!(fmt, "switchInt({:?})", discr),
Return => write!(fmt, "return"),
GeneratorDrop => write!(fmt, "generator_drop"),
Resume => write!(fmt, "resume"),
Abort => write!(fmt, "abort"),
Yield { ref value, .. } => write!(fmt, "_1 = suspend({:?})", value),
Yield { value, resume_arg, .. } => write!(fmt, "{:?} = yield({:?})", resume_arg, value),
Unreachable => write!(fmt, "unreachable"),
Drop { ref location, .. } => write!(fmt, "drop({:?})", location),
DropAndReplace { ref location, ref value, .. } => {
Drop { location, .. } => write!(fmt, "drop({:?})", location),
DropAndReplace { location, value, .. } => {
write!(fmt, "replace({:?} <- {:?})", location, value)
}
Call { ref func, ref args, ref destination, .. } => {
if let Some((ref destination, _)) = *destination {
Call { func, args, destination, .. } => {
if let Some((destination, _)) = destination {
write!(fmt, "{:?} = ", destination)?;
}
write!(fmt, "{:?}(", func)?;
Expand All @@ -1494,7 +1494,7 @@ impl<'tcx> TerminatorKind<'tcx> {
}
write!(fmt, ")")
}
Assert { ref cond, expected, ref msg, .. } => {
Assert { cond, expected, msg, .. } => {
write!(fmt, "assert(")?;
if !expected {
write!(fmt, "!")?;
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
13 changes: 9 additions & 4 deletions src/librustc_error_codes/error_codes/E0310.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Types in type definitions have lifetimes associated with them that represent
how long the data stored within them is guaranteed to be live. This lifetime
must be as long as the data needs to be alive, and missing the constraint that
denotes this will cause this error.
A parameter type is missing a lifetime constraint or has a lifetime that
does not live long enough.

Erroneous code example:

```compile_fail,E0310
// This won't compile because T is not constrained to the static lifetime
Expand All @@ -11,6 +11,11 @@ struct Foo<T> {
}
```

Type parameters in type definitions have lifetimes associated with them that
represent how long the data stored within them is guaranteed to live. This
lifetime must be as long as the data needs to be alive, and missing the
constraint that denotes this will cause this error.

This will compile, because it has the constraint on the type parameter:

```
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
Loading