Skip to content

Commit

Permalink
Treat cross-crate unboxed closure def IDs consistently
Browse files Browse the repository at this point in the history
Always translate the ID into the local crate ID space since
presently the only way to encounter an unboxed closure type
from another crate is to inline once of its functions.

This may need to change if abstract return types are added.

Closes #18543
  • Loading branch information
bkoropoff committed Nov 2, 2014
1 parent 28f70d3 commit 9b322a6
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 31 deletions.
5 changes: 4 additions & 1 deletion src/librustc/metadata/tydecode.rs
Expand Up @@ -56,6 +56,9 @@ pub enum DefIdSource {

// Identifies a region parameter (`fn foo<'X>() { ... }`).
RegionParameter,

// Identifies an unboxed closure
UnboxedClosureSource
}
pub type conv_did<'a> =
|source: DefIdSource, ast::DefId|: 'a -> ast::DefId;
Expand Down Expand Up @@ -465,7 +468,7 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
}
'k' => {
assert_eq!(next(st), '[');
let did = parse_def(st, NominalType, |x,y| conv(x,y));
let did = parse_def(st, UnboxedClosureSource, |x,y| conv(x,y));
let region = parse_region(st, |x,y| conv(x,y));
let substs = parse_substs(st, |x,y| conv(x,y));
assert_eq!(next(st), ']');
Expand Down
8 changes: 6 additions & 2 deletions src/librustc/middle/astencode.rs
Expand Up @@ -21,7 +21,7 @@ use metadata::encoder as e;
use middle::region;
use metadata::tydecode;
use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter};
use metadata::tydecode::{RegionParameter};
use metadata::tydecode::{RegionParameter, UnboxedClosureSource};
use metadata::tyencode;
use middle::mem_categorization::Typer;
use middle::subst;
Expand Down Expand Up @@ -1801,13 +1801,17 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
* case. We translate them with `tr_def_id()` which will map
* the crate numbers back to the original source crate.
*
* Unboxed closures are cloned along with the function being
* inlined, and all side tables use interned node IDs, so we
* translate their def IDs accordingly.
*
* It'd be really nice to refactor the type repr to not include
* def-ids so that all these distinctions were unnecessary.
*/

let r = match source {
NominalType | TypeWithId | RegionParameter => dcx.tr_def_id(did),
TypeParameter => dcx.tr_intern_def_id(did)
TypeParameter | UnboxedClosureSource => dcx.tr_intern_def_id(did)
};
debug!("convert_def_id(source={}, did={})={}", source, did, r);
return r;
Expand Down
58 changes: 30 additions & 28 deletions src/librustc/middle/ty.rs
Expand Up @@ -4632,35 +4632,37 @@ pub struct UnboxedClosureUpvar {
// Returns a list of `UnboxedClosureUpvar`s for each upvar.
pub fn unboxed_closure_upvars(tcx: &ctxt, closure_id: ast::DefId, substs: &Substs)
-> Vec<UnboxedClosureUpvar> {
if closure_id.krate == ast::LOCAL_CRATE {
let capture_mode = tcx.capture_modes.borrow().get_copy(&closure_id.node);
match tcx.freevars.borrow().find(&closure_id.node) {
None => vec![],
Some(ref freevars) => {
freevars.iter().map(|freevar| {
let freevar_def_id = freevar.def.def_id();
let freevar_ty = node_id_to_type(tcx, freevar_def_id.node);
let mut freevar_ty = freevar_ty.subst(tcx, substs);
if capture_mode == ast::CaptureByRef {
let borrow = tcx.upvar_borrow_map.borrow().get_copy(&ty::UpvarId {
var_id: freevar_def_id.node,
closure_expr_id: closure_id.node
});
freevar_ty = mk_rptr(tcx, borrow.region, ty::mt {
ty: freevar_ty,
mutbl: borrow.kind.to_mutbl_lossy()
});
}
UnboxedClosureUpvar {
def: freevar.def,
span: freevar.span,
ty: freevar_ty
}
}).collect()
}
// Presently an unboxed closure type cannot "escape" out of a
// function, so we will only encounter ones that originated in the
// local crate or were inlined into it along with some function.
// This may change if abstract return types of some sort are
// implemented.
assert!(closure_id.krate == ast::LOCAL_CRATE);
let capture_mode = tcx.capture_modes.borrow().get_copy(&closure_id.node);
match tcx.freevars.borrow().find(&closure_id.node) {
None => vec![],
Some(ref freevars) => {
freevars.iter().map(|freevar| {
let freevar_def_id = freevar.def.def_id();
let freevar_ty = node_id_to_type(tcx, freevar_def_id.node);
let mut freevar_ty = freevar_ty.subst(tcx, substs);
if capture_mode == ast::CaptureByRef {
let borrow = tcx.upvar_borrow_map.borrow().get_copy(&ty::UpvarId {
var_id: freevar_def_id.node,
closure_expr_id: closure_id.node
});
freevar_ty = mk_rptr(tcx, borrow.region, ty::mt {
ty: freevar_ty,
mutbl: borrow.kind.to_mutbl_lossy()
});
}
UnboxedClosureUpvar {
def: freevar.def,
span: freevar.span,
ty: freevar_ty
}
}).collect()
}
} else {
tcx.sess.bug("unimplemented cross-crate closure upvars")
}
}

Expand Down

0 comments on commit 9b322a6

Please sign in to comment.