Skip to content

Commit

Permalink
Fix handling of unboxed closure type param substitutions
Browse files Browse the repository at this point in the history
- When selecting an implicit trait impl for an unboxed closure, plumb
  through and use the substitutions from impl selection instead of
  using those from the current param environment in trans, which may
  be incorrect.
- When generating a function declaration for an unboxed closure, plumb
  through the substitutions from the param environment of the closure
  as above.  Also normalize the type to avoid generating duplicate
  declarations due to regions being inconsistently replaced with
  ReStatic elsewhere.
- Do not place the closure type in the self param space when
  translating the unboxed closure callee, etc.  It is not actually
  used, and doing so conflicts with the self substitution from
  default trait methods.

Closes #18661
Closes #18685
  • Loading branch information
bkoropoff committed Nov 7, 2014
1 parent 63c4f22 commit daa215e
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 50 deletions.
8 changes: 4 additions & 4 deletions src/librustc/middle/traits/mod.rs
Expand Up @@ -176,7 +176,7 @@ pub enum Vtable<N> {
/// ID is the ID of the closure expression. This is a `VtableImpl`
/// in spirit, but the impl is generated by the compiler and does
/// not appear in the source.
VtableUnboxedClosure(ast::DefId),
VtableUnboxedClosure(ast::DefId, subst::Substs),

/// Successful resolution to an obligation provided by the caller
/// for some type parameter.
Expand Down Expand Up @@ -338,7 +338,7 @@ impl<N> Vtable<N> {
pub fn iter_nested(&self) -> Items<N> {
match *self {
VtableImpl(ref i) => i.iter_nested(),
VtableUnboxedClosure(_) => (&[]).iter(),
VtableUnboxedClosure(..) => (&[]).iter(),
VtableParam(_) => (&[]).iter(),
VtableBuiltin(ref i) => i.iter_nested(),
}
Expand All @@ -347,7 +347,7 @@ impl<N> Vtable<N> {
pub fn map_nested<M>(&self, op: |&N| -> M) -> Vtable<M> {
match *self {
VtableImpl(ref i) => VtableImpl(i.map_nested(op)),
VtableUnboxedClosure(d) => VtableUnboxedClosure(d),
VtableUnboxedClosure(d, ref s) => VtableUnboxedClosure(d, s.clone()),
VtableParam(ref p) => VtableParam((*p).clone()),
VtableBuiltin(ref i) => VtableBuiltin(i.map_nested(op)),
}
Expand All @@ -356,7 +356,7 @@ impl<N> Vtable<N> {
pub fn map_move_nested<M>(self, op: |N| -> M) -> Vtable<M> {
match self {
VtableImpl(i) => VtableImpl(i.map_move_nested(op)),
VtableUnboxedClosure(d) => VtableUnboxedClosure(d),
VtableUnboxedClosure(d, s) => VtableUnboxedClosure(d, s),
VtableParam(p) => VtableParam(p),
VtableBuiltin(i) => VtableBuiltin(i.map_move_nested(op)),
}
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/middle/traits/select.rs
Expand Up @@ -1558,9 +1558,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Ok(VtableImpl(vtable_impl))
}

UnboxedClosureCandidate(closure_def_id, ref substs) => {
try!(self.confirm_unboxed_closure_candidate(obligation, closure_def_id, substs));
Ok(VtableUnboxedClosure(closure_def_id))
UnboxedClosureCandidate(closure_def_id, substs) => {
try!(self.confirm_unboxed_closure_candidate(obligation, closure_def_id, &substs));
Ok(VtableUnboxedClosure(closure_def_id, substs))
}
}
}
Expand Down
7 changes: 4 additions & 3 deletions src/librustc/middle/traits/util.rs
Expand Up @@ -311,9 +311,10 @@ impl<N:Repr> Repr for super::Vtable<N> {
super::VtableImpl(ref v) =>
v.repr(tcx),

super::VtableUnboxedClosure(ref d) =>
format!("VtableUnboxedClosure({})",
d.repr(tcx)),
super::VtableUnboxedClosure(ref d, ref s) =>
format!("VtableUnboxedClosure({},{})",
d.repr(tcx),
s.repr(tcx)),

super::VtableParam(ref v) =>
format!("VtableParam({})", v.repr(tcx)),
Expand Down
4 changes: 3 additions & 1 deletion src/librustc/middle/trans/callee.rs
Expand Up @@ -490,7 +490,9 @@ pub fn trans_fn_ref_with_substs(
};

// If this is an unboxed closure, redirect to it.
match closure::get_or_create_declaration_if_unboxed_closure(bcx, def_id) {
match closure::get_or_create_declaration_if_unboxed_closure(bcx,
def_id,
&substs) {
None => {}
Some(llfn) => return llfn,
}
Expand Down
15 changes: 11 additions & 4 deletions src/librustc/middle/trans/closure.rs
Expand Up @@ -27,6 +27,7 @@ use middle::trans::monomorphize::MonoId;
use middle::trans::type_of::*;
use middle::trans::type_::Type;
use middle::ty;
use middle::subst::{Subst, Substs};
use util::ppaux::Repr;
use util::ppaux::ty_to_string;

Expand Down Expand Up @@ -420,15 +421,21 @@ pub fn trans_expr_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
/// Returns the LLVM function declaration for an unboxed closure, creating it
/// if necessary. If the ID does not correspond to a closure ID, returns None.
pub fn get_or_create_declaration_if_unboxed_closure<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
closure_id: ast::DefId)
closure_id: ast::DefId,
substs: &Substs)
-> Option<ValueRef> {
let ccx = bcx.ccx();
if !ccx.tcx().unboxed_closures.borrow().contains_key(&closure_id) {
// Not an unboxed closure.
return None
}

let function_type = node_id_type(bcx, closure_id.node);
let function_type = ty::node_id_to_type(bcx.tcx(), closure_id.node);
let function_type = function_type.subst(bcx.tcx(), substs);

// Normalize type so differences in regions and typedefs don't cause
// duplicate declarations
let function_type = ty::normalize_ty(bcx.tcx(), function_type);
let params = match ty::get(function_type).sty {
ty::ty_unboxed_closure(_, _, ref substs) => substs.types.clone(),
_ => unreachable!()
Expand All @@ -447,7 +454,6 @@ pub fn get_or_create_declaration_if_unboxed_closure<'blk, 'tcx>(bcx: Block<'blk,
None => {}
}

let function_type = node_id_type(bcx, closure_id.node);
let symbol = ccx.tcx().map.with_path(closure_id.node, |path| {
mangle_internal_name_by_path_and_seq(path, "unboxed_closure")
});
Expand Down Expand Up @@ -480,7 +486,8 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
let closure_id = ast_util::local_def(id);
let llfn = get_or_create_declaration_if_unboxed_closure(
bcx,
closure_id).unwrap();
closure_id,
&bcx.fcx.param_substs.substs).unwrap();

let unboxed_closures = bcx.tcx().unboxed_closures.borrow();
let function_type = (*unboxed_closures)[closure_id]
Expand Down
47 changes: 13 additions & 34 deletions src/librustc/middle/trans/meth.rs
Expand Up @@ -355,16 +355,13 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,

Callee { bcx: bcx, data: Fn(llfn) }
}
traits::VtableUnboxedClosure(closure_def_id) => {
let self_ty = node_id_type(bcx, closure_def_id.node);
let callee_substs = get_callee_substitutions_for_unboxed_closure(
bcx,
self_ty);

traits::VtableUnboxedClosure(closure_def_id, substs) => {
// The substitutions should have no type parameters remaining
// after passing through fulfill_obligation
let llfn = trans_fn_ref_with_substs(bcx,
closure_def_id,
MethodCall(method_call),
callee_substs);
substs);

Callee {
bcx: bcx,
Expand Down Expand Up @@ -518,24 +515,6 @@ pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
};
}

/// Looks up the substitutions for an unboxed closure and adds the
/// self type
fn get_callee_substitutions_for_unboxed_closure(bcx: Block,
self_ty: ty::t)
-> subst::Substs {
match ty::get(self_ty).sty {
ty::ty_unboxed_closure(_, _, ref substs) => {
substs.with_self_ty(ty::mk_rptr(bcx.tcx(),
ty::ReStatic,
ty::mt {
ty: self_ty,
mutbl: ast::MutMutable,
}))
},
_ => unreachable!()
}
}

/// Creates a returns a dynamic vtable for the given type and vtable origin.
/// This is used only for objects.
///
Expand Down Expand Up @@ -580,19 +559,19 @@ pub fn get_vtable(bcx: Block,
nested: _ }) => {
emit_vtable_methods(bcx, id, substs).into_iter()
}
traits::VtableUnboxedClosure(closure_def_id) => {
let self_ty = node_id_type(bcx, closure_def_id.node);

let callee_substs =
get_callee_substitutions_for_unboxed_closure(
bcx,
self_ty.clone());
traits::VtableUnboxedClosure(closure_def_id, substs) => {
// Look up closure type
let self_ty = ty::node_id_to_type(bcx.tcx(), closure_def_id.node);
// Apply substitutions from closure param environment.
// The substitutions should have no type parameters
// remaining after passing through fulfill_obligation
let self_ty = self_ty.subst(bcx.tcx(), &substs);

let mut llfn = trans_fn_ref_with_substs(
bcx,
closure_def_id,
ExprId(0),
callee_substs.clone());
substs.clone());

{
let unboxed_closures = bcx.tcx()
Expand Down Expand Up @@ -645,7 +624,7 @@ pub fn get_vtable(bcx: Block,
llfn,
&closure_type,
closure_def_id,
callee_substs);
substs);
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/librustc/middle/ty_fold.rs
Expand Up @@ -414,7 +414,9 @@ impl<N:TypeFoldable> TypeFoldable for traits::Vtable<N> {
fn fold_with<'tcx, F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::Vtable<N> {
match *self {
traits::VtableImpl(ref v) => traits::VtableImpl(v.fold_with(folder)),
traits::VtableUnboxedClosure(d) => traits::VtableUnboxedClosure(d),
traits::VtableUnboxedClosure(d, ref s) => {
traits::VtableUnboxedClosure(d, s.fold_with(folder))
}
traits::VtableParam(ref p) => traits::VtableParam(p.fold_with(folder)),
traits::VtableBuiltin(ref d) => traits::VtableBuiltin(d.fold_with(folder)),
}
Expand Down

0 comments on commit daa215e

Please sign in to comment.