stop using the closure_kinds
query / table for anything
Closure Kind is now extracted from the closure substs exclusively.
This commit is contained in:
parent
716f75b1b8
commit
2dff9a49e5
@ -1463,26 +1463,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
!traits::type_known_to_meet_bound(self, param_env, ty, copy_def_id, span)
|
||||
}
|
||||
|
||||
/// Obtains the latest type of the given closure; this may be a
|
||||
/// closure in the current function, in which case its
|
||||
/// `ClosureKind` may not yet be known.
|
||||
pub fn closure_kind(&self,
|
||||
def_id: DefId)
|
||||
closure_def_id: DefId,
|
||||
closure_substs: ty::ClosureSubsts<'tcx>)
|
||||
-> Option<ty::ClosureKind>
|
||||
{
|
||||
if let Some(tables) = self.in_progress_tables {
|
||||
if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
|
||||
let hir_id = self.tcx.hir.node_to_hir_id(id);
|
||||
return tables.borrow()
|
||||
.closure_kinds()
|
||||
.get(hir_id)
|
||||
.cloned()
|
||||
.map(|(kind, _)| kind);
|
||||
}
|
||||
}
|
||||
|
||||
// During typeck, ALL closures are local. But afterwards,
|
||||
// during trans, we see closure ids from other traits.
|
||||
// That may require loading the closure data out of the
|
||||
// cstore.
|
||||
Some(self.tcx.closure_kind(def_id))
|
||||
let closure_kind_ty = closure_substs.closure_kind_ty(closure_def_id, self.tcx);
|
||||
let closure_kind_ty = self.shallow_resolve(&closure_kind_ty);
|
||||
closure_kind_ty.to_opt_closure_kind()
|
||||
}
|
||||
|
||||
/// Obtain the signature of a function or closure.
|
||||
|
@ -750,10 +750,19 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
|
||||
let kind = match self.node_ty(fn_hir_id)?.sty {
|
||||
ty::TyGenerator(..) => ty::ClosureKind::FnOnce,
|
||||
ty::TyClosure(..) => {
|
||||
match self.tables.closure_kinds().get(fn_hir_id) {
|
||||
Some(&(kind, _)) => kind,
|
||||
None => span_bug!(span, "missing closure kind"),
|
||||
ty::TyClosure(closure_def_id, closure_substs) => {
|
||||
match self.infcx {
|
||||
// During upvar inference we may not know the
|
||||
// closure kind, just use `Fn`.
|
||||
Some(infcx) =>
|
||||
infcx.closure_kind(closure_def_id, closure_substs)
|
||||
.unwrap_or(ty::ClosureKind::Fn),
|
||||
|
||||
None =>
|
||||
self.tcx.global_tcx()
|
||||
.lift(&closure_substs)
|
||||
.expect("no inference cx, but inference variables in closure ty")
|
||||
.closure_kind(closure_def_id, self.tcx.global_tcx())
|
||||
}
|
||||
}
|
||||
ref t => span_bug!(span, "unexpected type for fn in mem_categorization: {:?}", t),
|
||||
|
@ -643,8 +643,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
violations)
|
||||
}
|
||||
|
||||
ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => {
|
||||
let found_kind = self.closure_kind(closure_def_id).unwrap();
|
||||
ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
|
||||
let found_kind = self.closure_kind(closure_def_id, closure_substs).unwrap();
|
||||
let closure_span = self.tcx.hir.span_if_local(closure_def_id).unwrap();
|
||||
let node_id = self.tcx.hir.as_local_node_id(closure_def_id).unwrap();
|
||||
let mut err = struct_span_err!(
|
||||
|
@ -439,7 +439,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
|
||||
}
|
||||
|
||||
ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
|
||||
match closure_substs.opt_closure_kind(closure_def_id, selcx.tcx()) {
|
||||
match selcx.infcx().closure_kind(closure_def_id, closure_substs) {
|
||||
Some(closure_kind) => {
|
||||
if closure_kind.extends(kind) {
|
||||
Ok(Some(vec![]))
|
||||
|
@ -719,7 +719,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
|
||||
match closure_substs.opt_closure_kind(closure_def_id, self.tcx()) {
|
||||
match self.infcx.closure_kind(closure_def_id, closure_substs) {
|
||||
Some(closure_kind) => {
|
||||
if closure_kind.extends(kind) {
|
||||
EvaluatedToOk
|
||||
@ -1593,10 +1593,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
// touch bound regions, they just capture the in-scope
|
||||
// type/region parameters
|
||||
match obligation.self_ty().skip_binder().sty {
|
||||
ty::TyClosure(closure_def_id, _) => {
|
||||
ty::TyClosure(closure_def_id, closure_substs) => {
|
||||
debug!("assemble_unboxed_candidates: kind={:?} obligation={:?}",
|
||||
kind, obligation);
|
||||
match self.infcx.closure_kind(closure_def_id) {
|
||||
match self.infcx.closure_kind(closure_def_id, closure_substs) {
|
||||
Some(closure_kind) => {
|
||||
debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind);
|
||||
if closure_kind.extends(kind) {
|
||||
|
@ -189,7 +189,7 @@ fn resolve_closure<'a, 'tcx>(
|
||||
requested_kind: ty::ClosureKind)
|
||||
-> Instance<'tcx>
|
||||
{
|
||||
let actual_kind = tcx.closure_kind(def_id);
|
||||
let actual_kind = substs.closure_kind(def_id, tcx);
|
||||
|
||||
match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
|
||||
Ok(true) => fn_once_adapter_instance(tcx, def_id, substs),
|
||||
|
@ -290,16 +290,8 @@ impl<'tcx> ClosureSubsts<'tcx> {
|
||||
upvar_kinds.iter().map(|t| t.as_type().expect("upvar should be type"))
|
||||
}
|
||||
|
||||
/// Returns the closure kind for this closure; may return `None`
|
||||
/// if inference has not yet completed.
|
||||
pub fn opt_closure_kind(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>)
|
||||
-> Option<ty::ClosureKind> {
|
||||
let closure_kind_ty = self.closure_kind_ty(def_id, tcx);
|
||||
closure_kind_ty.to_opt_closure_kind()
|
||||
}
|
||||
|
||||
/// Returns the closure kind for this closure; may return `None`
|
||||
/// if inference has not yet completed.
|
||||
/// Returns the closure kind for this closure; may return a type
|
||||
/// variable during inference.
|
||||
pub fn closure_kind_ty(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> Ty<'tcx> {
|
||||
self.split(def_id, tcx).closure_kind_ty
|
||||
}
|
||||
@ -307,9 +299,10 @@ impl<'tcx> ClosureSubsts<'tcx> {
|
||||
|
||||
impl<'tcx> ClosureSubsts<'tcx> {
|
||||
/// Returns the closure kind for this closure; only usable outside
|
||||
/// of an inference context.
|
||||
/// of an inference context, because in that context we know that
|
||||
/// there are no type variables.
|
||||
pub fn closure_kind(self, def_id: DefId, tcx: TyCtxt<'_, 'tcx, 'tcx>) -> ty::ClosureKind {
|
||||
self.opt_closure_kind(def_id, tcx).unwrap()
|
||||
self.split(def_id, tcx).closure_kind_ty.to_opt_closure_kind().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1514,6 +1507,8 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
|
||||
|
||||
TyInfer(_) => None,
|
||||
|
||||
TyError => Some(ty::ClosureKind::Fn),
|
||||
|
||||
_ => bug!("cannot convert type `{:?}` to a closure kind", self),
|
||||
}
|
||||
}
|
||||
|
@ -248,14 +248,18 @@ pub fn closure_self_ty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
let closure_expr_hir_id = tcx.hir.node_to_hir_id(closure_expr_id);
|
||||
let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_hir_id);
|
||||
|
||||
let closure_def_id = tcx.hir.local_def_id(closure_expr_id);
|
||||
let (closure_def_id, closure_substs) = match closure_ty.sty {
|
||||
ty::TyClosure(closure_def_id, closure_substs) => (closure_def_id, closure_substs),
|
||||
_ => bug!("closure expr does not have closure type: {:?}", closure_ty)
|
||||
};
|
||||
|
||||
let region = ty::ReFree(ty::FreeRegion {
|
||||
scope: closure_def_id,
|
||||
bound_region: ty::BoundRegion::BrEnv,
|
||||
});
|
||||
let region = tcx.mk_region(region);
|
||||
|
||||
match tcx.closure_kind(closure_def_id) {
|
||||
match closure_substs.closure_kind_ty(closure_def_id, tcx).to_opt_closure_kind().unwrap() {
|
||||
ty::ClosureKind::Fn =>
|
||||
tcx.mk_ref(region,
|
||||
ty::TypeAndMut { ty: closure_ty,
|
||||
|
@ -511,7 +511,7 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
let sig = tcx.fn_sig(def_id).subst(tcx, substs.substs);
|
||||
|
||||
let env_region = ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrEnv);
|
||||
let env_ty = match tcx.closure_kind(def_id) {
|
||||
let env_ty = match substs.closure_kind(def_id, tcx) {
|
||||
ty::ClosureKind::Fn => tcx.mk_imm_ref(tcx.mk_region(env_region), ty),
|
||||
ty::ClosureKind::FnMut => tcx.mk_mut_ref(tcx.mk_region(env_region), ty),
|
||||
ty::ClosureKind::FnOnce => ty,
|
||||
|
@ -86,7 +86,7 @@ pub fn resolve_closure<'a, 'tcx> (
|
||||
requested_kind: ty::ClosureKind)
|
||||
-> Instance<'tcx>
|
||||
{
|
||||
let actual_kind = tcx.closure_kind(def_id);
|
||||
let actual_kind = substs.closure_kind(def_id, tcx);
|
||||
|
||||
match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
|
||||
Ok(true) => fn_once_adapter_instance(tcx, def_id, substs),
|
||||
|
@ -108,7 +108,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
// Check whether this is a call to a closure where we
|
||||
// haven't yet decided on whether the closure is fn vs
|
||||
// fnmut vs fnonce. If so, we have to defer further processing.
|
||||
if self.closure_kind(def_id).is_none() {
|
||||
if self.closure_kind(def_id, substs).is_none() {
|
||||
let closure_ty = self.fn_sig(def_id).subst(self.tcx, substs.substs);
|
||||
let fn_sig = self.replace_late_bound_regions_with_fresh_var(call_expr.span,
|
||||
infer::FnCall,
|
||||
@ -122,6 +122,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
adjustments,
|
||||
fn_sig,
|
||||
closure_def_id: def_id,
|
||||
closure_substs: substs,
|
||||
});
|
||||
return Some(CallStep::DeferredClosure(fn_sig));
|
||||
}
|
||||
@ -336,6 +337,7 @@ pub struct DeferredCallResolution<'gcx: 'tcx, 'tcx> {
|
||||
adjustments: Vec<Adjustment<'tcx>>,
|
||||
fn_sig: ty::FnSig<'tcx>,
|
||||
closure_def_id: DefId,
|
||||
closure_substs: ty::ClosureSubsts<'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> {
|
||||
@ -344,7 +346,7 @@ impl<'a, 'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> {
|
||||
|
||||
// we should not be invoked until the closure kind has been
|
||||
// determined by upvar inference
|
||||
assert!(fcx.closure_kind(self.closure_def_id).is_some());
|
||||
assert!(fcx.closure_kind(self.closure_def_id, self.closure_substs).is_some());
|
||||
|
||||
// We may now know enough to figure out fn vs fnmut etc.
|
||||
match fcx.try_overloaded_call_traits(self.call_expr,
|
||||
|
@ -107,6 +107,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
let closure_type = self.tcx.mk_closure(expr_def_id, substs);
|
||||
|
||||
if let Some(interior) = interior {
|
||||
self.demand_eqtype(expr.span,
|
||||
ty::ClosureKind::FnOnce.to_ty(self.tcx),
|
||||
substs.closure_kind_ty(expr_def_id, self.tcx));
|
||||
return self.tcx.mk_generator(expr_def_id, substs, interior);
|
||||
}
|
||||
|
||||
@ -135,15 +138,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
opt_kind
|
||||
);
|
||||
|
||||
{
|
||||
let mut tables = self.tables.borrow_mut();
|
||||
tables.closure_tys_mut().insert(expr.hir_id, sig);
|
||||
match opt_kind {
|
||||
Some(kind) => {
|
||||
tables.closure_kinds_mut().insert(expr.hir_id, (kind, None));
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
self.tables.borrow_mut().closure_tys_mut().insert(expr.hir_id, sig);
|
||||
if let Some(kind) = opt_kind {
|
||||
self.tables.borrow_mut().closure_kinds_mut().insert(expr.hir_id, (kind, None));
|
||||
self.demand_eqtype(expr.span,
|
||||
kind.to_ty(self.tcx),
|
||||
substs.closure_kind_ty(expr_def_id, self.tcx));
|
||||
}
|
||||
|
||||
closure_type
|
||||
|
@ -46,7 +46,6 @@ use middle::expr_use_visitor as euv;
|
||||
use middle::mem_categorization as mc;
|
||||
use middle::mem_categorization::Categorization;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::TypeFoldable;
|
||||
use rustc::infer::UpvarRegion;
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
@ -158,40 +157,58 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
});
|
||||
|
||||
{
|
||||
let body_owner_def_id = self.tcx.hir.body_owner_def_id(body.id());
|
||||
let region_scope_tree = &self.tcx.region_scope_tree(body_owner_def_id);
|
||||
let mut delegate = InferBorrowKind {
|
||||
fcx: self,
|
||||
adjust_closure_kinds: FxHashMap(),
|
||||
adjust_upvar_captures: ty::UpvarCaptureMap::default(),
|
||||
};
|
||||
euv::ExprUseVisitor::with_infer(
|
||||
&mut delegate,
|
||||
&self.infcx,
|
||||
self.param_env,
|
||||
region_scope_tree,
|
||||
&self.tables.borrow(),
|
||||
).consume_body(body);
|
||||
|
||||
// Write the adjusted values back into the main tables.
|
||||
if infer_kind {
|
||||
if let Some(kind) = delegate
|
||||
.adjust_closure_kinds
|
||||
.remove(&closure_def_id.to_local())
|
||||
{
|
||||
self.tables
|
||||
.borrow_mut()
|
||||
.closure_kinds_mut()
|
||||
.insert(closure_hir_id, kind);
|
||||
}
|
||||
// Extract the type of the closure.
|
||||
let (def_id, closure_substs) = match self.node_ty(closure_hir_id).sty {
|
||||
ty::TyClosure(def_id, substs) | ty::TyGenerator(def_id, substs, _) => (def_id, substs),
|
||||
ref t => {
|
||||
span_bug!(
|
||||
span,
|
||||
"type of closure expr {:?} is not a closure {:?}",
|
||||
closure_node_id,
|
||||
t
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
let body_owner_def_id = self.tcx.hir.body_owner_def_id(body.id());
|
||||
let region_scope_tree = &self.tcx.region_scope_tree(body_owner_def_id);
|
||||
let mut delegate = InferBorrowKind {
|
||||
fcx: self,
|
||||
adjust_closure_kinds: FxHashMap(),
|
||||
adjust_upvar_captures: ty::UpvarCaptureMap::default(),
|
||||
};
|
||||
euv::ExprUseVisitor::with_infer(
|
||||
&mut delegate,
|
||||
&self.infcx,
|
||||
self.param_env,
|
||||
region_scope_tree,
|
||||
&self.tables.borrow(),
|
||||
).consume_body(body);
|
||||
|
||||
// Write the adjusted values back into the main tables.
|
||||
if infer_kind {
|
||||
let opt_adjusted = delegate.adjust_closure_kinds.remove(&closure_def_id.to_local());
|
||||
let closure_kind_ty = closure_substs.closure_kind_ty(def_id, self.tcx);
|
||||
if let Some((kind, origin)) = opt_adjusted {
|
||||
self.tables
|
||||
.borrow_mut()
|
||||
.closure_kinds_mut()
|
||||
.insert(closure_hir_id, (kind, origin));
|
||||
|
||||
self.demand_eqtype(span, kind.to_ty(self.tcx), closure_kind_ty);
|
||||
} else {
|
||||
// If there are only reads, or no upvars, then the
|
||||
// default of `Fn` will never *have* to be adjusted, so there will be
|
||||
// no entry in the map.
|
||||
self.demand_eqtype(span, ty::ClosureKind::Fn.to_ty(self.tcx), closure_kind_ty);
|
||||
}
|
||||
self.tables
|
||||
.borrow_mut()
|
||||
.upvar_capture_map
|
||||
.extend(delegate.adjust_upvar_captures);
|
||||
}
|
||||
|
||||
self.tables
|
||||
.borrow_mut()
|
||||
.upvar_capture_map
|
||||
.extend(delegate.adjust_upvar_captures);
|
||||
|
||||
// Now that we've analyzed the closure, we know how each
|
||||
// variable is borrowed, and we know what traits the closure
|
||||
// implements (Fn vs FnMut etc). We now have some updates to do
|
||||
@ -204,27 +221,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
// C, then the type would have infinite size (and the
|
||||
// inference algorithm will reject it).
|
||||
|
||||
// Extract the type variables UV0...UVn.
|
||||
let (def_id, closure_substs) = match self.node_ty(closure_hir_id).sty {
|
||||
ty::TyClosure(def_id, substs) | ty::TyGenerator(def_id, substs, _) => (def_id, substs),
|
||||
ref t => {
|
||||
span_bug!(
|
||||
span,
|
||||
"type of closure expr {:?} is not a closure {:?}",
|
||||
closure_node_id,
|
||||
t
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Equate the type variable representing the closure kind.
|
||||
let closure_kind_ty = closure_substs.closure_kind_ty(def_id, self.tcx);
|
||||
if closure_kind_ty.needs_infer() {
|
||||
let final_closure_kind = self.tables.borrow().closure_kinds()[closure_hir_id].0;
|
||||
self.demand_eqtype(span, final_closure_kind.to_ty(self.tcx), closure_kind_ty);
|
||||
}
|
||||
|
||||
// Equate the type variables with the actual types.
|
||||
// Equate the type variables for the upvars with the actual types.
|
||||
let final_upvar_tys = self.final_upvar_tys(closure_node_id);
|
||||
debug!(
|
||||
"analyze_closure: id={:?} closure_substs={:?} final_upvar_tys={:?}",
|
||||
|
@ -19,7 +19,6 @@ struct A (B);
|
||||
|
||||
impl A {
|
||||
pub fn matches<F: Fn()>(&self, f: &F) {
|
||||
//~^ ERROR reached the recursion limit while instantiating `A::matches::<[closure
|
||||
let &A(ref term) = self;
|
||||
term.matches(f);
|
||||
}
|
||||
@ -59,6 +58,7 @@ struct D (Box<A>);
|
||||
|
||||
impl D {
|
||||
pub fn matches<F: Fn()>(&self, f: &F) {
|
||||
//~^ ERROR reached the type-length limit while instantiating `D::matches::<[closure
|
||||
let &D(ref a) = self;
|
||||
a.matches(f)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user