Merge remote branch 'nmatsakis/issue-4808-representation-of-extern-fn' into incoming
This commit is contained in:
commit
02a4b5bed3
@ -451,9 +451,17 @@ impl tr for ast::def {
|
||||
|
||||
impl tr for ty::AutoAdjustment {
|
||||
fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::AutoAdjustment {
|
||||
ty::AutoAdjustment {
|
||||
autoderefs: self.autoderefs,
|
||||
autoref: self.autoref.map(|ar| ar.tr(xcx)),
|
||||
match self {
|
||||
&ty::AutoAddEnv(r, s) => {
|
||||
ty::AutoAddEnv(r.tr(xcx), s)
|
||||
}
|
||||
|
||||
&ty::AutoDerefRef(ref adr) => {
|
||||
ty::AutoDerefRef(ty::AutoDerefRef {
|
||||
autoderefs: adr.autoderefs,
|
||||
autoref: adr.autoref.map(|ar| ar.tr(xcx)),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -299,17 +299,27 @@ pub impl GatherLoanCtxt {
|
||||
expr_repr(self.tcx(), expr), adjustment);
|
||||
let _i = indenter();
|
||||
|
||||
match adjustment.autoref {
|
||||
None => {
|
||||
match *adjustment {
|
||||
ty::AutoAddEnv(*) => {
|
||||
debug!("autoaddenv -- no autoref");
|
||||
return;
|
||||
}
|
||||
|
||||
ty::AutoDerefRef(
|
||||
ty::AutoDerefRef {
|
||||
autoref: None, _ }) => {
|
||||
debug!("no autoref");
|
||||
return;
|
||||
}
|
||||
|
||||
Some(ref autoref) => {
|
||||
ty::AutoDerefRef(
|
||||
ty::AutoDerefRef {
|
||||
autoref: Some(ref autoref),
|
||||
autoderefs: autoderefs}) => {
|
||||
let mcx = &mem_categorization_ctxt {
|
||||
tcx: self.tcx(),
|
||||
method_map: self.bccx.method_map};
|
||||
let mut cmt = mcx.cat_expr_autoderefd(expr, adjustment);
|
||||
let mut cmt = mcx.cat_expr_autoderefd(expr, autoderefs);
|
||||
debug!("after autoderef, cmt=%s", self.bccx.cmt_to_repr(cmt));
|
||||
|
||||
match autoref.kind {
|
||||
|
@ -480,9 +480,20 @@ pub impl BorrowckCtxt {
|
||||
}
|
||||
|
||||
fn cat_expr_autoderefd(&self, expr: @ast::expr,
|
||||
adj: @ty::AutoAdjustment)
|
||||
-> cmt {
|
||||
cat_expr_autoderefd(self.tcx, self.method_map, expr, adj)
|
||||
adj: @ty::AutoAdjustment) -> cmt {
|
||||
match *adj {
|
||||
ty::AutoAddEnv(*) => {
|
||||
// no autoderefs
|
||||
cat_expr_unadjusted(self.tcx, self.method_map, expr)
|
||||
}
|
||||
|
||||
ty::AutoDerefRef(
|
||||
ty::AutoDerefRef {
|
||||
autoderefs: autoderefs, _}) => {
|
||||
cat_expr_autoderefd(self.tcx, self.method_map, expr,
|
||||
autoderefs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn cat_def(&self,
|
||||
|
@ -241,12 +241,12 @@ pub fn cat_expr_autoderefd(
|
||||
tcx: ty::ctxt,
|
||||
method_map: typeck::method_map,
|
||||
expr: @ast::expr,
|
||||
adj: @ty::AutoAdjustment) -> cmt {
|
||||
|
||||
autoderefs: uint) -> cmt
|
||||
{
|
||||
let mcx = &mem_categorization_ctxt {
|
||||
tcx: tcx, method_map: method_map
|
||||
};
|
||||
return mcx.cat_expr_autoderefd(expr, adj);
|
||||
return mcx.cat_expr_autoderefd(expr, autoderefs);
|
||||
}
|
||||
|
||||
pub fn cat_def(
|
||||
@ -361,28 +361,38 @@ pub impl mem_categorization_ctxt {
|
||||
self.cat_expr_unadjusted(expr)
|
||||
}
|
||||
|
||||
Some(adjustment) => {
|
||||
match adjustment.autoref {
|
||||
Some(_) => {
|
||||
// Equivalent to &*expr or something similar.
|
||||
// This is an rvalue, effectively.
|
||||
let expr_ty = ty::expr_ty(self.tcx, expr);
|
||||
self.cat_rvalue(expr, expr_ty)
|
||||
}
|
||||
None => {
|
||||
// Equivalent to *expr or something similar.
|
||||
self.cat_expr_autoderefd(expr, adjustment)
|
||||
}
|
||||
}
|
||||
Some(@ty::AutoAddEnv(*)) => {
|
||||
// Convert a bare fn to a closure by adding NULL env.
|
||||
// Result is an rvalue.
|
||||
let expr_ty = ty::expr_ty_adjusted(self.tcx, expr);
|
||||
self.cat_rvalue(expr, expr_ty)
|
||||
}
|
||||
|
||||
Some(
|
||||
@ty::AutoDerefRef(
|
||||
ty::AutoDerefRef {
|
||||
autoref: Some(_), _})) => {
|
||||
// Equivalent to &*expr or something similar.
|
||||
// Result is an rvalue.
|
||||
let expr_ty = ty::expr_ty_adjusted(self.tcx, expr);
|
||||
self.cat_rvalue(expr, expr_ty)
|
||||
}
|
||||
|
||||
Some(
|
||||
@ty::AutoDerefRef(
|
||||
ty::AutoDerefRef {
|
||||
autoref: None, autoderefs: autoderefs})) => {
|
||||
// Equivalent to *expr or something similar.
|
||||
self.cat_expr_autoderefd(expr, autoderefs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn cat_expr_autoderefd(&self,
|
||||
expr: @ast::expr,
|
||||
adjustment: &ty::AutoAdjustment) -> cmt {
|
||||
autoderefs: uint) -> cmt {
|
||||
let mut cmt = self.cat_expr_unadjusted(expr);
|
||||
for uint::range(1, adjustment.autoderefs+1) |deref| {
|
||||
for uint::range(1, autoderefs+1) |deref| {
|
||||
cmt = self.cat_deref(expr, cmt, deref);
|
||||
}
|
||||
return cmt;
|
||||
|
@ -410,7 +410,9 @@ pub impl VisitContext {
|
||||
// those adjustments is to take a reference, then it's only
|
||||
// reading the underlying expression, not moving it.
|
||||
let comp_mode = match self.tcx.adjustments.find(&expr.id) {
|
||||
Some(adj) if adj.autoref.is_some() => Read,
|
||||
Some(@ty::AutoDerefRef(
|
||||
ty::AutoDerefRef {
|
||||
autoref: Some(_), _})) => Read,
|
||||
_ => expr_mode.component_mode(expr)
|
||||
};
|
||||
|
||||
|
@ -94,10 +94,25 @@ pub fn trans(bcx: block, expr: @ast::expr) -> Callee {
|
||||
}
|
||||
|
||||
// any other expressions are closures:
|
||||
return closure_callee(&expr::trans_to_datum(bcx, expr));
|
||||
return datum_callee(bcx, expr);
|
||||
|
||||
fn closure_callee(db: &DatumBlock) -> Callee {
|
||||
return Callee {bcx: db.bcx, data: Closure(db.datum)};
|
||||
fn datum_callee(bcx: block, expr: @ast::expr) -> Callee {
|
||||
let DatumBlock {bcx, datum} = expr::trans_to_datum(bcx, expr);
|
||||
match ty::get(datum.ty).sty {
|
||||
ty::ty_bare_fn(*) => {
|
||||
let llval = datum.to_appropriate_llval(bcx);
|
||||
return Callee {bcx: bcx, data: Fn(FnData {llfn: llval})};
|
||||
}
|
||||
ty::ty_closure(*) => {
|
||||
return Callee {bcx: bcx, data: Closure(datum)};
|
||||
}
|
||||
_ => {
|
||||
bcx.tcx().sess.span_bug(
|
||||
expr.span,
|
||||
fmt!("Type of callee is neither bare-fn nor closure: %s",
|
||||
bcx.ty_to_str(datum.ty)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fn_callee(bcx: block, fd: FnData) -> Callee {
|
||||
@ -129,7 +144,7 @@ pub fn trans(bcx: block, expr: @ast::expr) -> Callee {
|
||||
ast::def_binding(*) |
|
||||
ast::def_upvar(*) |
|
||||
ast::def_self(*) => {
|
||||
closure_callee(&expr::trans_to_datum(bcx, ref_expr))
|
||||
datum_callee(bcx, ref_expr)
|
||||
}
|
||||
ast::def_mod(*) | ast::def_foreign_mod(*) |
|
||||
ast::def_const(*) | ast::def_ty(*) | ast::def_prim_ty(*) |
|
||||
@ -392,7 +407,6 @@ pub fn trans_lang_call_with_type_params(bcx: block,
|
||||
fty);
|
||||
let mut llfnty = type_of::type_of(callee.bcx.ccx(),
|
||||
substituted);
|
||||
llfnty = lib::llvm::struct_tys(llfnty)[0];
|
||||
new_llval = PointerCast(callee.bcx, fn_data.llfn, llfnty);
|
||||
}
|
||||
_ => fail!()
|
||||
@ -715,6 +729,8 @@ pub fn trans_arg_expr(bcx: block,
|
||||
}
|
||||
|
||||
ast::by_copy => {
|
||||
debug!("by copy arg with type %s, storing to scratch",
|
||||
ty_to_str(ccx.tcx, arg_datum.ty));
|
||||
let scratch = scratch_datum(bcx, arg_datum.ty, false);
|
||||
|
||||
arg_datum.store_to_datum(bcx, arg_expr.id,
|
||||
|
@ -1344,6 +1344,12 @@ pub fn expr_ty(bcx: block, ex: @ast::expr) -> ty::t {
|
||||
node_id_type(bcx, ex.id)
|
||||
}
|
||||
|
||||
pub fn expr_ty_adjusted(bcx: block, ex: @ast::expr) -> ty::t {
|
||||
let tcx = bcx.tcx();
|
||||
let t = ty::expr_ty_adjusted(tcx, ex);
|
||||
monomorphize_type(bcx, t)
|
||||
}
|
||||
|
||||
pub fn node_id_type_params(bcx: block, id: ast::node_id) -> ~[ty::t] {
|
||||
let tcx = bcx.tcx();
|
||||
let params = ty::node_id_to_type_params(tcx, id);
|
||||
|
@ -144,7 +144,8 @@ use middle::trans::tvec;
|
||||
use middle::trans::type_of;
|
||||
use middle::ty;
|
||||
use middle::ty::struct_mutable_fields;
|
||||
use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn};
|
||||
use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn,
|
||||
AutoDerefRef, AutoAddEnv};
|
||||
use util::common::indenter;
|
||||
use util::ppaux::ty_to_str;
|
||||
|
||||
@ -197,7 +198,14 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
|
||||
None => {
|
||||
trans_to_datum_unadjusted(bcx, expr)
|
||||
}
|
||||
Some(adj) => {
|
||||
Some(@AutoAddEnv(*)) => {
|
||||
let mut bcx = bcx;
|
||||
let mut datum = unpack_datum!(bcx, {
|
||||
trans_to_datum_unadjusted(bcx, expr)
|
||||
});
|
||||
add_env(bcx, expr, datum)
|
||||
}
|
||||
Some(@AutoDerefRef(ref adj)) => {
|
||||
let mut bcx = bcx;
|
||||
let mut datum = unpack_datum!(bcx, {
|
||||
trans_to_datum_unadjusted(bcx, expr)
|
||||
@ -266,6 +274,25 @@ pub fn trans_to_datum(bcx: block, expr: @ast::expr) -> DatumBlock {
|
||||
DatumBlock {bcx: bcx, datum: scratch}
|
||||
}
|
||||
|
||||
fn add_env(bcx: block, expr: @ast::expr, datum: Datum) -> DatumBlock {
|
||||
// This is not the most efficient thing possible; since closures
|
||||
// are two words it'd be better if this were compiled in
|
||||
// 'dest' mode, but I can't find a nice way to structure the
|
||||
// code and keep it DRY that accommodates that use case at the
|
||||
// moment.
|
||||
|
||||
let tcx = bcx.tcx();
|
||||
let closure_ty = expr_ty_adjusted(bcx, expr);
|
||||
debug!("add_env(closure_ty=%s)", ty_to_str(tcx, closure_ty));
|
||||
let scratch = scratch_datum(bcx, closure_ty, false);
|
||||
let llfn = GEPi(bcx, scratch.val, [0u, abi::fn_field_code]);
|
||||
assert datum.appropriate_mode() == ByValue;
|
||||
Store(bcx, datum.to_appropriate_llval(bcx), llfn);
|
||||
let llenv = GEPi(bcx, scratch.val, [0u, abi::fn_field_box]);
|
||||
Store(bcx, base::null_env_ptr(bcx), llenv);
|
||||
DatumBlock {bcx: bcx, datum: scratch}
|
||||
}
|
||||
|
||||
fn auto_slice_and_ref(bcx: block, datum: Datum) -> DatumBlock {
|
||||
let DatumBlock { bcx, datum } = auto_slice(bcx, datum);
|
||||
auto_ref(bcx, datum)
|
||||
@ -420,6 +447,9 @@ fn trans_rvalue_datum_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
|
||||
trace_span!(bcx, expr.span, @shorten(bcx.expr_to_str(expr)));
|
||||
|
||||
match expr.node {
|
||||
ast::expr_path(_) => {
|
||||
return trans_def_datum_unadjusted(bcx, expr, bcx.def(expr.id));
|
||||
}
|
||||
ast::expr_vstore(contents, ast::expr_vstore_box) |
|
||||
ast::expr_vstore(contents, ast::expr_vstore_mut_box) => {
|
||||
return tvec::trans_uniq_or_managed_vstore(bcx, heap_managed,
|
||||
@ -685,22 +715,13 @@ fn trans_def_dps_unadjusted(bcx: block, ref_expr: @ast::expr,
|
||||
};
|
||||
|
||||
match def {
|
||||
ast::def_fn(did, _) | ast::def_static_method(did, None, _) => {
|
||||
let fn_data = callee::trans_fn_ref(bcx, did, ref_expr.id);
|
||||
return fn_data_to_datum(bcx, did, fn_data, lldest);
|
||||
}
|
||||
ast::def_static_method(impl_did, Some(trait_did), _) => {
|
||||
let fn_data = meth::trans_static_method_callee(bcx, impl_did,
|
||||
trait_did,
|
||||
ref_expr.id);
|
||||
return fn_data_to_datum(bcx, impl_did, fn_data, lldest);
|
||||
}
|
||||
ast::def_variant(tid, vid) => {
|
||||
let variant_info = ty::enum_variant_with_id(ccx.tcx, tid, vid);
|
||||
if variant_info.args.len() > 0u {
|
||||
// N-ary variant.
|
||||
let fn_data = callee::trans_fn_ref(bcx, vid, ref_expr.id);
|
||||
return fn_data_to_datum(bcx, vid, fn_data, lldest);
|
||||
Store(bcx, fn_data.llfn, lldest);
|
||||
return bcx;
|
||||
} else if !ty::enum_is_univariant(ccx.tcx, tid) {
|
||||
// Nullary variant.
|
||||
let lldiscrimptr = GEPi(bcx, lldest, [0u, 0u]);
|
||||
@ -725,6 +746,66 @@ fn trans_def_dps_unadjusted(bcx: block, ref_expr: @ast::expr,
|
||||
}
|
||||
}
|
||||
|
||||
fn trans_def_datum_unadjusted(bcx: block,
|
||||
ref_expr: @ast::expr,
|
||||
def: ast::def) -> DatumBlock
|
||||
{
|
||||
let _icx = bcx.insn_ctxt("trans_def_datum_unadjusted");
|
||||
|
||||
match def {
|
||||
ast::def_fn(did, _) | ast::def_static_method(did, None, _) => {
|
||||
let fn_data = callee::trans_fn_ref(bcx, did, ref_expr.id);
|
||||
return fn_data_to_datum(bcx, ref_expr, did, fn_data);
|
||||
}
|
||||
ast::def_static_method(impl_did, Some(trait_did), _) => {
|
||||
let fn_data = meth::trans_static_method_callee(bcx, impl_did,
|
||||
trait_did,
|
||||
ref_expr.id);
|
||||
return fn_data_to_datum(bcx, ref_expr, impl_did, fn_data);
|
||||
}
|
||||
_ => {
|
||||
bcx.tcx().sess.span_bug(ref_expr.span, fmt!(
|
||||
"Non-DPS def %? referened by %s",
|
||||
def, bcx.node_id_to_str(ref_expr.id)));
|
||||
}
|
||||
}
|
||||
|
||||
fn fn_data_to_datum(bcx: block,
|
||||
ref_expr: @ast::expr,
|
||||
def_id: ast::def_id,
|
||||
fn_data: callee::FnData) -> DatumBlock {
|
||||
/*!
|
||||
*
|
||||
* Translates a reference to a top-level fn item into a rust
|
||||
* value. This is just a fn pointer.
|
||||
*/
|
||||
|
||||
let is_extern = {
|
||||
let fn_tpt = ty::lookup_item_type(bcx.tcx(), def_id);
|
||||
ty::ty_fn_purity(fn_tpt.ty) == ast::extern_fn
|
||||
};
|
||||
let (rust_ty, llval) = if is_extern {
|
||||
let rust_ty = ty::mk_ptr(
|
||||
bcx.tcx(),
|
||||
ty::mt {
|
||||
ty: ty::mk_mach_uint(bcx.tcx(), ast::ty_u8),
|
||||
mutbl: ast::m_imm
|
||||
}); // *u8
|
||||
(rust_ty, PointerCast(bcx, fn_data.llfn, T_ptr(T_i8())))
|
||||
} else {
|
||||
let fn_ty = expr_ty(bcx, ref_expr);
|
||||
(fn_ty, fn_data.llfn)
|
||||
};
|
||||
return DatumBlock {
|
||||
bcx: bcx,
|
||||
datum: Datum {val: llval,
|
||||
ty: rust_ty,
|
||||
mode: ByValue,
|
||||
source: RevokeClean}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
|
||||
/*!
|
||||
*
|
||||
@ -1012,36 +1093,6 @@ pub fn trans_local_var(bcx: block, def: ast::def) -> Datum {
|
||||
}
|
||||
}
|
||||
|
||||
fn fn_data_to_datum(bcx: block,
|
||||
def_id: ast::def_id,
|
||||
fn_data: callee::FnData,
|
||||
lldest: ValueRef) -> block {
|
||||
//!
|
||||
//
|
||||
// Translates a reference to a top-level fn item into a rust
|
||||
// value. This is generally a Rust closure pair: (fn ptr, env)
|
||||
// where the environment is NULL. However, extern functions for
|
||||
// interfacing with C are represted as just the fn ptr with type
|
||||
// *u8.
|
||||
//
|
||||
// Strictly speaking, references to extern fns ought to be
|
||||
// RvalueDatumExprs, but it's not worth the complexity to avoid the
|
||||
// extra stack slot that LLVM probably optimizes away anyhow.
|
||||
|
||||
let fn_tpt = ty::lookup_item_type(bcx.tcx(), def_id);
|
||||
if ty::ty_fn_purity(fn_tpt.ty) == ast::extern_fn {
|
||||
let val = PointerCast(bcx, fn_data.llfn, T_ptr(T_i8()));
|
||||
Store(bcx, val, lldest);
|
||||
return bcx;
|
||||
}
|
||||
|
||||
let llfn = GEPi(bcx, lldest, [0u, abi::fn_field_code]);
|
||||
Store(bcx, fn_data.llfn, llfn);
|
||||
let llenv = GEPi(bcx, lldest, [0u, abi::fn_field_box]);
|
||||
Store(bcx, base::null_env_ptr(bcx), llenv);
|
||||
return bcx;
|
||||
}
|
||||
|
||||
// The optional node ID here is the node ID of the path identifying the enum
|
||||
// variant in use. If none, this cannot possibly an enum variant (so, if it
|
||||
// is and `node_id_opt` is none, this function fails).
|
||||
|
@ -134,8 +134,7 @@ pub fn sizing_type_of(cx: @CrateContext, t: ty::t) -> TypeRef {
|
||||
T_struct(~[T_ptr(T_i8()), T_ptr(T_i8())])
|
||||
}
|
||||
|
||||
// FIXME(#4804) Bare fn repr
|
||||
ty::ty_bare_fn(*) => T_struct(~[T_ptr(T_i8()), T_ptr(T_i8())]),
|
||||
ty::ty_bare_fn(*) => T_ptr(T_i8()),
|
||||
ty::ty_closure(*) => T_struct(~[T_ptr(T_i8()), T_ptr(T_i8())]),
|
||||
ty::ty_trait(_, _, vstore) => T_opaque_trait(cx, vstore),
|
||||
|
||||
@ -173,7 +172,9 @@ pub fn sizing_type_of(cx: @CrateContext, t: ty::t) -> TypeRef {
|
||||
ty::ty_enum(def_id, _) => T_struct(enum_body_types(cx, def_id, t)),
|
||||
|
||||
ty::ty_self | ty::ty_infer(*) | ty::ty_param(*) | ty::ty_err(*) => {
|
||||
cx.tcx.sess.bug(~"fictitious type in sizing_type_of()")
|
||||
cx.tcx.sess.bug(
|
||||
fmt!("fictitious type %? in sizing_type_of()",
|
||||
ty::get(t).sty))
|
||||
}
|
||||
};
|
||||
|
||||
@ -270,9 +271,7 @@ pub fn type_of(cx: @CrateContext, t: ty::t) -> TypeRef {
|
||||
T_struct(~[T_struct(tys)])
|
||||
}
|
||||
|
||||
// FIXME(#4804) Bare fn repr
|
||||
// ty::ty_bare_fn(_) => T_ptr(type_of_fn_from_ty(cx, t)),
|
||||
ty::ty_bare_fn(_) => T_fn_pair(cx, type_of_fn_from_ty(cx, t)),
|
||||
ty::ty_bare_fn(_) => T_ptr(type_of_fn_from_ty(cx, t)),
|
||||
ty::ty_closure(_) => T_fn_pair(cx, type_of_fn_from_ty(cx, t)),
|
||||
ty::ty_trait(_, _, vstore) => T_opaque_trait(cx, vstore),
|
||||
ty::ty_type => T_ptr(cx.tydesc_type),
|
||||
|
@ -172,7 +172,14 @@ impl cmp::Eq for region_variance {
|
||||
|
||||
#[auto_encode]
|
||||
#[auto_decode]
|
||||
pub struct AutoAdjustment {
|
||||
pub enum AutoAdjustment {
|
||||
AutoAddEnv(ty::Region, ast::Sigil),
|
||||
AutoDerefRef(AutoDerefRef)
|
||||
}
|
||||
|
||||
#[auto_encode]
|
||||
#[auto_decode]
|
||||
pub struct AutoDerefRef {
|
||||
autoderefs: uint,
|
||||
autoref: Option<AutoRef>
|
||||
}
|
||||
@ -198,7 +205,7 @@ pub enum AutoRefKind {
|
||||
AutoBorrowVecRef,
|
||||
|
||||
/// Convert from @fn()/~fn() to &fn()
|
||||
AutoBorrowFn,
|
||||
AutoBorrowFn
|
||||
}
|
||||
|
||||
// Stores information about provided methods (a.k.a. default methods) in
|
||||
@ -1475,7 +1482,6 @@ pub fn type_is_structural(ty: t) -> bool {
|
||||
match get(ty).sty {
|
||||
ty_rec(_) | ty_struct(*) | ty_tup(_) | ty_enum(*) |
|
||||
ty_closure(_) |
|
||||
ty_bare_fn(_) | // FIXME(#4804) Bare fn repr
|
||||
ty_trait(*) |
|
||||
ty_evec(_, vstore_fixed(_)) | ty_estr(vstore_fixed(_)) |
|
||||
ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_))
|
||||
@ -1585,7 +1591,7 @@ pub pure fn type_is_scalar(ty: t) -> bool {
|
||||
match get(ty).sty {
|
||||
ty_nil | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
|
||||
ty_infer(IntVar(_)) | ty_infer(FloatVar(_)) | ty_type |
|
||||
ty_ptr(_) => true,
|
||||
ty_bare_fn(*) | ty_ptr(_) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
@ -2882,7 +2888,25 @@ pub fn expr_ty_adjusted(cx: ctxt, expr: @ast::expr) -> t {
|
||||
return match cx.adjustments.find(&expr.id) {
|
||||
None => unadjusted_ty,
|
||||
|
||||
Some(adj) => {
|
||||
Some(@AutoAddEnv(r, s)) => {
|
||||
match ty::get(unadjusted_ty).sty {
|
||||
ty::ty_bare_fn(ref b) => {
|
||||
ty::mk_closure(
|
||||
cx,
|
||||
ty::ClosureTy {purity: b.purity,
|
||||
sigil: s,
|
||||
onceness: ast::Many,
|
||||
region: r,
|
||||
sig: copy b.sig})
|
||||
}
|
||||
ref b => {
|
||||
cx.sess.bug(
|
||||
fmt!("add_env adjustment on non-bare-fn: %?", b));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(@AutoDerefRef(ref adj)) => {
|
||||
let mut adjusted_ty = unadjusted_ty;
|
||||
|
||||
for uint::range(0, adj.autoderefs) |i| {
|
||||
@ -3064,9 +3088,11 @@ pub fn expr_kind(tcx: ctxt,
|
||||
match expr.node {
|
||||
ast::expr_path(*) => {
|
||||
match resolve_expr(tcx, expr) {
|
||||
ast::def_fn(*) | ast::def_static_method(*) |
|
||||
ast::def_variant(*) | ast::def_struct(*) => RvalueDpsExpr,
|
||||
|
||||
// Fn pointers are just scalar values.
|
||||
ast::def_fn(*) | ast::def_static_method(*) => RvalueDatumExpr,
|
||||
|
||||
// Note: there is actually a good case to be made that
|
||||
// def_args, particularly those of immediate type, ought to
|
||||
// considered rvalues.
|
||||
|
@ -799,26 +799,28 @@ pub impl LookupContext {
|
||||
let region = self.infcx().next_region_var(self.expr.span,
|
||||
self.expr.id);
|
||||
(ty::mk_rptr(tcx, region, self_mt),
|
||||
ty::AutoAdjustment {
|
||||
ty::AutoDerefRef(ty::AutoDerefRef {
|
||||
autoderefs: autoderefs+1,
|
||||
autoref: Some(ty::AutoRef {kind: AutoPtr,
|
||||
region: region,
|
||||
mutbl: self_mt.mutbl})})
|
||||
mutbl: self_mt.mutbl})}))
|
||||
}
|
||||
ty::ty_evec(self_mt, vstore_slice(_))
|
||||
if self_mt.mutbl == m_mutbl => {
|
||||
let region = self.infcx().next_region_var(self.expr.span,
|
||||
self.expr.id);
|
||||
(ty::mk_evec(tcx, self_mt, vstore_slice(region)),
|
||||
ty::AutoAdjustment {
|
||||
ty::AutoDerefRef(ty::AutoDerefRef {
|
||||
autoderefs: autoderefs,
|
||||
autoref: Some(ty::AutoRef {kind: AutoBorrowVec,
|
||||
region: region,
|
||||
mutbl: self_mt.mutbl})})
|
||||
mutbl: self_mt.mutbl})}))
|
||||
}
|
||||
_ => {
|
||||
(self_ty, ty::AutoAdjustment {autoderefs: autoderefs,
|
||||
autoref: None})
|
||||
(self_ty,
|
||||
ty::AutoDerefRef(ty::AutoDerefRef {
|
||||
autoderefs: autoderefs,
|
||||
autoref: None}))
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -947,14 +949,14 @@ pub impl LookupContext {
|
||||
Some(mme) => {
|
||||
self.fcx.write_adjustment(
|
||||
self.self_expr.id,
|
||||
@ty::AutoAdjustment {
|
||||
@ty::AutoDerefRef(ty::AutoDerefRef {
|
||||
autoderefs: autoderefs,
|
||||
autoref: Some(ty::AutoRef {
|
||||
kind: kind,
|
||||
region: region,
|
||||
mutbl: *mutbl,
|
||||
}),
|
||||
});
|
||||
}));
|
||||
return Some(mme);
|
||||
}
|
||||
}
|
||||
|
@ -739,7 +739,9 @@ pub impl FnCtxt {
|
||||
if derefs == 0 { return; }
|
||||
self.write_adjustment(
|
||||
node_id,
|
||||
@ty::AutoAdjustment { autoderefs: derefs, autoref: None }
|
||||
@ty::AutoDerefRef(ty::AutoDerefRef {
|
||||
autoderefs: derefs,
|
||||
autoref: None })
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -184,8 +184,13 @@ pub fn visit_expr(expr: @ast::expr, &&rcx: @mut Rcx, v: rvt) {
|
||||
debug!("visit_expr(e=%s)", rcx.fcx.expr_to_str(expr));
|
||||
|
||||
for rcx.fcx.inh.adjustments.find(&expr.id).each |adjustment| {
|
||||
for adjustment.autoref.each |autoref| {
|
||||
guarantor::for_autoref(rcx, expr, *adjustment, autoref);
|
||||
match *adjustment {
|
||||
@ty::AutoDerefRef(
|
||||
ty::AutoDerefRef {
|
||||
autoderefs: autoderefs, autoref: Some(ref autoref)}) => {
|
||||
guarantor::for_autoref(rcx, expr, autoderefs, autoref);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,9 +334,11 @@ pub fn constrain_auto_ref(rcx: @mut Rcx, expr: @ast::expr) {
|
||||
|
||||
let adjustment = rcx.fcx.inh.adjustments.find(&expr.id);
|
||||
let region = match adjustment {
|
||||
Some(@ty::AutoAdjustment { autoref: Some(ref auto_ref), _ }) => {
|
||||
Some(@ty::AutoDerefRef(
|
||||
ty::AutoDerefRef {
|
||||
autoref: Some(ref auto_ref), _})) => {
|
||||
auto_ref.region
|
||||
},
|
||||
}
|
||||
_ => { return; }
|
||||
};
|
||||
|
||||
@ -563,7 +570,7 @@ pub mod guarantor {
|
||||
|
||||
pub fn for_autoref(rcx: @mut Rcx,
|
||||
expr: @ast::expr,
|
||||
adjustment: &ty::AutoAdjustment,
|
||||
autoderefs: uint,
|
||||
autoref: &ty::AutoRef) {
|
||||
/*!
|
||||
*
|
||||
@ -578,7 +585,7 @@ pub mod guarantor {
|
||||
|
||||
let mut expr_ct = categorize_unadjusted(rcx, expr);
|
||||
expr_ct = apply_autoderefs(
|
||||
rcx, expr, adjustment.autoderefs, expr_ct);
|
||||
rcx, expr, autoderefs, expr_ct);
|
||||
for expr_ct.cat.guarantor.each |g| {
|
||||
infallibly_mk_subr(rcx, true, expr.span, autoref.region, *g);
|
||||
}
|
||||
@ -723,19 +730,32 @@ pub mod guarantor {
|
||||
let mut expr_ct = categorize_unadjusted(rcx, expr);
|
||||
debug!("before adjustments, cat=%?", expr_ct.cat);
|
||||
|
||||
for rcx.fcx.inh.adjustments.find(&expr.id).each |adjustment| {
|
||||
debug!("adjustment=%?", adjustment);
|
||||
|
||||
expr_ct = apply_autoderefs(
|
||||
rcx, expr, adjustment.autoderefs, expr_ct);
|
||||
|
||||
for adjustment.autoref.each |autoref| {
|
||||
// If there is an autoref, then the result of this
|
||||
// expression will be some sort of borrowed pointer.
|
||||
expr_ct.cat.guarantor = None;
|
||||
expr_ct.cat.pointer = BorrowedPointer(autoref.region);
|
||||
debug!("autoref, cat=%?", expr_ct.cat);
|
||||
match rcx.fcx.inh.adjustments.find(&expr.id) {
|
||||
Some(@ty::AutoAddEnv(*)) => {
|
||||
// This is basically an rvalue, not a pointer, no regions
|
||||
// involved.
|
||||
expr_ct.cat = ExprCategorization {
|
||||
guarantor: None,
|
||||
pointer: NotPointer
|
||||
};
|
||||
}
|
||||
|
||||
Some(@ty::AutoDerefRef(ref adjustment)) => {
|
||||
debug!("adjustment=%?", adjustment);
|
||||
|
||||
expr_ct = apply_autoderefs(
|
||||
rcx, expr, adjustment.autoderefs, expr_ct);
|
||||
|
||||
for adjustment.autoref.each |autoref| {
|
||||
// If there is an autoref, then the result of this
|
||||
// expression will be some sort of borrowed pointer.
|
||||
expr_ct.cat.guarantor = None;
|
||||
expr_ct.cat.pointer = BorrowedPointer(autoref.region);
|
||||
debug!("autoref, cat=%?", expr_ct.cat);
|
||||
}
|
||||
}
|
||||
|
||||
None => {}
|
||||
}
|
||||
|
||||
debug!("result=%?", expr_ct.cat);
|
||||
|
@ -79,7 +79,24 @@ fn resolve_type_vars_for_node(wbcx: @mut WbCtxt, sp: span, id: ast::node_id)
|
||||
// Resolve any borrowings for the node with id `id`
|
||||
match fcx.inh.adjustments.find(&id) {
|
||||
None => (),
|
||||
Some(adj) => {
|
||||
|
||||
Some(@ty::AutoAddEnv(r, s)) => {
|
||||
match resolve_region(fcx.infcx(), r, resolve_all | force_all) {
|
||||
Err(e) => {
|
||||
// This should not, I think, happen:
|
||||
fcx.ccx.tcx.sess.span_err(
|
||||
sp, fmt!("cannot resolve bound for closure: %s",
|
||||
infer::fixup_err_to_str(e)));
|
||||
}
|
||||
Ok(r1) => {
|
||||
let resolved_adj = @ty::AutoAddEnv(r1, s);
|
||||
debug!("Adjustments for node %d: %?", id, resolved_adj);
|
||||
fcx.tcx().adjustments.insert(id, resolved_adj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(@ty::AutoDerefRef(adj)) => {
|
||||
let resolved_autoref = match adj.autoref {
|
||||
Some(ref autoref) => {
|
||||
match resolve_region(fcx.infcx(), autoref.region,
|
||||
@ -99,9 +116,10 @@ fn resolve_type_vars_for_node(wbcx: @mut WbCtxt, sp: span, id: ast::node_id)
|
||||
None => None
|
||||
};
|
||||
|
||||
let resolved_adj = @ty::AutoAdjustment {
|
||||
let resolved_adj = @ty::AutoDerefRef(ty::AutoDerefRef {
|
||||
autoderefs: adj.autoderefs,
|
||||
autoref: resolved_autoref,
|
||||
..*adj};
|
||||
});
|
||||
debug!("Adjustments for node %d: %?", id, resolved_adj);
|
||||
fcx.tcx().adjustments.insert(id, resolved_adj);
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ we may want to adjust precisely when coercions occur.
|
||||
use core::prelude::*;
|
||||
|
||||
use middle::ty::{TyVar, AutoPtr, AutoBorrowVec, AutoBorrowFn};
|
||||
use middle::ty::{AutoAdjustment, AutoRef};
|
||||
use middle::ty::{AutoAdjustment, AutoDerefRef, AutoRef};
|
||||
use middle::ty::{vstore_slice, vstore_box, vstore_uniq, vstore_fixed};
|
||||
use middle::ty::{mt};
|
||||
use middle::ty;
|
||||
@ -206,14 +206,14 @@ pub impl Coerce {
|
||||
r_borrow,
|
||||
mt {ty: inner_ty, mutbl: mt_b.mutbl});
|
||||
if_ok!(sub.tys(a_borrowed, b));
|
||||
Ok(Some(@AutoAdjustment {
|
||||
Ok(Some(@AutoDerefRef(AutoDerefRef {
|
||||
autoderefs: 1,
|
||||
autoref: Some(AutoRef {
|
||||
kind: AutoPtr,
|
||||
region: r_borrow,
|
||||
mutbl: mt_b.mutbl
|
||||
})
|
||||
}))
|
||||
})))
|
||||
}
|
||||
|
||||
fn coerce_borrowed_string(&self,
|
||||
@ -236,14 +236,14 @@ pub impl Coerce {
|
||||
let r_a = self.infcx.next_region_var_nb(self.span);
|
||||
let a_borrowed = ty::mk_estr(self.infcx.tcx, vstore_slice(r_a));
|
||||
if_ok!(self.subtype(a_borrowed, b));
|
||||
Ok(Some(@AutoAdjustment {
|
||||
Ok(Some(@AutoDerefRef(AutoDerefRef {
|
||||
autoderefs: 0,
|
||||
autoref: Some(AutoRef {
|
||||
kind: AutoBorrowVec,
|
||||
region: r_a,
|
||||
mutbl: m_imm
|
||||
})
|
||||
}))
|
||||
})))
|
||||
}
|
||||
|
||||
fn coerce_borrowed_vector(&self,
|
||||
@ -269,14 +269,14 @@ pub impl Coerce {
|
||||
mt {ty: ty_inner, mutbl: mt_b.mutbl},
|
||||
vstore_slice(r_borrow));
|
||||
if_ok!(sub.tys(a_borrowed, b));
|
||||
Ok(Some(@AutoAdjustment {
|
||||
Ok(Some(@AutoDerefRef(AutoDerefRef {
|
||||
autoderefs: 0,
|
||||
autoref: Some(AutoRef {
|
||||
kind: AutoBorrowVec,
|
||||
region: r_borrow,
|
||||
mutbl: mt_b.mutbl
|
||||
})
|
||||
}))
|
||||
})))
|
||||
}
|
||||
|
||||
fn coerce_borrowed_fn(&self,
|
||||
@ -309,14 +309,14 @@ pub impl Coerce {
|
||||
});
|
||||
|
||||
if_ok!(self.subtype(a_borrowed, b));
|
||||
Ok(Some(@AutoAdjustment {
|
||||
Ok(Some(@AutoDerefRef(AutoDerefRef {
|
||||
autoderefs: 0,
|
||||
autoref: Some(AutoRef {
|
||||
kind: AutoBorrowFn,
|
||||
region: r_borrow,
|
||||
mutbl: m_imm
|
||||
})
|
||||
}))
|
||||
})))
|
||||
}
|
||||
|
||||
fn coerce_from_bare_fn(&self,
|
||||
@ -347,10 +347,12 @@ pub impl Coerce {
|
||||
|
||||
// for now, bare fn and closures have the same
|
||||
// representation
|
||||
let adj = @ty::AutoAddEnv(fn_ty_b.region, fn_ty_b.sigil);
|
||||
let a_closure = ty::mk_closure(
|
||||
self.infcx.tcx,
|
||||
ty::ClosureTy {sig: copy fn_ty_a.sig, ..fn_ty_b});
|
||||
self.subtype(a_closure, b)
|
||||
if_ok!(self.subtype(a_closure, b));
|
||||
Ok(Some(adj))
|
||||
}
|
||||
|
||||
fn coerce_unsafe_ptr(&self,
|
||||
|
Loading…
Reference in New Issue
Block a user