address review comments
This commit is contained in:
parent
57950982b2
commit
d394e75ef6
4 changed files with 80 additions and 73 deletions
|
@ -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<Ty<'tcx>> {
|
||||
(0..n).map(|_i| self.next_ty_var()).collect()
|
||||
}
|
||||
|
||||
pub fn next_int_var_id(&self) -> IntVid {
|
||||
self.int_unification_table
|
||||
.borrow_mut()
|
||||
|
|
|
@ -183,6 +183,22 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
|
|||
tcx.intern_substs(&substs)
|
||||
}
|
||||
|
||||
pub fn extend_to<FR, FT>(&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<FR, FT>(substs: &mut Vec<Kind<'tcx>>,
|
||||
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<FR, FT>(substs: &mut Vec<Kind<'tcx>>,
|
||||
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())
|
||||
|
|
|
@ -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("<upvar>"),
|
||||
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<ty::ClosureKind>,
|
||||
|
@ -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);
|
||||
|
|
|
@ -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("<upvar>"),
|
||||
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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue