diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index a52d02ccca7..d475f6ddcba 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -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; @@ -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), ']'); diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 692a815c63c..a127566b67e 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -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; @@ -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; diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index b9af31665a1..faeca0b1886 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -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 { - 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") } }