Skip to content

Commit 3544d88

Browse files
committed
stop using the closure_kinds query / table for anything
Closure Kind is now extracted from the closure substs exclusively.
1 parent a805298 commit 3544d88

File tree

14 files changed

+107
-106
lines changed

14 files changed

+107
-106
lines changed

src/librustc/infer/mod.rs

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,26 +1338,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
13381338
!traits::type_known_to_meet_bound(self, param_env, ty, copy_def_id, span)
13391339
}
13401340

1341+
/// Obtains the latest type of the given closure; this may be a
1342+
/// closure in the current function, in which case its
1343+
/// `ClosureKind` may not yet be known.
13411344
pub fn closure_kind(&self,
1342-
def_id: DefId)
1345+
closure_def_id: DefId,
1346+
closure_substs: ty::ClosureSubsts<'tcx>)
13431347
-> Option<ty::ClosureKind>
13441348
{
1345-
if let Some(tables) = self.in_progress_tables {
1346-
if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
1347-
let hir_id = self.tcx.hir.node_to_hir_id(id);
1348-
return tables.borrow()
1349-
.closure_kinds()
1350-
.get(hir_id)
1351-
.cloned()
1352-
.map(|(kind, _)| kind);
1353-
}
1354-
}
1355-
1356-
// During typeck, ALL closures are local. But afterwards,
1357-
// during trans, we see closure ids from other traits.
1358-
// That may require loading the closure data out of the
1359-
// cstore.
1360-
Some(self.tcx.closure_kind(def_id))
1349+
let closure_kind_ty = closure_substs.closure_kind_ty(closure_def_id, self.tcx);
1350+
let closure_kind_ty = self.shallow_resolve(&closure_kind_ty);
1351+
closure_kind_ty.to_opt_closure_kind()
13611352
}
13621353

13631354
/// Obtain the signature of a function or closure.

src/librustc/middle/mem_categorization.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -750,10 +750,19 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
750750

751751
let kind = match self.node_ty(fn_hir_id)?.sty {
752752
ty::TyGenerator(..) => ty::ClosureKind::FnOnce,
753-
ty::TyClosure(..) => {
754-
match self.tables.closure_kinds().get(fn_hir_id) {
755-
Some(&(kind, _)) => kind,
756-
None => span_bug!(span, "missing closure kind"),
753+
ty::TyClosure(closure_def_id, closure_substs) => {
754+
match self.infcx {
755+
// During upvar inference we may not know the
756+
// closure kind, just use `Fn`.
757+
Some(infcx) =>
758+
infcx.closure_kind(closure_def_id, closure_substs)
759+
.unwrap_or(ty::ClosureKind::Fn),
760+
761+
None =>
762+
self.tcx.global_tcx()
763+
.lift(&closure_substs)
764+
.expect("no inference cx, but inference variables in closure ty")
765+
.closure_kind(closure_def_id, self.tcx.global_tcx())
757766
}
758767
}
759768
ref t => span_bug!(span, "unexpected type for fn in mem_categorization: {:?}", t),

src/librustc/traits/error_reporting.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -661,8 +661,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
661661
violations)
662662
}
663663

664-
ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => {
665-
let found_kind = self.closure_kind(closure_def_id).unwrap();
664+
ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
665+
let found_kind = self.closure_kind(closure_def_id, closure_substs).unwrap();
666666
let closure_span = self.tcx.hir.span_if_local(closure_def_id).unwrap();
667667
let node_id = self.tcx.hir.as_local_node_id(closure_def_id).unwrap();
668668
let mut err = struct_span_err!(

src/librustc/traits/fulfill.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
492492
}
493493

494494
ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
495-
match closure_substs.opt_closure_kind(closure_def_id, selcx.tcx()) {
495+
match selcx.infcx().closure_kind(closure_def_id, closure_substs) {
496496
Some(closure_kind) => {
497497
if closure_kind.extends(kind) {
498498
Ok(Some(vec![]))

src/librustc/traits/select.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -719,7 +719,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
719719
}
720720

721721
ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
722-
match closure_substs.opt_closure_kind(closure_def_id, self.tcx()) {
722+
match self.infcx.closure_kind(closure_def_id, closure_substs) {
723723
Some(closure_kind) => {
724724
if closure_kind.extends(kind) {
725725
EvaluatedToOk
@@ -1593,10 +1593,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
15931593
// touch bound regions, they just capture the in-scope
15941594
// type/region parameters
15951595
match obligation.self_ty().skip_binder().sty {
1596-
ty::TyClosure(closure_def_id, _) => {
1596+
ty::TyClosure(closure_def_id, closure_substs) => {
15971597
debug!("assemble_unboxed_candidates: kind={:?} obligation={:?}",
15981598
kind, obligation);
1599-
match self.infcx.closure_kind(closure_def_id) {
1599+
match self.infcx.closure_kind(closure_def_id, closure_substs) {
16001600
Some(closure_kind) => {
16011601
debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind);
16021602
if closure_kind.extends(kind) {

src/librustc/ty/instance.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ fn resolve_closure<'a, 'tcx>(
189189
requested_kind: ty::ClosureKind)
190190
-> Instance<'tcx>
191191
{
192-
let actual_kind = tcx.closure_kind(def_id);
192+
let actual_kind = substs.closure_kind(def_id, tcx);
193193

194194
match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
195195
Ok(true) => fn_once_adapter_instance(tcx, def_id, substs),

src/librustc/ty/sty.rs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -289,26 +289,19 @@ impl<'tcx> ClosureSubsts<'tcx> {
289289
upvar_kinds.iter().map(|t| t.as_type().expect("upvar should be type"))
290290
}
291291

292-
/// Returns the closure kind for this closure; may return `None`
293-
/// if inference has not yet completed.
294-
pub fn opt_closure_kind(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>)
295-
-> Option<ty::ClosureKind> {
296-
let closure_kind_ty = self.closure_kind_ty(def_id, tcx);
297-
closure_kind_ty.to_opt_closure_kind()
298-
}
299-
300-
/// Returns the closure kind for this closure; may return `None`
301-
/// if inference has not yet completed.
292+
/// Returns the closure kind for this closure; may return a type
293+
/// variable during inference.
302294
pub fn closure_kind_ty(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> Ty<'tcx> {
303295
self.split(def_id, tcx).closure_kind_ty
304296
}
305297
}
306298

307299
impl<'tcx> ClosureSubsts<'tcx> {
308300
/// Returns the closure kind for this closure; only usable outside
309-
/// of an inference context.
301+
/// of an inference context, because in that context we know that
302+
/// there are no type variables.
310303
pub fn closure_kind(self, def_id: DefId, tcx: TyCtxt<'_, 'tcx, 'tcx>) -> ty::ClosureKind {
311-
self.opt_closure_kind(def_id, tcx).unwrap()
304+
self.split(def_id, tcx).closure_kind_ty.to_opt_closure_kind().unwrap()
312305
}
313306
}
314307

@@ -1472,6 +1465,8 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
14721465

14731466
TyInfer(_) => None,
14741467

1468+
TyError => Some(ty::ClosureKind::Fn),
1469+
14751470
_ => bug!("cannot convert type `{:?}` to a closure kind", self),
14761471
}
14771472
}

src/librustc_mir/build/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,14 +247,18 @@ pub fn closure_self_ty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
247247
let closure_expr_hir_id = tcx.hir.node_to_hir_id(closure_expr_id);
248248
let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_hir_id);
249249

250-
let closure_def_id = tcx.hir.local_def_id(closure_expr_id);
250+
let (closure_def_id, closure_substs) = match closure_ty.sty {
251+
ty::TyClosure(closure_def_id, closure_substs) => (closure_def_id, closure_substs),
252+
_ => bug!("closure expr does not have closure type: {:?}", closure_ty)
253+
};
254+
251255
let region = ty::ReFree(ty::FreeRegion {
252256
scope: closure_def_id,
253257
bound_region: ty::BoundRegion::BrEnv,
254258
});
255259
let region = tcx.mk_region(region);
256260

257-
match tcx.closure_kind(closure_def_id) {
261+
match closure_substs.closure_kind_ty(closure_def_id, tcx).to_opt_closure_kind().unwrap() {
258262
ty::ClosureKind::Fn =>
259263
tcx.mk_ref(region,
260264
ty::TypeAndMut { ty: closure_ty,

src/librustc_trans/common.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
511511
let sig = tcx.fn_sig(def_id).subst(tcx, substs.substs);
512512

513513
let env_region = ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrEnv);
514-
let env_ty = match tcx.closure_kind(def_id) {
514+
let env_ty = match substs.closure_kind(def_id, tcx) {
515515
ty::ClosureKind::Fn => tcx.mk_imm_ref(tcx.mk_region(env_region), ty),
516516
ty::ClosureKind::FnMut => tcx.mk_mut_ref(tcx.mk_region(env_region), ty),
517517
ty::ClosureKind::FnOnce => ty,

src/librustc_trans_utils/monomorphize.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ pub fn resolve_closure<'a, 'tcx> (
8686
requested_kind: ty::ClosureKind)
8787
-> Instance<'tcx>
8888
{
89-
let actual_kind = tcx.closure_kind(def_id);
89+
let actual_kind = substs.closure_kind(def_id, tcx);
9090

9191
match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
9292
Ok(true) => fn_once_adapter_instance(tcx, def_id, substs),

src/librustc_typeck/check/callee.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
108108
// Check whether this is a call to a closure where we
109109
// haven't yet decided on whether the closure is fn vs
110110
// fnmut vs fnonce. If so, we have to defer further processing.
111-
if self.closure_kind(def_id).is_none() {
111+
if self.closure_kind(def_id, substs).is_none() {
112112
let closure_ty = self.fn_sig(def_id).subst(self.tcx, substs.substs);
113113
let fn_sig = self.replace_late_bound_regions_with_fresh_var(call_expr.span,
114114
infer::FnCall,
@@ -122,6 +122,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
122122
adjustments,
123123
fn_sig,
124124
closure_def_id: def_id,
125+
closure_substs: substs,
125126
});
126127
return Some(CallStep::DeferredClosure(fn_sig));
127128
}
@@ -336,6 +337,7 @@ pub struct DeferredCallResolution<'gcx: 'tcx, 'tcx> {
336337
adjustments: Vec<Adjustment<'tcx>>,
337338
fn_sig: ty::FnSig<'tcx>,
338339
closure_def_id: DefId,
340+
closure_substs: ty::ClosureSubsts<'tcx>,
339341
}
340342

341343
impl<'a, 'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> {
@@ -344,7 +346,7 @@ impl<'a, 'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> {
344346

345347
// we should not be invoked until the closure kind has been
346348
// determined by upvar inference
347-
assert!(fcx.closure_kind(self.closure_def_id).is_some());
349+
assert!(fcx.closure_kind(self.closure_def_id, self.closure_substs).is_some());
348350

349351
// We may now know enough to figure out fn vs fnmut etc.
350352
match fcx.try_overloaded_call_traits(self.call_expr,

src/librustc_typeck/check/closure.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
107107
let closure_type = self.tcx.mk_closure(expr_def_id, substs);
108108

109109
if let Some(interior) = interior {
110+
self.demand_eqtype(expr.span,
111+
ty::ClosureKind::FnOnce.to_ty(self.tcx),
112+
substs.closure_kind_ty(expr_def_id, self.tcx));
110113
return self.tcx.mk_generator(expr_def_id, substs, interior);
111114
}
112115

@@ -135,15 +138,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
135138
opt_kind
136139
);
137140

138-
{
139-
let mut tables = self.tables.borrow_mut();
140-
tables.closure_tys_mut().insert(expr.hir_id, sig);
141-
match opt_kind {
142-
Some(kind) => {
143-
tables.closure_kinds_mut().insert(expr.hir_id, (kind, None));
144-
}
145-
None => {}
146-
}
141+
self.tables.borrow_mut().closure_tys_mut().insert(expr.hir_id, sig);
142+
if let Some(kind) = opt_kind {
143+
self.tables.borrow_mut().closure_kinds_mut().insert(expr.hir_id, (kind, None));
144+
self.demand_eqtype(expr.span,
145+
kind.to_ty(self.tcx),
146+
substs.closure_kind_ty(expr_def_id, self.tcx));
147147
}
148148

149149
closure_type

src/librustc_typeck/check/upvar.rs

Lines changed: 50 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ use middle::expr_use_visitor as euv;
4646
use middle::mem_categorization as mc;
4747
use middle::mem_categorization::Categorization;
4848
use rustc::ty::{self, Ty, TyCtxt};
49-
use rustc::ty::TypeFoldable;
5049
use rustc::infer::UpvarRegion;
5150
use syntax::ast;
5251
use syntax_pos::Span;
@@ -158,37 +157,58 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
158157
}
159158
});
160159

161-
{
162-
let body_owner_def_id = self.tcx.hir.body_owner_def_id(body.id());
163-
let region_scope_tree = &self.tcx.region_scope_tree(body_owner_def_id);
164-
let mut delegate = InferBorrowKind {
165-
fcx: self,
166-
adjust_closure_kinds: FxHashMap(),
167-
adjust_upvar_captures: ty::UpvarCaptureMap::default(),
168-
};
169-
euv::ExprUseVisitor::with_infer(
170-
&mut delegate,
171-
&self.infcx,
172-
self.param_env,
173-
region_scope_tree,
174-
&self.tables.borrow(),
175-
).consume_body(body);
176-
177-
// Write the adjusted values back into the main tables.
178-
if infer_kind {
179-
if let Some(kind) = delegate.adjust_closure_kinds.remove(&closure_def_id.index) {
180-
self.tables
181-
.borrow_mut()
182-
.closure_kinds_mut()
183-
.insert(closure_hir_id, kind);
184-
}
160+
// Extract the type of the closure.
161+
let (def_id, closure_substs) = match self.node_ty(closure_hir_id).sty {
162+
ty::TyClosure(def_id, substs) | ty::TyGenerator(def_id, substs, _) => (def_id, substs),
163+
ref t => {
164+
span_bug!(
165+
span,
166+
"type of closure expr {:?} is not a closure {:?}",
167+
closure_node_id,
168+
t
169+
);
170+
}
171+
};
172+
173+
let body_owner_def_id = self.tcx.hir.body_owner_def_id(body.id());
174+
let region_scope_tree = &self.tcx.region_scope_tree(body_owner_def_id);
175+
let mut delegate = InferBorrowKind {
176+
fcx: self,
177+
adjust_closure_kinds: FxHashMap(),
178+
adjust_upvar_captures: ty::UpvarCaptureMap::default(),
179+
};
180+
euv::ExprUseVisitor::with_infer(
181+
&mut delegate,
182+
&self.infcx,
183+
self.param_env,
184+
region_scope_tree,
185+
&self.tables.borrow(),
186+
).consume_body(body);
187+
188+
// Write the adjusted values back into the main tables.
189+
if infer_kind {
190+
let opt_adjusted = delegate.adjust_closure_kinds.remove(&closure_def_id.index);
191+
let closure_kind_ty = closure_substs.closure_kind_ty(def_id, self.tcx);
192+
if let Some((kind, origin)) = opt_adjusted {
193+
self.tables
194+
.borrow_mut()
195+
.closure_kinds_mut()
196+
.insert(closure_hir_id, (kind, origin));
197+
198+
self.demand_eqtype(span, kind.to_ty(self.tcx), closure_kind_ty);
199+
} else {
200+
// If there are only reads, or no upvars, then the
201+
// default of `Fn` will never *have* to be adjusted, so there will be
202+
// no entry in the map.
203+
self.demand_eqtype(span, ty::ClosureKind::Fn.to_ty(self.tcx), closure_kind_ty);
185204
}
186-
self.tables
187-
.borrow_mut()
188-
.upvar_capture_map
189-
.extend(delegate.adjust_upvar_captures);
190205
}
191206

207+
self.tables
208+
.borrow_mut()
209+
.upvar_capture_map
210+
.extend(delegate.adjust_upvar_captures);
211+
192212
// Now that we've analyzed the closure, we know how each
193213
// variable is borrowed, and we know what traits the closure
194214
// implements (Fn vs FnMut etc). We now have some updates to do
@@ -201,27 +221,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
201221
// C, then the type would have infinite size (and the
202222
// inference algorithm will reject it).
203223

204-
// Extract the type variables UV0...UVn.
205-
let (def_id, closure_substs) = match self.node_ty(closure_hir_id).sty {
206-
ty::TyClosure(def_id, substs) | ty::TyGenerator(def_id, substs, _) => (def_id, substs),
207-
ref t => {
208-
span_bug!(
209-
span,
210-
"type of closure expr {:?} is not a closure {:?}",
211-
closure_node_id,
212-
t
213-
);
214-
}
215-
};
216-
217-
// Equate the type variable representing the closure kind.
218-
let closure_kind_ty = closure_substs.closure_kind_ty(def_id, self.tcx);
219-
if closure_kind_ty.needs_infer() {
220-
let final_closure_kind = self.tables.borrow().closure_kinds()[closure_hir_id].0;
221-
self.demand_eqtype(span, final_closure_kind.to_ty(self.tcx), closure_kind_ty);
222-
}
223-
224-
// Equate the type variables with the actual types.
224+
// Equate the type variables for the upvars with the actual types.
225225
let final_upvar_tys = self.final_upvar_tys(closure_node_id);
226226
debug!(
227227
"analyze_closure: id={:?} closure_substs={:?} final_upvar_tys={:?}",

src/test/compile-fail/issue-22638.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ struct A (B);
1919

2020
impl A {
2121
pub fn matches<F: Fn()>(&self, f: &F) {
22-
//~^ ERROR reached the recursion limit while instantiating `A::matches::<[closure
2322
let &A(ref term) = self;
2423
term.matches(f);
2524
}
@@ -59,6 +58,7 @@ struct D (Box<A>);
5958

6059
impl D {
6160
pub fn matches<F: Fn()>(&self, f: &F) {
61+
//~^ ERROR reached the type-length limit while instantiating `D::matches::<[closure
6262
let &D(ref a) = self;
6363
a.matches(f)
6464
}

0 commit comments

Comments
 (0)