Skip to content

Commit 0bc324a

Browse files
committed
remove pop_skolemized and friends
1 parent 3b8008f commit 0bc324a

File tree

6 files changed

+81
-652
lines changed

6 files changed

+81
-652
lines changed

src/librustc/infer/higher_ranked/mod.rs

Lines changed: 13 additions & 307 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,12 @@
1111
//! Helper routines for higher-ranked things. See the `doc` module at
1212
//! the end of the file for details.
1313
14-
use super::{CombinedSnapshot,
15-
InferCtxt,
16-
HigherRankedType,
17-
SkolemizationMap};
14+
use super::{InferCtxt,
15+
HigherRankedType};
1816
use super::combine::CombineFields;
19-
use super::region_constraints::{TaintDirections};
2017

2118
use ty::{self, Binder, TypeFoldable};
22-
use ty::error::TypeError;
2319
use ty::relate::{Relate, RelateResult, TypeRelation};
24-
use syntax_pos::Span;
25-
use util::nodemap::{FxHashMap, FxHashSet};
2620

2721
impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
2822
pub fn higher_ranked_sub<T>(&mut self,
@@ -46,36 +40,28 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
4640

4741
// Start a snapshot so we can examine "all bindings that were
4842
// created as part of this type comparison".
49-
return self.infcx.commit_if_ok(|snapshot| {
43+
return self.infcx.commit_if_ok(|_snapshot| {
5044
let span = self.trace.cause.span;
5145

52-
// First, we instantiate each bound region in the subtype with a fresh
46+
// First, we instantiate each bound region in the supertype with a
47+
// fresh concrete region.
48+
let b_prime =
49+
self.infcx.skolemize_late_bound_regions(b);
50+
51+
// Second, we instantiate each bound region in the subtype with a fresh
5352
// region variable.
5453
let (a_prime, _) =
5554
self.infcx.replace_late_bound_regions_with_fresh_var(
5655
span,
5756
HigherRankedType,
5857
a);
5958

60-
// Second, we instantiate each bound region in the supertype with a
61-
// fresh concrete region.
62-
let (b_prime, skol_map) =
63-
self.infcx.skolemize_late_bound_regions(b);
64-
6559
debug!("a_prime={:?}", a_prime);
6660
debug!("b_prime={:?}", b_prime);
6761

6862
// Compare types now that bound regions have been replaced.
6963
let result = self.sub(param_env, a_is_expected).relate(&a_prime, &b_prime)?;
7064

71-
// Presuming type comparison succeeds, we need to check
72-
// that the skolemized regions do not "leak".
73-
self.infcx.leak_check(!a_is_expected, span, &skol_map, snapshot)?;
74-
75-
// We are finished with the skolemized regions now so pop
76-
// them off.
77-
self.infcx.pop_skolemized(skol_map, snapshot);
78-
7965
debug!("higher_ranked_sub: OK result={:?}", result);
8066

8167
Ok(ty::Binder(result))
@@ -84,306 +70,26 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
8470
}
8571

8672
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
87-
fn tainted_regions(&self,
88-
snapshot: &CombinedSnapshot<'a, 'tcx>,
89-
r: ty::Region<'tcx>,
90-
directions: TaintDirections)
91-
-> FxHashSet<ty::Region<'tcx>> {
92-
self.borrow_region_constraints().tainted(
93-
self.tcx,
94-
&snapshot.region_constraints_snapshot,
95-
r,
96-
directions)
97-
}
98-
99-
fn region_vars_confined_to_snapshot(&self,
100-
snapshot: &CombinedSnapshot<'a, 'tcx>)
101-
-> Vec<ty::RegionVid>
102-
{
103-
/*!
104-
* Returns the set of region variables that do not affect any
105-
* types/regions which existed before `snapshot` was
106-
* started. This is used in the sub/lub/glb computations. The
107-
* idea here is that when we are computing lub/glb of two
108-
* regions, we sometimes create intermediate region variables.
109-
* Those region variables may touch some of the skolemized or
110-
* other "forbidden" regions we created to replace bound
111-
* regions, but they don't really represent an "external"
112-
* constraint.
113-
*
114-
* However, sometimes fresh variables are created for other
115-
* purposes too, and those *may* represent an external
116-
* constraint. In particular, when a type variable is
117-
* instantiated, we create region variables for all the
118-
* regions that appear within, and if that type variable
119-
* pre-existed the snapshot, then those region variables
120-
* represent external constraints.
121-
*
122-
* An example appears in the unit test
123-
* `sub_free_bound_false_infer`. In this test, we want to
124-
* know whether
125-
*
126-
* ```rust
127-
* fn(_#0t) <: for<'a> fn(&'a int)
128-
* ```
129-
*
130-
* Note that the subtype has a type variable. Because the type
131-
* variable can't be instantiated with a region that is bound
132-
* in the fn signature, this comparison ought to fail. But if
133-
* we're not careful, it will succeed.
134-
*
135-
* The reason is that when we walk through the subtyping
136-
* algorith, we begin by replacing `'a` with a skolemized
137-
* variable `'1`. We then have `fn(_#0t) <: fn(&'1 int)`. This
138-
* can be made true by unifying `_#0t` with `&'1 int`. In the
139-
* process, we create a fresh variable for the skolemized
140-
* region, `'$2`, and hence we have that `_#0t == &'$2
141-
* int`. However, because `'$2` was created during the sub
142-
* computation, if we're not careful we will erroneously
143-
* assume it is one of the transient region variables
144-
* representing a lub/glb internally. Not good.
145-
*
146-
* To prevent this, we check for type variables which were
147-
* unified during the snapshot, and say that any region
148-
* variable created during the snapshot but which finds its
149-
* way into a type variable is considered to "escape" the
150-
* snapshot.
151-
*/
152-
153-
let mut region_vars =
154-
self.borrow_region_constraints().vars_created_since_snapshot(
155-
&snapshot.region_constraints_snapshot);
156-
157-
let escaping_types =
158-
self.type_variables.borrow_mut().types_escaping_snapshot(&snapshot.type_snapshot);
159-
160-
let mut escaping_region_vars = FxHashSet();
161-
for ty in &escaping_types {
162-
self.tcx.collect_regions(ty, &mut escaping_region_vars);
163-
}
164-
165-
region_vars.retain(|&region_vid| {
166-
let r = ty::ReVar(region_vid);
167-
!escaping_region_vars.contains(&r)
168-
});
169-
170-
debug!("region_vars_confined_to_snapshot: region_vars={:?} escaping_types={:?}",
171-
region_vars,
172-
escaping_types);
173-
174-
region_vars
175-
}
176-
17773
/// Replace all regions bound by `binder` with skolemized regions and
17874
/// return a map indicating which bound-region was replaced with what
17975
/// skolemized region. This is the first step of checking subtyping
18076
/// when higher-ranked things are involved.
18177
///
182-
/// **Important:** you must call this function from within a snapshot.
183-
/// Moreover, before committing the snapshot, you must eventually call
184-
/// either `plug_leaks` or `pop_skolemized` to remove the skolemized
185-
/// regions. If you rollback the snapshot (or are using a probe), then
186-
/// the pop occurs as part of the rollback, so an explicit call is not
187-
/// needed (but is also permitted).
188-
///
18978
/// See `README.md` for more details.
19079
pub fn skolemize_late_bound_regions<T>(&self,
19180
binder: &ty::Binder<T>)
192-
-> (T, SkolemizationMap<'tcx>)
81+
-> T
19382
where T : TypeFoldable<'tcx>
19483
{
195-
let (result, map) = self.tcx.replace_late_bound_regions(binder, |br| {
84+
let (result, _) = self.tcx.replace_late_bound_regions(binder, |br| {
19685
self.universe.set(self.universe().subuniverse());
19786
self.tcx.mk_region(ty::ReSkolemized(self.universe(), br))
19887
});
19988

200-
debug!("skolemize_bound_regions(binder={:?}, result={:?}, map={:?})",
89+
debug!("skolemize_bound_regions(binder={:?}, result={:?})",
20190
binder,
202-
result,
203-
map);
204-
205-
(result, map)
206-
}
207-
208-
/// Searches the region constraints created since `snapshot` was started
209-
/// and checks to determine whether any of the skolemized regions created
210-
/// in `skol_map` would "escape" -- meaning that they are related to
211-
/// other regions in some way. If so, the higher-ranked subtyping doesn't
212-
/// hold. See `README.md` for more details.
213-
pub fn leak_check(&self,
214-
overly_polymorphic: bool,
215-
_span: Span,
216-
skol_map: &SkolemizationMap<'tcx>,
217-
snapshot: &CombinedSnapshot<'a, 'tcx>)
218-
-> RelateResult<'tcx, ()>
219-
{
220-
debug!("leak_check: skol_map={:?}",
221-
skol_map);
222-
223-
let new_vars = self.region_vars_confined_to_snapshot(snapshot);
224-
for (&skol_br, &skol) in skol_map {
225-
// The inputs to a skolemized variable can only
226-
// be itself or other new variables.
227-
let incoming_taints = self.tainted_regions(snapshot,
228-
skol,
229-
TaintDirections::both());
230-
for &tainted_region in &incoming_taints {
231-
// Each skolemized should only be relatable to itself
232-
// or new variables:
233-
match *tainted_region {
234-
ty::ReVar(vid) => {
235-
if new_vars.contains(&vid) {
236-
continue;
237-
}
238-
}
239-
_ => {
240-
if tainted_region == skol { continue; }
241-
}
242-
};
243-
244-
debug!("{:?} (which replaced {:?}) is tainted by {:?}",
245-
skol,
246-
skol_br,
247-
tainted_region);
248-
249-
return Err(if overly_polymorphic {
250-
debug!("Overly polymorphic!");
251-
TypeError::RegionsOverlyPolymorphic(skol_br, tainted_region)
252-
} else {
253-
debug!("Not as polymorphic!");
254-
TypeError::RegionsInsufficientlyPolymorphic(skol_br, tainted_region)
255-
})
256-
}
257-
}
258-
259-
Ok(())
260-
}
261-
262-
/// This code converts from skolemized regions back to late-bound
263-
/// regions. It works by replacing each region in the taint set of a
264-
/// skolemized region with a bound-region. The bound region will be bound
265-
/// by the outer-most binder in `value`; the caller must ensure that there is
266-
/// such a binder and it is the right place.
267-
///
268-
/// This routine is only intended to be used when the leak-check has
269-
/// passed; currently, it's used in the trait matching code to create
270-
/// a set of nested obligations frmo an impl that matches against
271-
/// something higher-ranked. More details can be found in
272-
/// `librustc/middle/traits/README.md`.
273-
///
274-
/// As a brief example, consider the obligation `for<'a> Fn(&'a int)
275-
/// -> &'a int`, and the impl:
276-
///
277-
/// impl<A,R> Fn<A,R> for SomethingOrOther
278-
/// where A : Clone
279-
/// { ... }
280-
///
281-
/// Here we will have replaced `'a` with a skolemized region
282-
/// `'0`. This means that our substitution will be `{A=>&'0
283-
/// int, R=>&'0 int}`.
284-
///
285-
/// When we apply the substitution to the bounds, we will wind up with
286-
/// `&'0 int : Clone` as a predicate. As a last step, we then go and
287-
/// replace `'0` with a late-bound region `'a`. The depth is matched
288-
/// to the depth of the predicate, in this case 1, so that the final
289-
/// predicate is `for<'a> &'a int : Clone`.
290-
pub fn plug_leaks<T>(&self,
291-
skol_map: SkolemizationMap<'tcx>,
292-
snapshot: &CombinedSnapshot<'a, 'tcx>,
293-
value: T) -> T
294-
where T : TypeFoldable<'tcx>
295-
{
296-
debug!("plug_leaks(skol_map={:?}, value={:?})",
297-
skol_map,
298-
value);
299-
300-
if skol_map.is_empty() {
301-
return value;
302-
}
303-
304-
// Compute a mapping from the "taint set" of each skolemized
305-
// region back to the `ty::BoundRegion` that it originally
306-
// represented. Because `leak_check` passed, we know that
307-
// these taint sets are mutually disjoint.
308-
let inv_skol_map: FxHashMap<ty::Region<'tcx>, ty::BoundRegion> =
309-
skol_map
310-
.iter()
311-
.flat_map(|(&skol_br, &skol)| {
312-
self.tainted_regions(snapshot, skol, TaintDirections::both())
313-
.into_iter()
314-
.map(move |tainted_region| (tainted_region, skol_br))
315-
})
316-
.collect();
317-
318-
debug!("plug_leaks: inv_skol_map={:?}",
319-
inv_skol_map);
320-
321-
// Remove any instantiated type variables from `value`; those can hide
322-
// references to regions from the `fold_regions` code below.
323-
let value = self.resolve_type_vars_if_possible(&value);
324-
325-
// Map any skolemization byproducts back to a late-bound
326-
// region. Put that late-bound region at whatever the outermost
327-
// binder is that we encountered in `value`. The caller is
328-
// responsible for ensuring that (a) `value` contains at least one
329-
// binder and (b) that binder is the one we want to use.
330-
let result = self.tcx.fold_regions(&value, &mut false, |r, current_depth| {
331-
match inv_skol_map.get(&r) {
332-
None => r,
333-
Some(br) => {
334-
// It is the responsibility of the caller to ensure
335-
// that each skolemized region appears within a
336-
// binder. In practice, this routine is only used by
337-
// trait checking, and all of the skolemized regions
338-
// appear inside predicates, which always have
339-
// binders, so this assert is satisfied.
340-
assert!(current_depth > 1);
341-
342-
// since leak-check passed, this skolemized region
343-
// should only have incoming edges from variables
344-
// (which ought not to escape the snapshot, but we
345-
// don't check that) or itself
346-
assert!(
347-
match *r {
348-
ty::ReVar(_) => true,
349-
ty::ReSkolemized(_, ref br1) => br == br1,
350-
_ => false,
351-
},
352-
"leak-check would have us replace {:?} with {:?}",
353-
r, br);
354-
355-
self.tcx.mk_region(ty::ReLateBound(
356-
ty::DebruijnIndex::new(current_depth - 1), br.clone()))
357-
}
358-
}
359-
});
360-
361-
self.pop_skolemized(skol_map, snapshot);
362-
363-
debug!("plug_leaks: result={:?}", result);
91+
result);
36492

36593
result
36694
}
367-
368-
/// Pops the skolemized regions found in `skol_map` from the region
369-
/// inference context. Whenever you create skolemized regions via
370-
/// `skolemize_late_bound_regions`, they must be popped before you
371-
/// commit the enclosing snapshot (if you do not commit, e.g. within a
372-
/// probe or as a result of an error, then this is not necessary, as
373-
/// popping happens as part of the rollback).
374-
///
375-
/// Note: popping also occurs implicitly as part of `leak_check`.
376-
pub fn pop_skolemized(&self,
377-
skol_map: SkolemizationMap<'tcx>,
378-
snapshot: &CombinedSnapshot<'a, 'tcx>) {
379-
debug!("pop_skolemized({:?})", skol_map);
380-
let skol_regions: FxHashSet<_> = skol_map.values().cloned().collect();
381-
self.borrow_region_constraints()
382-
.pop_skolemized(self.universe(), &skol_regions, &snapshot.region_constraints_snapshot);
383-
self.universe.set(snapshot.universe);
384-
if !skol_map.is_empty() {
385-
self.projection_cache.borrow_mut().rollback_skolemized(
386-
&snapshot.projection_cache_snapshot);
387-
}
388-
}
38995
}

src/librustc/infer/lexical_region_resolve/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,10 +264,13 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> {
264264
}
265265

266266
debug!(
267-
"Expanding value of {:?} from {:?} to {:?}",
267+
"Expanding value of {:?} from {:?} to {:?} \
268+
(lub_universe={:?}, b_universe={:?})",
268269
b_vid,
269270
cur_region,
270-
lub
271+
lub,
272+
lub_universe,
273+
b_universe
271274
);
272275

273276
*b_data = VarValue::Value(lub);

0 commit comments

Comments
 (0)