Skip to content

Commit 88902ad

Browse files
committed
convert the closure_kinds map to just store the origin information
The closure kinds themselves are now completely found in the `ClosureSubsts`.
1 parent 4968fa9 commit 88902ad

File tree

10 files changed

+107
-114
lines changed

10 files changed

+107
-114
lines changed

src/librustc/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#![feature(inclusive_range_syntax)]
5050
#![cfg_attr(windows, feature(libc))]
5151
#![feature(macro_vis_matcher)]
52+
#![feature(match_default_bindings)]
5253
#![feature(never_type)]
5354
#![feature(nonzero)]
5455
#![feature(quote)]

src/librustc/middle/mem_categorization.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -753,16 +753,16 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
753753
ty::TyClosure(closure_def_id, closure_substs) => {
754754
match self.infcx {
755755
// During upvar inference we may not know the
756-
// closure kind, just use `Fn`.
756+
// closure kind, just use the LATTICE_BOTTOM value.
757757
Some(infcx) =>
758758
infcx.closure_kind(closure_def_id, closure_substs)
759-
.unwrap_or(ty::ClosureKind::Fn),
759+
.unwrap_or(ty::ClosureKind::LATTICE_BOTTOM),
760760

761761
None =>
762762
self.tcx.global_tcx()
763763
.lift(&closure_substs)
764764
.expect("no inference cx, but inference variables in closure ty")
765-
.closure_kind(closure_def_id, self.tcx.global_tcx())
765+
.closure_kind(closure_def_id, self.tcx.global_tcx()),
766766
}
767767
}
768768
ref t => bug!("upvar from non-closure and non-generator: {:?}", t)

src/librustc/traits/error_reporting.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -674,14 +674,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
674674
if let Some(tables) = self.in_progress_tables {
675675
let tables = tables.borrow();
676676
let closure_hir_id = self.tcx.hir.node_to_hir_id(node_id);
677-
match tables.closure_kinds().get(closure_hir_id) {
678-
Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) => {
679-
err.span_note(span, &format!(
677+
match (found_kind, tables.closure_kind_origins().get(closure_hir_id)) {
678+
(ty::ClosureKind::FnOnce, Some((span, name))) => {
679+
err.span_note(*span, &format!(
680680
"closure is `FnOnce` because it moves the \
681681
variable `{}` out of its environment", name));
682682
},
683-
Some(&(ty::ClosureKind::FnMut, Some((span, name)))) => {
684-
err.span_note(span, &format!(
683+
(ty::ClosureKind::FnMut, Some((span, name))) => {
684+
err.span_note(*span, &format!(
685685
"closure is `FnMut` because it mutates the \
686686
variable `{}` here", name));
687687
},

src/librustc/ty/context.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -360,9 +360,9 @@ pub struct TypeckTables<'tcx> {
360360
/// Records the type of each closure.
361361
closure_tys: ItemLocalMap<ty::PolyFnSig<'tcx>>,
362362

363-
/// Records the kind of each closure and the span and name of the variable
364-
/// that caused the closure to be this kind.
365-
closure_kinds: ItemLocalMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>,
363+
/// Records the reasons that we picked the kind of each closure;
364+
/// not all closures are present in the map.
365+
closure_kind_origins: ItemLocalMap<(Span, ast::Name)>,
366366

367367
generator_sigs: ItemLocalMap<Option<ty::GenSig<'tcx>>>,
368368

@@ -415,7 +415,7 @@ impl<'tcx> TypeckTables<'tcx> {
415415
generator_sigs: ItemLocalMap(),
416416
generator_interiors: ItemLocalMap(),
417417
closure_tys: ItemLocalMap(),
418-
closure_kinds: ItemLocalMap(),
418+
closure_kind_origins: ItemLocalMap(),
419419
liberated_fn_sigs: ItemLocalMap(),
420420
fru_field_types: ItemLocalMap(),
421421
cast_kinds: ItemLocalMap(),
@@ -625,19 +625,17 @@ impl<'tcx> TypeckTables<'tcx> {
625625
}
626626
}
627627

628-
pub fn closure_kinds(&self) -> LocalTableInContext<(ty::ClosureKind,
629-
Option<(Span, ast::Name)>)> {
628+
pub fn closure_kind_origins(&self) -> LocalTableInContext<(Span, ast::Name)> {
630629
LocalTableInContext {
631630
local_id_root: self.local_id_root,
632-
data: &self.closure_kinds
631+
data: &self.closure_kind_origins
633632
}
634633
}
635634

636-
pub fn closure_kinds_mut(&mut self)
637-
-> LocalTableInContextMut<(ty::ClosureKind, Option<(Span, ast::Name)>)> {
635+
pub fn closure_kind_origins_mut(&mut self) -> LocalTableInContextMut<(Span, ast::Name)> {
638636
LocalTableInContextMut {
639637
local_id_root: self.local_id_root,
640-
data: &mut self.closure_kinds
638+
data: &mut self.closure_kind_origins
641639
}
642640
}
643641

@@ -734,7 +732,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for TypeckTables<'gcx> {
734732
ref pat_adjustments,
735733
ref upvar_capture_map,
736734
ref closure_tys,
737-
ref closure_kinds,
735+
ref closure_kind_origins,
738736
ref liberated_fn_sigs,
739737
ref fru_field_types,
740738

@@ -777,7 +775,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for TypeckTables<'gcx> {
777775
});
778776

779777
closure_tys.hash_stable(hcx, hasher);
780-
closure_kinds.hash_stable(hcx, hasher);
778+
closure_kind_origins.hash_stable(hcx, hasher);
781779
liberated_fn_sigs.hash_stable(hcx, hasher);
782780
fru_field_types.hash_stable(hcx, hasher);
783781
cast_kinds.hash_stable(hcx, hasher);

src/librustc/ty/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1902,6 +1902,9 @@ pub enum ClosureKind {
19021902
}
19031903

19041904
impl<'a, 'tcx> ClosureKind {
1905+
// This is the initial value used when doing upvar inference.
1906+
pub const LATTICE_BOTTOM: ClosureKind = ClosureKind::Fn;
1907+
19051908
pub fn trait_did(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> DefId {
19061909
match *self {
19071910
ClosureKind::Fn => tcx.require_lang_item(FnTraitLangItem),

src/librustc_borrowck/borrowck/mod.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -655,10 +655,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
655655
ty::TypeVariants::TyClosure(id, _) => {
656656
let node_id = self.tcx.hir.as_local_node_id(id).unwrap();
657657
let hir_id = self.tcx.hir.node_to_hir_id(node_id);
658-
if let Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) =
659-
self.tables.closure_kinds().get(hir_id)
660-
{
661-
err.span_note(span, &format!(
658+
if let Some((span, name)) = self.tables.closure_kind_origins().get(hir_id) {
659+
err.span_note(*span, &format!(
662660
"closure cannot be invoked more than once because \
663661
it moves the variable `{}` out of its environment",
664662
name

src/librustc_borrowck/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#![allow(non_camel_case_types)]
1717

18+
#![feature(match_default_bindings)]
1819
#![feature(quote)]
1920

2021
#[macro_use] extern crate log;

src/librustc_typeck/check/closure.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
140140

141141
self.tables.borrow_mut().closure_tys_mut().insert(expr.hir_id, sig);
142142
if let Some(kind) = opt_kind {
143-
self.tables.borrow_mut().closure_kinds_mut().insert(expr.hir_id, (kind, None));
144143
self.demand_eqtype(expr.span,
145144
kind.to_ty(self.tcx),
146145
substs.closure_kind_ty(expr_def_id, self.tcx));

src/librustc_typeck/check/upvar.rs

Lines changed: 80 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,14 @@ use super::FnCtxt;
4545
use middle::expr_use_visitor as euv;
4646
use middle::mem_categorization as mc;
4747
use middle::mem_categorization::Categorization;
48+
use rustc::hir::def_id::DefId;
4849
use rustc::ty::{self, Ty, TyCtxt};
4950
use rustc::infer::UpvarRegion;
5051
use syntax::ast;
5152
use syntax_pos::Span;
5253
use rustc::hir;
5354
use rustc::hir::def_id::DefIndex;
5455
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
55-
use rustc::util::nodemap::FxHashMap;
56-
57-
use std::collections::hash_map::Entry;
5856

5957
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
6058
pub fn closure_analyze(&self, body: &'gcx hir::Body) {
@@ -98,7 +96,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
9896
span: Span,
9997
body: &hir::Body,
10098
capture_clause: hir::CaptureClause,
101-
gen: bool,
99+
is_generator: bool,
102100
) {
103101
/*!
104102
* Analysis starting point.
@@ -110,24 +108,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
110108
body.id()
111109
);
112110

113-
let infer_kind = if gen {
114-
false
115-
} else {
116-
match self.tables
117-
.borrow_mut()
118-
.closure_kinds_mut()
119-
.entry(closure_hir_id)
120-
{
121-
Entry::Occupied(_) => false,
122-
Entry::Vacant(entry) => {
123-
debug!("check_closure: adding closure {:?} as Fn", closure_node_id);
124-
entry.insert((ty::ClosureKind::Fn, None));
125-
true
126-
}
111+
// Extract the type of the closure.
112+
let (closure_def_id, closure_substs) = match self.node_ty(closure_hir_id).sty {
113+
ty::TyClosure(def_id, substs) | ty::TyGenerator(def_id, substs, _) => (def_id, substs),
114+
ref t => {
115+
span_bug!(
116+
span,
117+
"type of closure expr {:?} is not a closure {:?}",
118+
closure_node_id,
119+
t
120+
);
127121
}
128122
};
129123

130-
let closure_def_id = self.tcx.hir.local_def_id(closure_node_id);
124+
let infer_kind = if is_generator {
125+
false
126+
} else {
127+
self.closure_kind(closure_def_id, closure_substs).is_none()
128+
};
131129

132130
self.tcx
133131
.with_freevars(closure_node_id, |freevars| for freevar in freevars {
@@ -156,24 +154,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
156154
.insert(upvar_id, capture_kind);
157155
});
158156

159-
// Extract the type of the closure.
160-
let (def_id, closure_substs) = match self.node_ty(closure_hir_id).sty {
161-
ty::TyClosure(def_id, substs) | ty::TyGenerator(def_id, substs, _) => (def_id, substs),
162-
ref t => {
163-
span_bug!(
164-
span,
165-
"type of closure expr {:?} is not a closure {:?}",
166-
closure_node_id,
167-
t
168-
);
169-
}
170-
};
171-
172157
let body_owner_def_id = self.tcx.hir.body_owner_def_id(body.id());
173158
let region_scope_tree = &self.tcx.region_scope_tree(body_owner_def_id);
174159
let mut delegate = InferBorrowKind {
175160
fcx: self,
176-
adjust_closure_kinds: FxHashMap(),
161+
closure_def_id: closure_def_id,
162+
current_closure_kind: ty::ClosureKind::LATTICE_BOTTOM,
163+
current_origin: None,
177164
adjust_upvar_captures: ty::UpvarCaptureMap::default(),
178165
};
179166
euv::ExprUseVisitor::with_infer(
@@ -184,22 +171,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
184171
&self.tables.borrow(),
185172
).consume_body(body);
186173

187-
// Write the adjusted values back into the main tables.
188174
if infer_kind {
189-
let opt_adjusted = delegate.adjust_closure_kinds.remove(&closure_def_id.index);
190-
let closure_kind_ty = closure_substs.closure_kind_ty(def_id, self.tcx);
191-
if let Some((kind, origin)) = opt_adjusted {
175+
// Unify the (as yet unbound) type variable in the closure
176+
// substs with the kind we inferred.
177+
let inferred_kind = delegate.current_closure_kind;
178+
let closure_kind_ty = closure_substs.closure_kind_ty(closure_def_id, self.tcx);
179+
self.demand_eqtype(span, inferred_kind.to_ty(self.tcx), closure_kind_ty);
180+
181+
// If we have an origin, store it.
182+
if let Some(origin) = delegate.current_origin {
192183
self.tables
193184
.borrow_mut()
194-
.closure_kinds_mut()
195-
.insert(closure_hir_id, (kind, origin));
196-
197-
self.demand_eqtype(span, kind.to_ty(self.tcx), closure_kind_ty);
198-
} else {
199-
// If there are only reads, or no upvars, then the
200-
// default of `Fn` will never *have* to be adjusted, so there will be
201-
// no entry in the map.
202-
self.demand_eqtype(span, ty::ClosureKind::Fn.to_ty(self.tcx), closure_kind_ty);
185+
.closure_kind_origins_mut()
186+
.insert(closure_hir_id, origin);
203187
}
204188
}
205189

@@ -229,19 +213,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
229213
final_upvar_tys
230214
);
231215
for (upvar_ty, final_upvar_ty) in closure_substs
232-
.upvar_tys(def_id, self.tcx)
216+
.upvar_tys(closure_def_id, self.tcx)
233217
.zip(final_upvar_tys)
234218
{
235219
self.demand_eqtype(span, final_upvar_ty, upvar_ty);
236220
}
237221

238222
// If we are also inferred the closure kind here,
239223
// process any deferred resolutions.
240-
if infer_kind {
241-
let deferred_call_resolutions = self.remove_deferred_call_resolutions(closure_def_id);
242-
for deferred_call_resolution in deferred_call_resolutions {
243-
deferred_call_resolution.resolve(self);
244-
}
224+
let deferred_call_resolutions = self.remove_deferred_call_resolutions(closure_def_id);
225+
for deferred_call_resolution in deferred_call_resolutions {
226+
deferred_call_resolution.resolve(self);
245227
}
246228
}
247229

@@ -293,7 +275,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
293275

294276
struct InferBorrowKind<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
295277
fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
296-
adjust_closure_kinds: FxHashMap<DefIndex, (ty::ClosureKind, Option<(Span, ast::Name)>)>,
278+
279+
// The def-id of the closure whose kind and upvar accesses are being inferred.
280+
closure_def_id: DefId,
281+
282+
// The kind that we have inferred that the current closure
283+
// requires. Note that we *always* infer a minimal kind, even if
284+
// we don't always *use* that in the final result (i.e., sometimes
285+
// we've taken the closure kind from the expectations instead, and
286+
// for generators we don't even implement the closure traits
287+
// really).
288+
current_closure_kind: ty::ClosureKind,
289+
290+
// If we modified `current_closure_kind`, this field contains a `Some()` with the
291+
// variable access that caused us to do so.
292+
current_origin: Option<(Span, ast::Name)>,
293+
294+
// For each upvar that we access, we track the minimal kind of
295+
// access we need (ref, ref mut, move, etc).
297296
adjust_upvar_captures: ty::UpvarCaptureMap<'tcx>,
298297
}
299298

@@ -533,42 +532,36 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
533532
var_name
534533
);
535534

536-
let closure_kind = self.adjust_closure_kinds
537-
.get(&closure_id)
538-
.cloned()
539-
.or_else(|| {
540-
let closure_id = self.fcx.tcx.hir.def_index_to_hir_id(closure_id);
541-
self.fcx
542-
.tables
543-
.borrow()
544-
.closure_kinds()
545-
.get(closure_id)
546-
.cloned()
547-
});
535+
// Is this the closure whose kind is currently being inferred?
536+
if DefId::local(closure_id) != self.closure_def_id {
537+
debug!("adjust_closure_kind: not current closure");
538+
return;
539+
}
548540

549-
if let Some((existing_kind, _)) = closure_kind {
550-
debug!(
551-
"adjust_closure_kind: closure_id={:?}, existing_kind={:?}, new_kind={:?}",
552-
closure_id,
553-
existing_kind,
554-
new_kind
555-
);
556-
557-
match (existing_kind, new_kind) {
558-
(ty::ClosureKind::Fn, ty::ClosureKind::Fn) |
559-
(ty::ClosureKind::FnMut, ty::ClosureKind::Fn) |
560-
(ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
561-
(ty::ClosureKind::FnOnce, _) => {
562-
// no change needed
563-
}
541+
// closures start out as `Fn`.
542+
let existing_kind = self.current_closure_kind;
564543

565-
(ty::ClosureKind::Fn, ty::ClosureKind::FnMut) |
566-
(ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
567-
(ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
568-
// new kind is stronger than the old kind
569-
self.adjust_closure_kinds
570-
.insert(closure_id, (new_kind, Some((upvar_span, var_name))));
571-
}
544+
debug!(
545+
"adjust_closure_kind: closure_id={:?}, existing_kind={:?}, new_kind={:?}",
546+
closure_id,
547+
existing_kind,
548+
new_kind
549+
);
550+
551+
match (existing_kind, new_kind) {
552+
(ty::ClosureKind::Fn, ty::ClosureKind::Fn) |
553+
(ty::ClosureKind::FnMut, ty::ClosureKind::Fn) |
554+
(ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
555+
(ty::ClosureKind::FnOnce, _) => {
556+
// no change needed
557+
}
558+
559+
(ty::ClosureKind::Fn, ty::ClosureKind::FnMut) |
560+
(ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
561+
(ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
562+
// new kind is stronger than the old kind
563+
self.current_closure_kind = new_kind;
564+
self.current_origin = Some((upvar_span, var_name));
572565
}
573566
}
574567
}

0 commit comments

Comments
 (0)