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

rustup to rustc 1.17.0-nightly (60a0edc6c 2017-02-26) #147

Merged
merged 8 commits into from
Mar 14, 2017
9 changes: 4 additions & 5 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
use std::error::Error;
use std::fmt;
use rustc::mir;
use rustc::ty::{BareFnTy, Ty, FnSig, layout};
use syntax::abi::Abi;
use rustc::ty::{FnSig, Ty, layout};
use memory::{Pointer, Function};
use rustc_const_math::ConstMathErr;
use syntax::codemap::Span;

#[derive(Clone, Debug)]
pub enum EvalError<'tcx> {
FunctionPointerTyMismatch(Abi, &'tcx FnSig<'tcx>, &'tcx BareFnTy<'tcx>),
FunctionPointerTyMismatch(FnSig<'tcx>, FnSig<'tcx>),
NoMirFor(String),
UnterminatedCString(Pointer),
DanglingPointerDeref,
@@ -151,8 +150,8 @@ impl<'tcx> fmt::Display for EvalError<'tcx> {
ptr.offset, ptr.offset + size, ptr.alloc_id, allocation_size)
},
EvalError::NoMirFor(ref func) => write!(f, "no mir for `{}`", func),
EvalError::FunctionPointerTyMismatch(abi, sig, got) =>
write!(f, "tried to call a function with abi {:?} and sig {:?} through a function pointer of type {:?}", abi, sig, got),
EvalError::FunctionPointerTyMismatch(sig, got) =>
write!(f, "tried to call a function with sig {} through a function pointer of type {}", sig, got),
EvalError::ArrayIndexOutOfBounds(span, len, index) =>
write!(f, "index out of bounds: the len is {} but the index is {} at {:?}", len, index, span),
EvalError::Math(span, ref err) =>
47 changes: 31 additions & 16 deletions src/eval_context.rs
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ use rustc::mir;
use rustc::traits::Reveal;
use rustc::ty::layout::{self, Layout, Size};
use rustc::ty::subst::{self, Subst, Substs};
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, Binder};
use rustc_data_structures::indexed_vec::Idx;
use syntax::codemap::{self, DUMMY_SP};

@@ -181,8 +181,6 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {

Float(ConstFloat::F32(f)) => PrimVal::from_f32(f),
Float(ConstFloat::F64(f)) => PrimVal::from_f64(f),
Float(ConstFloat::FInfer { .. }) =>
bug!("uninferred constants only exist before typeck"),

Bool(b) => PrimVal::from_bool(b),
Char(c) => PrimVal::from_char(c),
@@ -196,7 +194,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {

Struct(_) => unimplemented!(),
Tuple(_) => unimplemented!(),
Function(_) => unimplemented!(),
Function(_, _) => unimplemented!(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tempted to make this the way to refer to a TyFnDef (now that it has Substs), what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's unreachable ^^ At least in the run-pass tests that we run. We only use this function in mir::Literal::Value, and I think that can only contain primitives

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I know, it's because we use Item right now, and work around the awkwardness of it everywhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh... you mean changing it that Literal::Item stops referring to functions. Sounds good.

Array(_) => unimplemented!(),
Repeat(_, _) => unimplemented!(),
};
@@ -227,6 +225,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
self.tcx.normalize_associated_type(&substituted)
}

pub fn erase_lifetimes<T>(&self, value: &Binder<T>) -> T
where T : TypeFoldable<'tcx>
{
let value = self.tcx.erase_late_bound_regions(value);
self.tcx.erase_regions(&value)
}

pub(super) fn type_size(&self, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<u64>> {
self.type_size_with_substs(ty, self.substs())
}
@@ -457,7 +462,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {

General { discr, ref variants, .. } => {
if let mir::AggregateKind::Adt(adt_def, variant, _, _) = *kind {
let discr_val = adt_def.variants[variant].disr_val;
let discr_val = adt_def.discriminants(self.tcx)
.nth(variant)
.expect("broken mir: Adt variant id invalid")
.to_u128_unchecked();
let discr_size = discr.size().bytes();
if variants[variant].packed {
let ptr = self.force_allocation(dest)?.to_ptr_and_extra().0;
@@ -530,7 +538,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
CEnum { .. } => {
assert_eq!(operands.len(), 0);
if let mir::AggregateKind::Adt(adt_def, variant, _, _) = *kind {
let n = adt_def.variants[variant].disr_val;
let n = adt_def.discriminants(self.tcx)
.nth(variant)
.expect("broken mir: Adt variant index invalid")
.to_u128_unchecked();
self.write_primval(dest, PrimVal::Bytes(n), dest_ty)?;
} else {
bug!("tried to assign {:?} to Layout::CEnum", kind);
@@ -640,25 +651,29 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
}

ReifyFnPointer => match self.operand_ty(operand).sty {
ty::TyFnDef(def_id, substs, fn_ty) => {
let fn_ty = self.tcx.erase_regions(&fn_ty);
let fn_ptr = self.memory.create_fn_ptr(self.tcx,def_id, substs, fn_ty);
ty::TyFnDef(def_id, substs, sig) => {
let fn_ptr = self.memory.create_fn_ptr(def_id, substs, sig);
self.write_value(Value::ByVal(PrimVal::Ptr(fn_ptr)), dest, dest_ty)?;
},
ref other => bug!("reify fn pointer on {:?}", other),
},

UnsafeFnPointer => match dest_ty.sty {
ty::TyFnPtr(unsafe_fn_ty) => {
ty::TyFnPtr(_) => {
let src = self.eval_operand(operand)?;
let ptr = src.read_ptr(&self.memory)?;
let fn_def = self.memory.get_fn(ptr.alloc_id)?.expect_concrete()?;
let unsafe_fn_ty = self.tcx.erase_regions(&unsafe_fn_ty);
let fn_ptr = self.memory.create_fn_ptr(self.tcx, fn_def.def_id, fn_def.substs, unsafe_fn_ty);
self.write_value(Value::ByVal(PrimVal::Ptr(fn_ptr)), dest, dest_ty)?;
self.write_value(src, dest, dest_ty)?;
},
ref other => bug!("fn to unsafe fn cast on {:?}", other),
},

ClosureFnPointer => match self.operand_ty(operand).sty {
ty::TyClosure(def_id, substs) => {
let fn_ty = self.tcx.closure_type(def_id);
let fn_ptr = self.memory.create_fn_ptr_from_noncapture_closure(def_id, substs, fn_ty);
self.write_value(Value::ByVal(PrimVal::Ptr(fn_ptr)), dest, dest_ty)?;
},
ref other => bug!("reify fn pointer on {:?}", other),
},
}
}

@@ -668,7 +683,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
let ptr = self.force_allocation(lval)?.to_ptr();
let discr_val = self.read_discriminant_value(ptr, ty)?;
if let ty::TyAdt(adt_def, _) = ty.sty {
if adt_def.variants.iter().all(|v| discr_val != v.disr_val) {
if adt_def.discriminants(self.tcx).all(|v| discr_val != v.to_u128_unchecked()) {
return Err(EvalError::InvalidDiscriminant);
}
} else {
4 changes: 2 additions & 2 deletions src/lvalue.rs
Original file line number Diff line number Diff line change
@@ -137,9 +137,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
Local(mir::RETURN_POINTER) => self.frame().return_lvalue,
Local(local) => Lvalue::Local { frame: self.stack.len() - 1, local, field: None },

Static(def_id) => {
Static(ref static_) => {
let substs = self.tcx.intern_substs(&[]);
Lvalue::Global(GlobalId { def_id, substs, promoted: None })
Lvalue::Global(GlobalId { def_id: static_.def_id, substs, promoted: None })
}

Projection(ref proj) => return self.eval_lvalue_projection(proj),
67 changes: 26 additions & 41 deletions src/memory.rs
Original file line number Diff line number Diff line change
@@ -3,12 +3,10 @@ use std::collections::{btree_map, BTreeMap, HashMap, HashSet, VecDeque, BTreeSet
use std::{fmt, iter, ptr, mem, io};

use rustc::hir::def_id::DefId;
use rustc::ty::{self, BareFnTy, ClosureTy, ClosureSubsts, TyCtxt};
use rustc::ty::{self, PolyFnSig, ClosureSubsts};
use rustc::ty::subst::Substs;
use rustc::ty::layout::{self, TargetDataLayout};

use syntax::abi::Abi;

use error::{EvalError, EvalResult};
use value::PrimVal;

@@ -109,8 +107,7 @@ impl Pointer {
pub struct FunctionDefinition<'tcx> {
pub def_id: DefId,
pub substs: &'tcx Substs<'tcx>,
pub abi: Abi,
pub sig: &'tcx ty::FnSig<'tcx>,
pub sig: PolyFnSig<'tcx>,
}

/// Either a concrete function, or a glue function
@@ -127,18 +124,14 @@ pub enum Function<'tcx> {
DropGlue(ty::Ty<'tcx>),
/// Glue required to treat the ptr part of a fat pointer
/// as a function pointer
FnPtrAsTraitObject(&'tcx ty::FnSig<'tcx>),
FnPtrAsTraitObject(PolyFnSig<'tcx>),
/// Glue for Closures
Closure(FunctionDefinition<'tcx>),
/// Glue for noncapturing closures casted to function pointers
NonCaptureClosureAsFnPtr(FunctionDefinition<'tcx>),
}

impl<'tcx> Function<'tcx> {
pub fn expect_concrete(self) -> EvalResult<'tcx, FunctionDefinition<'tcx>> {
match self {
Function::Concrete(fn_def) => Ok(fn_def),
other => Err(EvalError::ExpectedConcreteFunction(other)),
}
}
pub fn expect_drop_glue_real_ty(self) -> EvalResult<'tcx, ty::Ty<'tcx>> {
match self {
Function::DropGlue(real_ty) => Ok(real_ty),
@@ -221,50 +214,43 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
self.alloc_map.iter()
}

pub fn create_closure_ptr(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, substs: ClosureSubsts<'tcx>, fn_ty: ClosureTy<'tcx>) -> Pointer {
// FIXME: this is a hack
let fn_ty = tcx.mk_bare_fn(ty::BareFnTy {
unsafety: fn_ty.unsafety,
abi: fn_ty.abi,
sig: fn_ty.sig,
});
pub fn create_closure_ptr(&mut self, def_id: DefId, substs: ClosureSubsts<'tcx>, sig: PolyFnSig<'tcx>) -> Pointer {
self.create_fn_alloc(Function::Closure(FunctionDefinition {
def_id,
substs: substs.substs,
abi: fn_ty.abi,
// FIXME: why doesn't this compile?
//sig: tcx.erase_late_bound_regions(&fn_ty.sig),
sig: fn_ty.sig.skip_binder(),
sig,
}))
}

pub fn create_fn_ptr_from_noncapture_closure(&mut self, def_id: DefId, substs: ClosureSubsts<'tcx>, sig: PolyFnSig<'tcx>) -> Pointer {
self.create_fn_alloc(Function::NonCaptureClosureAsFnPtr(FunctionDefinition {
def_id,
substs: substs.substs,
sig,
}))
}

pub fn create_fn_as_trait_glue(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, substs: &'tcx Substs<'tcx>, fn_ty: &'tcx BareFnTy<'tcx>) -> Pointer {
pub fn create_fn_as_trait_glue(&mut self, def_id: DefId, substs: &'tcx Substs, sig: PolyFnSig<'tcx>) -> Pointer {
self.create_fn_alloc(Function::FnDefAsTraitObject(FunctionDefinition {
def_id,
substs,
abi: fn_ty.abi,
// FIXME: why doesn't this compile?
//sig: tcx.erase_late_bound_regions(&fn_ty.sig),
sig: fn_ty.sig.skip_binder(),
sig,
}))
}

pub fn create_fn_ptr_as_trait_glue(&mut self, fn_ty: &'tcx BareFnTy<'tcx>) -> Pointer {
self.create_fn_alloc(Function::FnPtrAsTraitObject(fn_ty.sig.skip_binder()))
pub fn create_fn_ptr_as_trait_glue(&mut self, sig: PolyFnSig<'tcx>) -> Pointer {
self.create_fn_alloc(Function::FnPtrAsTraitObject(sig))
}

pub fn create_drop_glue(&mut self, ty: ty::Ty<'tcx>) -> Pointer {
self.create_fn_alloc(Function::DropGlue(ty))
}

pub fn create_fn_ptr(&mut self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, substs: &'tcx Substs<'tcx>, fn_ty: &'tcx BareFnTy<'tcx>) -> Pointer {
pub fn create_fn_ptr(&mut self, def_id: DefId, substs: &'tcx Substs, sig: PolyFnSig<'tcx>) -> Pointer {
self.create_fn_alloc(Function::Concrete(FunctionDefinition {
def_id,
substs,
abi: fn_ty.abi,
// FIXME: why doesn't this compile?
//sig: tcx.erase_late_bound_regions(&fn_ty.sig),
sig: fn_ty.sig.skip_binder(),
sig,
}))
}

@@ -535,6 +521,10 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
trace!("{} closure glue for {}", msg, dump_fn_def(fn_def));
continue;
},
(None, Some(&Function::NonCaptureClosureAsFnPtr(fn_def))) => {
trace!("{} non-capture closure as fn ptr glue for {}", msg, dump_fn_def(fn_def));
continue;
},
(None, None) => {
trace!("{} (deallocated)", msg);
continue;
@@ -606,12 +596,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {

fn dump_fn_def<'tcx>(fn_def: FunctionDefinition<'tcx>) -> String {
let name = ty::tls::with(|tcx| tcx.item_path_str(fn_def.def_id));
let abi = if fn_def.abi == Abi::Rust {
format!("")
} else {
format!("extern {} ", fn_def.abi)
};
format!("function pointer: {}: {}{}", name, abi, fn_def.sig)
format!("function pointer: {}: {}", name, fn_def.sig.skip_binder())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think skipping the binder is needed here at all!

Copy link
Contributor Author

@oli-obk oli-obk Mar 2, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes it is :) There's no Display impl for Binder

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, right, it's Debug only - should still do the right thing though.

}

/// Byte accessors
3 changes: 2 additions & 1 deletion src/step.rs
Original file line number Diff line number Diff line change
@@ -242,7 +242,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for ConstantExtractor<'a, 'b, 'tcx> {
location: mir::Location
) {
self.super_lvalue(lvalue, context, location);
if let mir::Lvalue::Static(def_id) = *lvalue {
if let mir::Lvalue::Static(ref static_) = *lvalue {
let def_id = static_.def_id;
let substs = self.ecx.tcx.intern_substs(&[]);
let span = self.span;
if let Some(node_item) = self.ecx.tcx.hir.get_if_local(def_id) {
6 changes: 3 additions & 3 deletions src/terminator/drop.rs
Original file line number Diff line number Diff line change
@@ -97,7 +97,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
let (adt_ptr, extra) = lval.to_ptr_and_extra();

// run drop impl before the fields' drop impls
if let Some(drop_def_id) = adt_def.destructor() {
if let Some(destructor) = adt_def.destructor(self.tcx) {
let trait_ref = ty::Binder(ty::TraitRef {
def_id: self.tcx.lang_items.drop_trait().unwrap(),
substs: self.tcx.mk_substs_trait(ty, &[]),
@@ -112,7 +112,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
LvalueExtra::Length(n) => Value::ByValPair(PrimVal::Ptr(adt_ptr), PrimVal::from_u128(n as u128)),
LvalueExtra::Vtable(vtable) => Value::ByValPair(PrimVal::Ptr(adt_ptr), PrimVal::Ptr(vtable)),
};
drop.push((drop_def_id, val, vtable.substs));
drop.push((destructor.did, val, vtable.substs));
}

let layout = self.type_layout(ty)?;
@@ -121,7 +121,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
Layout::General { .. } => {
let discr_val = self.read_discriminant_value(adt_ptr, ty)? as u128;
let ptr = self.force_allocation(lval)?.to_ptr();
match adt_def.variants.iter().position(|v| discr_val == v.disr_val) {
match adt_def.discriminants(self.tcx).position(|v| discr_val == v.to_u128_unchecked()) {
Some(i) => {
lval = Lvalue::Ptr {
ptr,
Loading