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,
Expand Down Expand Up @@ -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) =>
Expand Down
47 changes: 31 additions & 16 deletions src/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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),
Expand All @@ -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!(),
};
Expand Down Expand Up @@ -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())
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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),
},
}
}

Expand All @@ -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 {
Expand Down
4 changes: 2 additions & 2 deletions src/lvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
67 changes: 26 additions & 41 deletions src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand All @@ -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),
Expand Down Expand Up @@ -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,
}))
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion src/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
6 changes: 3 additions & 3 deletions src/terminator/drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, &[]),
Expand All @@ -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)?;
Expand All @@ -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,
Expand Down
Loading