Skip to content

Commit 1e3214b

Browse files
committed
Normalize the associated types in closure and closure upvar types.
1 parent 78f848c commit 1e3214b

File tree

8 files changed

+145
-44
lines changed

8 files changed

+145
-44
lines changed

src/librustc/middle/traits/select.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1781,6 +1781,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
17811781
substs.repr(self.tcx()));
17821782

17831783
let closure_type = self.closure_typer.unboxed_closure_type(closure_def_id, substs);
1784+
1785+
debug!("confirm_unboxed_closure_candidate: closure_def_id={} closure_type={}",
1786+
closure_def_id.repr(self.tcx()),
1787+
closure_type.repr(self.tcx()));
1788+
17841789
let closure_sig = &closure_type.sig;
17851790
let arguments_tuple = closure_sig.0.inputs[0];
17861791
let trait_substs =

src/librustc/middle/ty.rs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5665,7 +5665,7 @@ pub fn tup_fields<'tcx>(v: &[Ty<'tcx>]) -> Vec<field<'tcx>> {
56655665
}).collect()
56665666
}
56675667

5668-
#[deriving(Copy)]
5668+
#[deriving(Copy, Clone)]
56695669
pub struct UnboxedClosureUpvar<'tcx> {
56705670
pub def: def::Def,
56715671
pub span: Span,
@@ -7099,12 +7099,30 @@ pub trait HasProjectionTypes {
70997099
fn has_projection_types(&self) -> bool;
71007100
}
71017101

7102+
impl<'tcx,T:HasProjectionTypes> HasProjectionTypes for Vec<T> {
7103+
fn has_projection_types(&self) -> bool {
7104+
self.iter().any(|p| p.has_projection_types())
7105+
}
7106+
}
7107+
71027108
impl<'tcx,T:HasProjectionTypes> HasProjectionTypes for VecPerParamSpace<T> {
71037109
fn has_projection_types(&self) -> bool {
71047110
self.iter().any(|p| p.has_projection_types())
71057111
}
71067112
}
71077113

7114+
impl<'tcx> HasProjectionTypes for ClosureTy<'tcx> {
7115+
fn has_projection_types(&self) -> bool {
7116+
self.sig.has_projection_types()
7117+
}
7118+
}
7119+
7120+
impl<'tcx> HasProjectionTypes for UnboxedClosureUpvar<'tcx> {
7121+
fn has_projection_types(&self) -> bool {
7122+
self.ty.has_projection_types()
7123+
}
7124+
}
7125+
71087126
impl<'tcx> HasProjectionTypes for ty::GenericBounds<'tcx> {
71097127
fn has_projection_types(&self) -> bool {
71107128
self.predicates.has_projection_types()
@@ -7304,3 +7322,23 @@ impl ReferencesError for Region
73047322
false
73057323
}
73067324
}
7325+
7326+
impl<'tcx> Repr<'tcx> for ClosureTy<'tcx> {
7327+
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
7328+
format!("ClosureTy({},{},{},{},{},{})",
7329+
self.unsafety,
7330+
self.onceness,
7331+
self.store,
7332+
self.bounds.repr(tcx),
7333+
self.sig.repr(tcx),
7334+
self.abi)
7335+
}
7336+
}
7337+
7338+
impl<'tcx> Repr<'tcx> for UnboxedClosureUpvar<'tcx> {
7339+
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
7340+
format!("UnboxedClosureUpvar({},{})",
7341+
self.def.repr(tcx),
7342+
self.ty.repr(tcx))
7343+
}
7344+
}

src/librustc/middle/ty_fold.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,16 @@ impl<'tcx,T,U> TypeFoldable<'tcx> for ty::OutlivesPredicate<T,U>
532532
}
533533
}
534534

535+
impl<'tcx> TypeFoldable<'tcx> for ty::UnboxedClosureUpvar<'tcx> {
536+
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::UnboxedClosureUpvar<'tcx> {
537+
ty::UnboxedClosureUpvar {
538+
def: self.def,
539+
span: self.span,
540+
ty: self.ty.fold_with(folder),
541+
}
542+
}
543+
}
544+
535545
///////////////////////////////////////////////////////////////////////////
536546
// "super" routines: these are the default implementations for TypeFolder.
537547
//

src/librustc_trans/trans/base.rs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
4343
use middle::subst;
4444
use middle::weak_lang_items;
4545
use middle::subst::{Subst, Substs};
46-
use middle::ty::{mod, Ty};
46+
use middle::ty::{mod, Ty, UnboxedClosureTyper};
4747
use session::config::{mod, NoDebugInfo, FullDebugInfo};
4848
use session::Session;
4949
use trans::_match;
@@ -257,12 +257,12 @@ fn get_extern_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<'tcx>,
257257
}
258258

259259
pub fn self_type_for_unboxed_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
260-
closure_id: ast::DefId,
261-
fn_ty: Ty<'tcx>)
262-
-> Ty<'tcx> {
263-
let unboxed_closures = ccx.tcx().unboxed_closures.borrow();
264-
let unboxed_closure = &(*unboxed_closures)[closure_id];
265-
match unboxed_closure.kind {
260+
closure_id: ast::DefId,
261+
fn_ty: Ty<'tcx>)
262+
-> Ty<'tcx>
263+
{
264+
let unboxed_closure_kind = ccx.tcx().unboxed_closure_kind(closure_id);
265+
match unboxed_closure_kind {
266266
ty::FnUnboxedClosureKind => {
267267
ty::mk_imm_rptr(ccx.tcx(), ccx.tcx().mk_region(ty::ReStatic), fn_ty)
268268
}
@@ -291,13 +291,15 @@ pub fn decl_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
291291
(f.sig.0.inputs.clone(), f.sig.0.output, f.abi, Some(Type::i8p(ccx)))
292292
}
293293
ty::ty_unboxed_closure(closure_did, _, substs) => {
294-
let unboxed_closures = ccx.tcx().unboxed_closures.borrow();
295-
let unboxed_closure = &(*unboxed_closures)[closure_did];
296-
let function_type = unboxed_closure.closure_type.clone();
294+
let typer = common::NormalizingUnboxedClosureTyper::new(ccx.tcx());
295+
let function_type = typer.unboxed_closure_type(closure_did, substs);
297296
let self_type = self_type_for_unboxed_closure(ccx, closure_did, fn_ty);
298297
let llenvironment_type = type_of_explicit_arg(ccx, self_type);
299-
(function_type.sig.0.inputs.iter().map(|t| t.subst(ccx.tcx(), substs)).collect(),
300-
function_type.sig.0.output.subst(ccx.tcx(), substs),
298+
debug!("decl_rust_fn: function_type={} self_type={}",
299+
function_type.repr(ccx.tcx()),
300+
self_type.repr(ccx.tcx()));
301+
(function_type.sig.0.inputs,
302+
function_type.sig.0.output,
301303
RustCall,
302304
Some(llenvironment_type))
303305
}
@@ -2436,11 +2438,9 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<
24362438
ty::ty_closure(ref f) => (f.sig.clone(), f.abi, true),
24372439
ty::ty_bare_fn(_, ref f) => (f.sig.clone(), f.abi, false),
24382440
ty::ty_unboxed_closure(closure_did, _, substs) => {
2439-
let unboxed_closures = ccx.tcx().unboxed_closures.borrow();
2440-
let ref function_type = (*unboxed_closures)[closure_did]
2441-
.closure_type;
2442-
2443-
(function_type.sig.subst(ccx.tcx(), substs), RustCall, true)
2441+
let typer = common::NormalizingUnboxedClosureTyper::new(ccx.tcx());
2442+
let function_type = typer.unboxed_closure_type(closure_did, substs);
2443+
(function_type.sig, RustCall, true)
24442444
}
24452445
_ => ccx.sess().bug("expected closure or function.")
24462446
};

src/librustc_trans/trans/closure.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ use trans::common::*;
2222
use trans::datum::{Datum, DatumBlock, Expr, Lvalue, rvalue_scratch_datum};
2323
use trans::debuginfo;
2424
use trans::expr;
25-
use trans::monomorphize::MonoId;
25+
use trans::monomorphize::{mod, MonoId};
2626
use trans::type_of::*;
2727
use trans::type_::Type;
28-
use middle::ty::{mod, Ty};
29-
use middle::subst::{Subst, Substs};
28+
use middle::ty::{mod, Ty, UnboxedClosureTyper};
29+
use middle::subst::{Substs};
3030
use session::config::FullDebugInfo;
3131
use util::ppaux::Repr;
3232
use util::ppaux::ty_to_string;
@@ -464,7 +464,7 @@ pub fn get_or_create_declaration_if_unboxed_closure<'blk, 'tcx>(bcx: Block<'blk,
464464
}
465465

466466
let function_type = ty::node_id_to_type(bcx.tcx(), closure_id.node);
467-
let function_type = function_type.subst(bcx.tcx(), substs);
467+
let function_type = monomorphize::apply_param_substs(bcx.tcx(), substs, &function_type);
468468

469469
// Normalize type so differences in regions and typedefs don't cause
470470
// duplicate declarations
@@ -511,7 +511,8 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
511511
body: &ast::Block,
512512
id: ast::NodeId,
513513
dest: expr::Dest)
514-
-> Block<'blk, 'tcx> {
514+
-> Block<'blk, 'tcx>
515+
{
515516
let _icx = push_ctxt("closure::trans_unboxed_closure");
516517

517518
debug!("trans_unboxed_closure()");
@@ -522,9 +523,13 @@ pub fn trans_unboxed_closure<'blk, 'tcx>(
522523
closure_id,
523524
bcx.fcx.param_substs).unwrap();
524525

525-
let function_type = (*bcx.tcx().unboxed_closures.borrow())[closure_id]
526-
.closure_type
527-
.clone();
526+
// Get the type of this closure. Use the current `param_substs` as
527+
// the closure substitutions. This makes sense because the closure
528+
// takes the same set of type arguments as the enclosing fn, and
529+
// this function (`trans_unboxed_closure`) is invoked at the point
530+
// of the closure expression.
531+
let typer = NormalizingUnboxedClosureTyper::new(bcx.tcx());
532+
let function_type = typer.unboxed_closure_type(closure_id, bcx.fcx.param_substs);
528533
let function_type = ty::mk_closure(bcx.tcx(), function_type);
529534

530535
let freevars: Vec<ty::Freevar> =

src/librustc_trans/trans/common.rs

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -632,27 +632,26 @@ impl<'blk, 'tcx> ty::UnboxedClosureTyper<'tcx> for BlockS<'blk, 'tcx> {
632632
def_id: ast::DefId)
633633
-> ty::UnboxedClosureKind
634634
{
635-
self.tcx().unboxed_closure_kind(def_id)
635+
let typer = NormalizingUnboxedClosureTyper::new(self.tcx());
636+
typer.unboxed_closure_kind(def_id)
636637
}
637638

638639
fn unboxed_closure_type(&self,
639640
def_id: ast::DefId,
640641
substs: &subst::Substs<'tcx>)
641642
-> ty::ClosureTy<'tcx>
642643
{
643-
// the substitutions in `substs` are already monomorphized, so we can
644-
// ignore `param_substs`
645-
self.tcx().unboxed_closure_type(def_id, substs)
644+
let typer = NormalizingUnboxedClosureTyper::new(self.tcx());
645+
typer.unboxed_closure_type(def_id, substs)
646646
}
647647

648648
fn unboxed_closure_upvars(&self,
649649
def_id: ast::DefId,
650650
substs: &Substs<'tcx>)
651651
-> Option<Vec<ty::UnboxedClosureUpvar<'tcx>>>
652652
{
653-
// the substitutions in `substs` are already monomorphized, so we can
654-
// ignore `param_substs`
655-
ty::unboxed_closure_upvars(self.tcx(), def_id, substs)
653+
let typer = NormalizingUnboxedClosureTyper::new(self.tcx());
654+
typer.unboxed_closure_upvars(def_id, substs)
656655
}
657656
}
658657

@@ -948,7 +947,8 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
948947

949948
// Do the initial selection for the obligation. This yields the
950949
// shallow result we are looking for -- that is, what specific impl.
951-
let mut selcx = traits::SelectionContext::new(&infcx, &param_env, tcx);
950+
let typer = NormalizingUnboxedClosureTyper::new(infcx.tcx);
951+
let mut selcx = traits::SelectionContext::new(&infcx, &param_env, &typer);
952952
let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
953953
trait_ref.to_poly_trait_predicate());
954954
let selection = match selcx.select(&obligation) {
@@ -992,6 +992,47 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
992992
vtable
993993
}
994994

995+
pub struct NormalizingUnboxedClosureTyper<'a,'tcx:'a> {
996+
tcx: &'a ty::ctxt<'tcx>
997+
}
998+
999+
impl<'a,'tcx> NormalizingUnboxedClosureTyper<'a,'tcx> {
1000+
pub fn new(tcx: &'a ty::ctxt<'tcx>) -> NormalizingUnboxedClosureTyper<'a,'tcx> {
1001+
NormalizingUnboxedClosureTyper { tcx: tcx }
1002+
}
1003+
}
1004+
1005+
impl<'a,'tcx> ty::UnboxedClosureTyper<'tcx> for NormalizingUnboxedClosureTyper<'a,'tcx> {
1006+
fn unboxed_closure_kind(&self,
1007+
def_id: ast::DefId)
1008+
-> ty::UnboxedClosureKind
1009+
{
1010+
self.tcx.unboxed_closure_kind(def_id)
1011+
}
1012+
1013+
fn unboxed_closure_type(&self,
1014+
def_id: ast::DefId,
1015+
substs: &subst::Substs<'tcx>)
1016+
-> ty::ClosureTy<'tcx>
1017+
{
1018+
// the substitutions in `substs` are already monomorphized,
1019+
// but we still must normalize associated types
1020+
let closure_ty = self.tcx.unboxed_closure_type(def_id, substs);
1021+
monomorphize::normalize_associated_type(self.tcx, &closure_ty)
1022+
}
1023+
1024+
fn unboxed_closure_upvars(&self,
1025+
def_id: ast::DefId,
1026+
substs: &Substs<'tcx>)
1027+
-> Option<Vec<ty::UnboxedClosureUpvar<'tcx>>>
1028+
{
1029+
// the substitutions in `substs` are already monomorphized,
1030+
// but we still must normalize associated types
1031+
let result = ty::unboxed_closure_upvars(self.tcx, def_id, substs);
1032+
monomorphize::normalize_associated_type(self.tcx, &result)
1033+
}
1034+
}
1035+
9951036
pub fn drain_fulfillment_cx<'a,'tcx,T>(span: Span,
9961037
infcx: &infer::InferCtxt<'a,'tcx>,
9971038
param_env: &ty::ParameterEnvironment<'tcx>,
@@ -1006,7 +1047,8 @@ pub fn drain_fulfillment_cx<'a,'tcx,T>(span: Span,
10061047
// In principle, we only need to do this so long as `result`
10071048
// contains unbound type parameters. It could be a slight
10081049
// optimization to stop iterating early.
1009-
match fulfill_cx.select_all_or_error(infcx, param_env, infcx.tcx) {
1050+
let typer = NormalizingUnboxedClosureTyper::new(infcx.tcx);
1051+
match fulfill_cx.select_all_or_error(infcx, param_env, &typer) {
10101052
Ok(()) => { }
10111053
Err(errors) => {
10121054
if errors.iter().all(|e| e.is_overflow()) {

src/librustc_trans/trans/debuginfo.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -194,13 +194,13 @@ use llvm;
194194
use llvm::{ModuleRef, ContextRef, ValueRef};
195195
use llvm::debuginfo::*;
196196
use metadata::csearch;
197-
use middle::subst::{mod, Subst, Substs};
197+
use middle::subst::{mod, Substs};
198198
use trans::{mod, adt, machine, type_of};
199199
use trans::common::*;
200200
use trans::_match::{BindingInfo, TrByCopy, TrByMove, TrByRef};
201201
use trans::monomorphize;
202202
use trans::type_::Type;
203-
use middle::ty::{mod, Ty};
203+
use middle::ty::{mod, Ty, UnboxedClosureTyper};
204204
use middle::pat_util;
205205
use session::config::{mod, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
206206
use util::nodemap::{DefIdMap, NodeMap, FnvHashMap, FnvHashSet};
@@ -470,9 +470,9 @@ impl<'tcx> TypeMap<'tcx> {
470470
closure_ty.clone(),
471471
&mut unique_type_id);
472472
},
473-
ty::ty_unboxed_closure(ref def_id, _, substs) => {
474-
let closure_ty = cx.tcx().unboxed_closures.borrow()
475-
.get(def_id).unwrap().closure_type.subst(cx.tcx(), substs);
473+
ty::ty_unboxed_closure(def_id, _, substs) => {
474+
let typer = NormalizingUnboxedClosureTyper::new(cx.tcx());
475+
let closure_ty = typer.unboxed_closure_type(def_id, substs);
476476
self.get_unique_type_id_of_closure_type(cx,
477477
closure_ty,
478478
&mut unique_type_id);
@@ -3020,9 +3020,9 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
30203020
ty::ty_closure(ref closurety) => {
30213021
subroutine_type_metadata(cx, unique_type_id, &closurety.sig, usage_site_span)
30223022
}
3023-
ty::ty_unboxed_closure(ref def_id, _, substs) => {
3024-
let sig = cx.tcx().unboxed_closures.borrow()
3025-
.get(def_id).unwrap().closure_type.sig.subst(cx.tcx(), substs);
3023+
ty::ty_unboxed_closure(def_id, _, substs) => {
3024+
let typer = NormalizingUnboxedClosureTyper::new(cx.tcx());
3025+
let sig = typer.unboxed_closure_type(def_id, substs).sig;
30263026
subroutine_type_metadata(cx, unique_type_id, &sig, usage_site_span)
30273027
}
30283028
ty::ty_struct(def_id, substs) => {

src/librustc_trans/trans/monomorphize.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,8 @@ pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
323323

324324
let infcx = infer::new_infer_ctxt(tcx);
325325
let param_env = ty::empty_parameter_environment();
326-
let mut selcx = traits::SelectionContext::new(&infcx, &param_env, tcx);
326+
let typer = NormalizingUnboxedClosureTyper::new(infcx.tcx);
327+
let mut selcx = traits::SelectionContext::new(&infcx, &param_env, &typer);
327328
let cause = traits::ObligationCause::dummy();
328329
let traits::Normalized { value: result, obligations } =
329330
traits::normalize(&mut selcx, cause, value);

0 commit comments

Comments
 (0)