Skip to content

Rollup of 5 pull requests #63174

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

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
6bd7e16
cast: no need to catch errors any more, force_bits should succeed
RalfJung Jul 24, 2019
305eadb
operator: implement binary_op strictly by first checking the type, th…
RalfJung Jul 24, 2019
6946b14
turn cast_immediate into its own function
RalfJung Jul 24, 2019
f92c3a3
refactor cast_immediate to dispatch on the type first, and on the val…
RalfJung Jul 24, 2019
8debe64
use From to convert scalars to immediates
RalfJung Jul 24, 2019
8713a7b
fix casts from fat pointers
RalfJung Jul 24, 2019
8890624
improve error when CTFE does ptr-int-cast; update tests
RalfJung Jul 24, 2019
3cd4079
get rid of some remaining type-based dispatching in cast code
RalfJung Jul 24, 2019
2bebfd3
add is_any_ptr type test; this also helps pacify tidy
RalfJung Jul 24, 2019
1f57eb0
trailing full stops
RalfJung Jul 25, 2019
0ba2e80
bless all the things
RalfJung Jul 25, 2019
d7b9bbf
const_prop no longer does ptr-to-int casts
RalfJung Jul 25, 2019
08a8de8
Add keywords item into the sidebar
GuillaumeGomez Jul 25, 2019
f3a3290
Account for maybe_whole_expr in range patterns.
Centril Jul 30, 2019
87e73c1
Remove redundant method with const variable resolution
varkor Jul 31, 2019
3f461f5
cleanup StringReader fields
matklad Jul 31, 2019
6551285
Address review comments.
Centril Jul 31, 2019
b26cd8c
Rollup merge of #62946 - RalfJung:miri_type_dispatch_first, r=oli-obk
Centril Jul 31, 2019
067d891
Rollup merge of #62971 - GuillaumeGomez:keyword-sidebar, r=nobody
Centril Jul 31, 2019
724146e
Rollup merge of #63122 - Centril:fix-63115, r=petrochenkov
Centril Jul 31, 2019
a2574cf
Rollup merge of #63153 - varkor:remove-resolve_const_var, r=cramertj
Centril Jul 31, 2019
dff0ba1
Rollup merge of #63170 - matklad:cleanup-fields, r=petrochenkov
Centril Jul 31, 2019
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
2 changes: 1 addition & 1 deletion src/librustc/infer/canonical/canonicalizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
const_var: &'tcx ty::Const<'tcx>
) -> &'tcx ty::Const<'tcx> {
let infcx = self.infcx.expect("encountered const-var without infcx");
let bound_to = infcx.resolve_const_var(const_var);
let bound_to = infcx.shallow_resolve(const_var);
if bound_to != const_var {
self.fold_const(bound_to)
} else {
Expand Down
27 changes: 4 additions & 23 deletions src/librustc/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1351,23 +1351,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
}

pub fn resolve_const_var(
&self,
ct: &'tcx ty::Const<'tcx>
) -> &'tcx ty::Const<'tcx> {
if let ty::Const { val: ConstValue::Infer(InferConst::Var(v)), .. } = ct {
self.const_unification_table
.borrow_mut()
.probe_value(*v)
.val
.known()
.map(|c| self.resolve_const_var(c))
.unwrap_or(ct)
} else {
ct
}
}

pub fn fully_resolve<T: TypeFoldable<'tcx>>(&self, value: &T) -> FixupResult<'tcx, T> {
/*!
* Attempts to resolve all type/region/const variables in
Expand Down Expand Up @@ -1586,7 +1569,7 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
// it can be resolved to an int/float variable, which
// can then be recursively resolved, hence the
// recursion. Note though that we prevent type
// variables from unifyxing to other type variables
// variables from unifying to other type variables
// directly (though they may be embedded
// structurally), and we prevent cycles in any case,
// so this recursion should always be of very limited
Expand Down Expand Up @@ -1626,17 +1609,15 @@ impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
}

fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
match ct {
ty::Const { val: ConstValue::Infer(InferConst::Var(vid)), .. } => {
if let ty::Const { val: ConstValue::Infer(InferConst::Var(vid)), .. } = ct {
self.infcx.const_unification_table
.borrow_mut()
.probe_value(*vid)
.val
.known()
.map(|c| self.fold_const(c))
.unwrap_or(ct)
}
_ => ct,
} else {
ct
}
}
}
Expand Down
12 changes: 5 additions & 7 deletions src/librustc/ty/relate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -594,13 +594,11 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
ty: a.ty,
}))
}
(ConstValue::ByRef { .. }, _) => {
bug!(
"non-Scalar ConstValue encountered in super_relate_consts {:?} {:?}",
a,
b,
);
}

// FIXME(const_generics): we should either handle `Scalar::Ptr` or add a comment
// saying that we're not handling it intentionally.

// FIXME(const_generics): handle `ConstValue::ByRef` and `ConstValue::Slice`.

// FIXME(const_generics): this is wrong, as it is a projection
(ConstValue::Unevaluated(a_def_id, a_substs),
Expand Down
6 changes: 6 additions & 0 deletions src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1863,6 +1863,12 @@ impl<'tcx> TyS<'tcx> {
}
}

/// Tests if this is any kind of primitive pointer type (reference, raw pointer, fn pointer).
#[inline]
pub fn is_any_ptr(&self) -> bool {
self.is_region_ptr() || self.is_unsafe_ptr() || self.is_fn_ptr()
}

/// Returns `true` if this type is an `Arc<T>`.
#[inline]
pub fn is_arc(&self) -> bool {
Expand Down
15 changes: 12 additions & 3 deletions src/librustc_mir/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ use rustc_data_structures::fx::FxHashMap;
use syntax::source_map::{Span, DUMMY_SP};

use crate::interpret::{self,
PlaceTy, MPlaceTy, OpTy, ImmTy, Immediate, Scalar,
PlaceTy, MPlaceTy, OpTy, ImmTy, Immediate, Scalar, Pointer,
RawConst, ConstValue,
InterpResult, InterpErrorInfo, InterpError, GlobalId, InterpCx, StackPopCleanup,
Allocation, AllocId, MemoryKind,
Allocation, AllocId, MemoryKind, Memory,
snapshot, RefTracking, intern_const_alloc_recursive,
};

Expand Down Expand Up @@ -397,7 +397,16 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
)
}

fn ptr_op(
fn ptr_to_int(
_mem: &Memory<'mir, 'tcx, Self>,
_ptr: Pointer,
) -> InterpResult<'tcx, u64> {
Err(
ConstEvalError::NeedsRfc("pointer-to-integer cast".to_string()).into(),
)
}

fn binary_ptr_op(
_ecx: &InterpCx<'mir, 'tcx, Self>,
_bin_op: mir::BinOp,
_left: ImmTy<'tcx>,
Expand Down
156 changes: 65 additions & 91 deletions src/librustc_mir/interpret/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,13 @@ use syntax::symbol::sym;
use rustc_apfloat::ieee::{Single, Double};
use rustc_apfloat::{Float, FloatConvert};
use rustc::mir::interpret::{
Scalar, InterpResult, Pointer, PointerArithmetic, InterpError,
Scalar, InterpResult, PointerArithmetic, InterpError,
};
use rustc::mir::CastKind;

use super::{InterpCx, Machine, PlaceTy, OpTy, Immediate, FnVal};
use super::{InterpCx, Machine, PlaceTy, OpTy, ImmTy, Immediate, FnVal};

impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool {
match ty.sty {
ty::RawPtr(ty::TypeAndMut { ty, .. }) |
ty::Ref(_, ty, _) => !self.type_is_sized(ty),
ty::Adt(def, _) if def.is_box() => !self.type_is_sized(ty.boxed_ty()),
_ => false,
}
}

pub fn cast(
&mut self,
src: OpTy<'tcx, M::PointerTag>,
Expand All @@ -37,40 +28,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {

Misc | Pointer(PointerCast::MutToConstPointer) => {
let src = self.read_immediate(src)?;

if self.type_is_fat_ptr(src.layout.ty) {
match (*src, self.type_is_fat_ptr(dest.layout.ty)) {
// pointers to extern types
(Immediate::Scalar(_),_) |
// slices and trait objects to other slices/trait objects
(Immediate::ScalarPair(..), true) => {
// No change to immediate
self.write_immediate(*src, dest)?;
}
// slices and trait objects to thin pointers (dropping the metadata)
(Immediate::ScalarPair(data, _), false) => {
self.write_scalar(data, dest)?;
}
}
} else {
match src.layout.variants {
layout::Variants::Single { index } => {
if let Some(discr) =
src.layout.ty.discriminant_for_variant(*self.tcx, index)
{
// Cast from a univariant enum
assert!(src.layout.is_zst());
return self.write_scalar(
Scalar::from_uint(discr.val, dest.layout.size),
dest);
}
}
layout::Variants::Multiple { .. } => {},
}

let dest_val = self.cast_scalar(src.to_scalar()?, src.layout, dest.layout)?;
self.write_scalar(dest_val, dest)?;
}
let res = self.cast_immediate(src, dest.layout)?;
self.write_immediate(res, dest)?;
}

Pointer(PointerCast::ReifyFnPointer) => {
Expand Down Expand Up @@ -126,36 +85,76 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Ok(())
}

fn cast_scalar(
fn cast_immediate(
&self,
val: Scalar<M::PointerTag>,
src_layout: TyLayout<'tcx>,
src: ImmTy<'tcx, M::PointerTag>,
dest_layout: TyLayout<'tcx>,
) -> InterpResult<'tcx, Scalar<M::PointerTag>> {
) -> InterpResult<'tcx, Immediate<M::PointerTag>> {
use rustc::ty::TyKind::*;
trace!("Casting {:?}: {:?} to {:?}", val, src_layout.ty, dest_layout.ty);
trace!("Casting {:?}: {:?} to {:?}", *src, src.layout.ty, dest_layout.ty);

match src_layout.ty.sty {
match src.layout.ty.sty {
// Floating point
Float(FloatTy::F32) => self.cast_from_float(val.to_f32()?, dest_layout.ty),
Float(FloatTy::F64) => self.cast_from_float(val.to_f64()?, dest_layout.ty),
// Integer(-like), including fn ptr casts and casts from enums that
// are represented as integers (this excludes univariant enums, which
// are handled in `cast` directly).
_ => {
Float(FloatTy::F32) =>
return Ok(self.cast_from_float(src.to_scalar()?.to_f32()?, dest_layout.ty)?.into()),
Float(FloatTy::F64) =>
return Ok(self.cast_from_float(src.to_scalar()?.to_f64()?, dest_layout.ty)?.into()),
// The rest is integer/pointer-"like", including fn ptr casts and casts from enums that
// are represented as integers.
_ =>
assert!(
src_layout.ty.is_bool() || src_layout.ty.is_char() ||
src_layout.ty.is_enum() || src_layout.ty.is_integral() ||
src_layout.ty.is_unsafe_ptr() || src_layout.ty.is_fn_ptr() ||
src_layout.ty.is_region_ptr(),
"Unexpected cast from type {:?}", src_layout.ty
);
match val.to_bits_or_ptr(src_layout.size, self) {
Err(ptr) => self.cast_from_ptr(ptr, src_layout, dest_layout),
Ok(data) => self.cast_from_int(data, src_layout, dest_layout),
src.layout.ty.is_bool() || src.layout.ty.is_char() ||
src.layout.ty.is_enum() || src.layout.ty.is_integral() ||
src.layout.ty.is_any_ptr(),
"Unexpected cast from type {:?}", src.layout.ty
)
}

// Handle cast from a univariant (ZST) enum.
match src.layout.variants {
layout::Variants::Single { index } => {
if let Some(discr) =
src.layout.ty.discriminant_for_variant(*self.tcx, index)
{
assert!(src.layout.is_zst());
return Ok(Scalar::from_uint(discr.val, dest_layout.size).into());
}
}
layout::Variants::Multiple { .. } => {},
}

// Handle casting the metadata away from a fat pointer.
if src.layout.ty.is_unsafe_ptr() && dest_layout.ty.is_unsafe_ptr() &&
dest_layout.size != src.layout.size
{
assert_eq!(src.layout.size, 2*self.memory.pointer_size());
assert_eq!(dest_layout.size, self.memory.pointer_size());
assert!(dest_layout.ty.is_unsafe_ptr());
match *src {
Immediate::ScalarPair(data, _) =>
return Ok(data.into()),
Immediate::Scalar(..) =>
bug!(
"{:?} input to a fat-to-thin cast ({:?} -> {:?})",
*src, src.layout.ty, dest_layout.ty
),
};
}

// Handle casting any ptr to raw ptr (might be a fat ptr).
if src.layout.ty.is_any_ptr() && dest_layout.ty.is_unsafe_ptr()
{
// The only possible size-unequal case was handled above.
assert_eq!(src.layout.size, dest_layout.size);
return Ok(*src);
}

// For all remaining casts, we either
// (a) cast a raw ptr to usize, or
// (b) cast from an integer-like (including bool, char, enums).
// In both cases we want the bits.
let bits = self.force_bits(src.to_scalar()?, src.layout.size)?;
Ok(self.cast_from_int(bits, src.layout, dest_layout)?.into())
}

fn cast_from_int(
Expand Down Expand Up @@ -236,31 +235,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
}

fn cast_from_ptr(
&self,
ptr: Pointer<M::PointerTag>,
src_layout: TyLayout<'tcx>,
dest_layout: TyLayout<'tcx>,
) -> InterpResult<'tcx, Scalar<M::PointerTag>> {
use rustc::ty::TyKind::*;

match dest_layout.ty.sty {
// Casting to a reference or fn pointer is not permitted by rustc,
// no need to support it here.
RawPtr(_) => Ok(ptr.into()),
Int(_) | Uint(_) => {
let size = self.memory.pointer_size();

match self.force_bits(Scalar::Ptr(ptr), size) {
Ok(bits) => self.cast_from_int(bits, src_layout, dest_layout),
Err(_) if dest_layout.size == size => Ok(ptr.into()),
Err(e) => Err(e),
}
}
_ => bug!("invalid MIR: ptr to {:?} cast", dest_layout.ty)
}
}

fn unsize_into_ptr(
&mut self,
src: OpTy<'tcx, M::PointerTag>,
Expand Down
11 changes: 3 additions & 8 deletions src/librustc_mir/interpret/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,10 @@ pub trait Machine<'mir, 'tcx>: Sized {
def_id: DefId,
) -> InterpResult<'tcx, Cow<'tcx, Allocation>>;

/// Called for all binary operations on integer(-like) types when one operand is a pointer
/// value, and for the `Offset` operation that is inherently about pointers.
/// Called for all binary operations where the LHS has pointer type.
///
/// Returns a (value, overflowed) pair if the operation succeeded
fn ptr_op(
fn binary_ptr_op(
ecx: &InterpCx<'mir, 'tcx, Self>,
bin_op: mir::BinOp,
left: ImmTy<'tcx, Self::PointerTag>,
Expand Down Expand Up @@ -234,7 +233,6 @@ pub trait Machine<'mir, 'tcx>: Sized {
extra: Self::FrameExtra,
) -> InterpResult<'tcx>;

#[inline(always)]
fn int_to_ptr(
_mem: &Memory<'mir, 'tcx, Self>,
int: u64,
Expand All @@ -246,11 +244,8 @@ pub trait Machine<'mir, 'tcx>: Sized {
}).into())
}

#[inline(always)]
fn ptr_to_int(
_mem: &Memory<'mir, 'tcx, Self>,
_ptr: Pointer<Self::PointerTag>,
) -> InterpResult<'tcx, u64> {
err!(ReadPointerAsBytes)
}
) -> InterpResult<'tcx, u64>;
}
Loading