From d394e75ef6b6b8ea41e62bcbd3023a3e29eb4ee7 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sat, 12 Nov 2016 23:20:02 +0200 Subject: [PATCH] address review comments --- src/librustc/infer/mod.rs | 4 -- src/librustc/ty/subst.rs | 33 ++++++++++---- src/librustc_typeck/check/closure.rs | 66 +++------------------------- src/librustc_typeck/collect.rs | 50 ++++++++++++++++++++- 4 files changed, 80 insertions(+), 73 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 24716c4795134..2d4b36ec18760 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1150,10 +1150,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.tcx.mk_var(self.next_ty_var_id(true)) } - pub fn next_ty_vars(&self, n: usize) -> Vec> { - (0..n).map(|_i| self.next_ty_var()).collect() - } - pub fn next_int_var_id(&self) -> IntVid { self.int_unification_table .borrow_mut() diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 76d512a20b26e..41fcb09fb2dc7 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -183,6 +183,22 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { tcx.intern_substs(&substs) } + pub fn extend_to(&self, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + def_id: DefId, + mut mk_region: FR, + mut mk_type: FT) + -> &'tcx Substs<'tcx> + where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> &'tcx ty::Region, + FT: FnMut(&ty::TypeParameterDef<'tcx>, &[Kind<'tcx>]) -> Ty<'tcx> + { + let defs = tcx.item_generics(def_id); + let mut result = Vec::with_capacity(defs.count()); + result.extend(self[..].iter().cloned()); + Substs::fill_single(&mut result, defs, &mut mk_region, &mut mk_type); + tcx.intern_substs(&result) + } + fn fill_item(substs: &mut Vec>, tcx: TyCtxt<'a, 'gcx, 'tcx>, defs: &ty::Generics<'tcx>, @@ -195,7 +211,15 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { let parent_defs = tcx.item_generics(def_id); Substs::fill_item(substs, tcx, parent_defs, mk_region, mk_type); } + Substs::fill_single(substs, defs, mk_region, mk_type) + } + fn fill_single(substs: &mut Vec>, + defs: &ty::Generics<'tcx>, + mk_region: &mut FR, + mk_type: &mut FT) + where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> &'tcx ty::Region, + FT: FnMut(&ty::TypeParameterDef<'tcx>, &[Kind<'tcx>]) -> Ty<'tcx> { // Handle Self first, before all regions. let mut types = defs.types.iter(); if defs.parent.is_none() && defs.has_self { @@ -275,15 +299,6 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> { tcx.mk_substs(target_substs.iter().chain(&self[defs.own_count()..]).cloned()) } - pub fn extend_with_types(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, - types: &[Ty<'tcx>]) - -> &'tcx Substs<'tcx> { - tcx.mk_substs( - self[..].iter().cloned().chain( - types.iter().map(|a| Kind::from(*a))) - ) - } - pub fn truncate_to(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, generics: &ty::Generics<'tcx>) -> &'tcx Substs<'tcx> { tcx.mk_substs(self.iter().take(generics.count()).cloned()) diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 3efbd6b30c220..75287d4064ae1 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -13,16 +13,11 @@ use super::{check_fn, Expectation, FnCtxt}; use astconv::AstConv; -use rustc::hir::def_id::DefId; use rustc::ty::{self, ToPolyTraitRef, Ty}; -use rustc::ty::subst::Substs; -use rustc::util::common::MemoizationMap; use std::cmp; use syntax::abi::Abi; use rustc::hir; -use syntax::parse::token; - impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn check_expr_closure(&self, expr: &hir::Expr, @@ -45,48 +40,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.check_closure(expr, expected_kind, decl, body, expected_sig) } - fn declare_closure(&self, def_id: DefId) { - let tcx = self.tcx.global_tcx(); - - tcx.generics.memoize(def_id, || { - let node_id = tcx.map.as_local_node_id(def_id).unwrap(); - let base_def_id = self.tcx.closure_base_def_id(def_id); - let base_generics = tcx.item_generics(base_def_id); - - // provide junk type parameter defs - the only place that - // cares about anything but the length is instantiation, - // and we don't do that for closures. - let upvar_decls : Vec<_> = tcx.with_freevars(node_id, |fv| { - fv.iter().enumerate().map(|(i, _)| ty::TypeParameterDef { - index: (base_generics.count() as u32) + (i as u32), - name: token::intern(""), - def_id: def_id, - default_def_id: base_def_id, - default: None, - object_lifetime_default: ty::ObjectLifetimeDefault::BaseDefault, - pure_wrt_drop: false, - }).collect() - }); - - tcx.alloc_generics(ty::Generics { - parent: Some(base_def_id), - parent_regions: base_generics.parent_regions + - (base_generics.regions.len() as u32), - parent_types: base_generics.parent_types + - (base_generics.types.len() as u32), - regions: vec![], - types: upvar_decls, - has_self: false, - }) - }); - - tcx.item_types.memoize(def_id, || tcx.mk_closure(def_id, Substs::for_item( - tcx, def_id, - |def, _| tcx.mk_region(def.to_early_bound_region()), - |def, _| tcx.mk_param_from_def(def) - ))); - } - fn check_closure(&self, expr: &hir::Expr, opt_kind: Option, @@ -99,8 +52,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expected_sig); let expr_def_id = self.tcx.map.local_def_id(expr.id); - self.declare_closure(expr_def_id); - let mut fn_ty = AstConv::ty_of_closure(self, hir::Unsafety::Normal, decl, @@ -110,18 +61,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Create type variables (for now) to represent the transformed // types of upvars. These will be unified during the upvar // inference phase (`upvar.rs`). - let num_upvars = self.tcx.with_freevars(expr.id, |fv| fv.len()); - let upvar_tys = self.next_ty_vars(num_upvars); - - debug!("check_closure: expr.id={:?} upvar_tys={:?}", - expr.id, - upvar_tys); - - let closure_type = self.tcx.mk_closure( - expr_def_id, - self.parameter_environment.free_substs.extend_with_types(self.tcx, &upvar_tys) + let closure_type = self.tcx.mk_closure(expr_def_id, + self.parameter_environment.free_substs.extend_to(self.tcx, expr_def_id, + |_, _| span_bug!(expr.span, "closure has region param"), + |_, _| self.infcx.next_ty_var() + ) ); + debug!("check_closure: expr.id={:?} closure_type={:?}", expr.id, closure_type); + let fn_sig = self.tcx .liberate_late_bound_regions(self.tcx.region_maps.call_site_extent(expr.id, body.id), &fn_ty.sig); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 968d5d73e7a8b..816243b3eab47 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -80,7 +80,7 @@ use std::cell::RefCell; use std::collections::hash_map::Entry::{Occupied, Vacant}; use syntax::{abi, ast, attr}; -use syntax::parse::token::keywords; +use syntax::parse::token::{self, keywords}; use syntax_pos::Span; use rustc::hir::{self, intravisit, map as hir_map, print as pprust}; @@ -134,6 +134,13 @@ impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> intravisit::walk_item(self, item); } + fn visit_expr(&mut self, expr: &hir::Expr) { + if let hir::ExprClosure(..) = expr.node { + convert_closure(self.ccx, expr.id); + } + intravisit::walk_expr(self, expr); + } + fn visit_ty(&mut self, ty: &hir::Ty) { if let hir::TyImplTrait(..) = ty.node { let def_id = self.ccx.tcx.map.local_def_id(ty.id); @@ -559,6 +566,40 @@ fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ccx.tcx.predicates.borrow_mut().insert(def_id, struct_predicates.clone()); } +fn convert_closure<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, + node_id: ast::NodeId) +{ + let tcx = ccx.tcx; + let def_id = tcx.map.local_def_id(node_id); + let base_def_id = tcx.closure_base_def_id(def_id); + let base_generics = generics_of_def_id(ccx, base_def_id); + + // provide junk type parameter defs - the only place that + // cares about anything but the length is instantiation, + // and we don't do that for closures. + let upvar_decls : Vec<_> = tcx.with_freevars(node_id, |fv| { + fv.iter().enumerate().map(|(i, _)| ty::TypeParameterDef { + index: (base_generics.count() as u32) + (i as u32), + name: token::intern(""), + def_id: def_id, + default_def_id: base_def_id, + default: None, + object_lifetime_default: ty::ObjectLifetimeDefault::BaseDefault, + pure_wrt_drop: false, + }).collect() + }); + tcx.generics.borrow_mut().insert(def_id, tcx.alloc_generics(ty::Generics { + parent: Some(base_def_id), + parent_regions: base_generics.parent_regions + (base_generics.regions.len() as u32), + parent_types: base_generics.parent_types + (base_generics.types.len() as u32), + regions: vec![], + types: upvar_decls, + has_self: base_generics.has_self, + })); + + type_of_def_id(ccx, def_id); +} + fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, container: AssociatedItemContainer, id: ast::NodeId, @@ -1504,6 +1545,13 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } } } + NodeExpr(&hir::Expr { node: hir::ExprClosure(..), .. }) => { + ccx.tcx.mk_closure(def_id, Substs::for_item( + ccx.tcx, def_id, + |def, _| ccx.tcx.mk_region(def.to_early_bound_region()), + |def, _| ccx.tcx.mk_param_from_def(def) + )) + } x => { bug!("unexpected sort of node in type_of_def_id(): {:?}", x); }