Fix handling of unboxed closure type param substitutions
- 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
This commit is contained in:
parent
63c4f22f2b
commit
daa215e8c5
7 changed files with 41 additions and 50 deletions
|
@ -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.
|
||||
|
@ -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(),
|
||||
}
|
||||
|
@ -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)),
|
||||
}
|
||||
|
@ -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)),
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)),
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -420,7 +421,8 @@ 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) {
|
||||
|
@ -428,7 +430,12 @@ pub fn get_or_create_declaration_if_unboxed_closure<'blk, 'tcx>(bcx: Block<'blk,
|
|||
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!()
|
||||
|
@ -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")
|
||||
});
|
||||
|
@ -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]
|
||||
|
|
|
@ -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,
|
||||
|
@ -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.
|
||||
///
|
||||
|
@ -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()
|
||||
|
@ -645,7 +624,7 @@ pub fn get_vtable(bcx: Block,
|
|||
llfn,
|
||||
&closure_type,
|
||||
closure_def_id,
|
||||
callee_substs);
|
||||
substs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)),
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue