Merge remote branch 'nmatsakis/issue-4808-representation-of-extern-fn' into incoming

This commit is contained in:
Patrick Walton 2013-03-01 08:43:36 -08:00
commit 02a4b5bed3
15 changed files with 312 additions and 129 deletions

View File

@ -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)),
})
}
}
}
}

View File

@ -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 {

View File

@ -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,

View File

@ -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;

View File

@ -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)
};

View File

@ -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,

View File

@ -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);

View File

@ -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).

View File

@ -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),

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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 })
);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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,