Skip to content

Commit daa215e

Browse files
committed
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 rust-lang#18661 Closes rust-lang#18685
1 parent 63c4f22 commit daa215e

File tree

7 files changed

+41
-50
lines changed

7 files changed

+41
-50
lines changed

src/librustc/middle/traits/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ pub enum Vtable<N> {
176176
/// ID is the ID of the closure expression. This is a `VtableImpl`
177177
/// in spirit, but the impl is generated by the compiler and does
178178
/// not appear in the source.
179-
VtableUnboxedClosure(ast::DefId),
179+
VtableUnboxedClosure(ast::DefId, subst::Substs),
180180

181181
/// Successful resolution to an obligation provided by the caller
182182
/// for some type parameter.
@@ -338,7 +338,7 @@ impl<N> Vtable<N> {
338338
pub fn iter_nested(&self) -> Items<N> {
339339
match *self {
340340
VtableImpl(ref i) => i.iter_nested(),
341-
VtableUnboxedClosure(_) => (&[]).iter(),
341+
VtableUnboxedClosure(..) => (&[]).iter(),
342342
VtableParam(_) => (&[]).iter(),
343343
VtableBuiltin(ref i) => i.iter_nested(),
344344
}
@@ -347,7 +347,7 @@ impl<N> Vtable<N> {
347347
pub fn map_nested<M>(&self, op: |&N| -> M) -> Vtable<M> {
348348
match *self {
349349
VtableImpl(ref i) => VtableImpl(i.map_nested(op)),
350-
VtableUnboxedClosure(d) => VtableUnboxedClosure(d),
350+
VtableUnboxedClosure(d, ref s) => VtableUnboxedClosure(d, s.clone()),
351351
VtableParam(ref p) => VtableParam((*p).clone()),
352352
VtableBuiltin(ref i) => VtableBuiltin(i.map_nested(op)),
353353
}
@@ -356,7 +356,7 @@ impl<N> Vtable<N> {
356356
pub fn map_move_nested<M>(self, op: |N| -> M) -> Vtable<M> {
357357
match self {
358358
VtableImpl(i) => VtableImpl(i.map_move_nested(op)),
359-
VtableUnboxedClosure(d) => VtableUnboxedClosure(d),
359+
VtableUnboxedClosure(d, s) => VtableUnboxedClosure(d, s),
360360
VtableParam(p) => VtableParam(p),
361361
VtableBuiltin(i) => VtableBuiltin(i.map_move_nested(op)),
362362
}

src/librustc/middle/traits/select.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1558,9 +1558,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15581558
Ok(VtableImpl(vtable_impl))
15591559
}
15601560

1561-
UnboxedClosureCandidate(closure_def_id, ref substs) => {
1562-
try!(self.confirm_unboxed_closure_candidate(obligation, closure_def_id, substs));
1563-
Ok(VtableUnboxedClosure(closure_def_id))
1561+
UnboxedClosureCandidate(closure_def_id, substs) => {
1562+
try!(self.confirm_unboxed_closure_candidate(obligation, closure_def_id, &substs));
1563+
Ok(VtableUnboxedClosure(closure_def_id, substs))
15641564
}
15651565
}
15661566
}

src/librustc/middle/traits/util.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -311,9 +311,10 @@ impl<N:Repr> Repr for super::Vtable<N> {
311311
super::VtableImpl(ref v) =>
312312
v.repr(tcx),
313313

314-
super::VtableUnboxedClosure(ref d) =>
315-
format!("VtableUnboxedClosure({})",
316-
d.repr(tcx)),
314+
super::VtableUnboxedClosure(ref d, ref s) =>
315+
format!("VtableUnboxedClosure({},{})",
316+
d.repr(tcx),
317+
s.repr(tcx)),
317318

318319
super::VtableParam(ref v) =>
319320
format!("VtableParam({})", v.repr(tcx)),

src/librustc/middle/trans/callee.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,9 @@ pub fn trans_fn_ref_with_substs(
490490
};
491491

492492
// If this is an unboxed closure, redirect to it.
493-
match closure::get_or_create_declaration_if_unboxed_closure(bcx, def_id) {
493+
match closure::get_or_create_declaration_if_unboxed_closure(bcx,
494+
def_id,
495+
&substs) {
494496
None => {}
495497
Some(llfn) => return llfn,
496498
}

src/librustc/middle/trans/closure.rs

+11-4
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use middle::trans::monomorphize::MonoId;
2727
use middle::trans::type_of::*;
2828
use middle::trans::type_::Type;
2929
use middle::ty;
30+
use middle::subst::{Subst, Substs};
3031
use util::ppaux::Repr;
3132
use util::ppaux::ty_to_string;
3233

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

431-
let function_type = node_id_type(bcx, closure_id.node);
433+
let function_type = ty::node_id_to_type(bcx.tcx(), closure_id.node);
434+
let function_type = function_type.subst(bcx.tcx(), substs);
435+
436+
// Normalize type so differences in regions and typedefs don't cause
437+
// duplicate declarations
438+
let function_type = ty::normalize_ty(bcx.tcx(), function_type);
432439
let params = match ty::get(function_type).sty {
433440
ty::ty_unboxed_closure(_, _, ref substs) => substs.types.clone(),
434441
_ => unreachable!()
@@ -447,7 +454,6 @@ pub fn get_or_create_declaration_if_unboxed_closure<'blk, 'tcx>(bcx: Block<'blk,
447454
None => {}
448455
}
449456

450-
let function_type = node_id_type(bcx, closure_id.node);
451457
let symbol = ccx.tcx().map.with_path(closure_id.node, |path| {
452458
mangle_internal_name_by_path_and_seq(path, "unboxed_closure")
453459
});
@@ -480,7 +486,8 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
480486
let closure_id = ast_util::local_def(id);
481487
let llfn = get_or_create_declaration_if_unboxed_closure(
482488
bcx,
483-
closure_id).unwrap();
489+
closure_id,
490+
&bcx.fcx.param_substs.substs).unwrap();
484491

485492
let unboxed_closures = bcx.tcx().unboxed_closures.borrow();
486493
let function_type = (*unboxed_closures)[closure_id]

src/librustc/middle/trans/meth.rs

+13-34
Original file line numberDiff line numberDiff line change
@@ -355,16 +355,13 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
355355

356356
Callee { bcx: bcx, data: Fn(llfn) }
357357
}
358-
traits::VtableUnboxedClosure(closure_def_id) => {
359-
let self_ty = node_id_type(bcx, closure_def_id.node);
360-
let callee_substs = get_callee_substitutions_for_unboxed_closure(
361-
bcx,
362-
self_ty);
363-
358+
traits::VtableUnboxedClosure(closure_def_id, substs) => {
359+
// The substitutions should have no type parameters remaining
360+
// after passing through fulfill_obligation
364361
let llfn = trans_fn_ref_with_substs(bcx,
365362
closure_def_id,
366363
MethodCall(method_call),
367-
callee_substs);
364+
substs);
368365

369366
Callee {
370367
bcx: bcx,
@@ -518,24 +515,6 @@ pub fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
518515
};
519516
}
520517

521-
/// Looks up the substitutions for an unboxed closure and adds the
522-
/// self type
523-
fn get_callee_substitutions_for_unboxed_closure(bcx: Block,
524-
self_ty: ty::t)
525-
-> subst::Substs {
526-
match ty::get(self_ty).sty {
527-
ty::ty_unboxed_closure(_, _, ref substs) => {
528-
substs.with_self_ty(ty::mk_rptr(bcx.tcx(),
529-
ty::ReStatic,
530-
ty::mt {
531-
ty: self_ty,
532-
mutbl: ast::MutMutable,
533-
}))
534-
},
535-
_ => unreachable!()
536-
}
537-
}
538-
539518
/// Creates a returns a dynamic vtable for the given type and vtable origin.
540519
/// This is used only for objects.
541520
///
@@ -580,19 +559,19 @@ pub fn get_vtable(bcx: Block,
580559
nested: _ }) => {
581560
emit_vtable_methods(bcx, id, substs).into_iter()
582561
}
583-
traits::VtableUnboxedClosure(closure_def_id) => {
584-
let self_ty = node_id_type(bcx, closure_def_id.node);
585-
586-
let callee_substs =
587-
get_callee_substitutions_for_unboxed_closure(
588-
bcx,
589-
self_ty.clone());
562+
traits::VtableUnboxedClosure(closure_def_id, substs) => {
563+
// Look up closure type
564+
let self_ty = ty::node_id_to_type(bcx.tcx(), closure_def_id.node);
565+
// Apply substitutions from closure param environment.
566+
// The substitutions should have no type parameters
567+
// remaining after passing through fulfill_obligation
568+
let self_ty = self_ty.subst(bcx.tcx(), &substs);
590569

591570
let mut llfn = trans_fn_ref_with_substs(
592571
bcx,
593572
closure_def_id,
594573
ExprId(0),
595-
callee_substs.clone());
574+
substs.clone());
596575

597576
{
598577
let unboxed_closures = bcx.tcx()
@@ -645,7 +624,7 @@ pub fn get_vtable(bcx: Block,
645624
llfn,
646625
&closure_type,
647626
closure_def_id,
648-
callee_substs);
627+
substs);
649628
}
650629
}
651630

src/librustc/middle/ty_fold.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,9 @@ impl<N:TypeFoldable> TypeFoldable for traits::Vtable<N> {
414414
fn fold_with<'tcx, F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::Vtable<N> {
415415
match *self {
416416
traits::VtableImpl(ref v) => traits::VtableImpl(v.fold_with(folder)),
417-
traits::VtableUnboxedClosure(d) => traits::VtableUnboxedClosure(d),
417+
traits::VtableUnboxedClosure(d, ref s) => {
418+
traits::VtableUnboxedClosure(d, s.fold_with(folder))
419+
}
418420
traits::VtableParam(ref p) => traits::VtableParam(p.fold_with(folder)),
419421
traits::VtableBuiltin(ref d) => traits::VtableBuiltin(d.fold_with(folder)),
420422
}

0 commit comments

Comments
 (0)