Skip to content

Commit c45307f

Browse files
committed
extract the code to create OutlivesBounds into its own module
Now it can be reused by the NLL code.
1 parent 1f33145 commit c45307f

File tree

2 files changed

+110
-98
lines changed

2 files changed

+110
-98
lines changed

src/librustc/infer/outlives/env.rs

Lines changed: 47 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use infer::{InferCtxt, GenericKind};
11+
use infer::{GenericKind, InferCtxt};
1212
use infer::outlives::free_region_map::FreeRegionMap;
13-
use infer::outlives::implied_bounds::ImpliedBound;
13+
use infer::outlives::implied_bounds::{self, OutlivesBound};
1414
use ty::{self, Ty};
1515

1616
use syntax::ast;
@@ -50,7 +50,7 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> OutlivesEnvironment<'tcx> {
5050
region_bound_pairs: vec![],
5151
};
5252

53-
env.init_free_regions_from_predicates();
53+
env.add_outlives_bounds(None, implied_bounds::explicit_outlives_bounds(param_env));
5454

5555
env
5656
}
@@ -144,65 +144,54 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> OutlivesEnvironment<'tcx> {
144144
for &ty in fn_sig_tys {
145145
let ty = infcx.resolve_type_vars_if_possible(&ty);
146146
debug!("add_implied_bounds: ty = {}", ty);
147-
let implied_bounds = infcx.implied_bounds(self.param_env, body_id, ty, span);
148-
149-
// But also record other relationships, such as `T:'x`,
150-
// that don't go into the free-region-map but which we use
151-
// here.
152-
for implication in implied_bounds {
153-
debug!("add_implied_bounds: implication={:?}", implication);
154-
match implication {
155-
ImpliedBound::RegionSubRegion(
156-
r_a @ &ty::ReEarlyBound(_),
157-
&ty::ReVar(vid_b),
158-
) |
159-
ImpliedBound::RegionSubRegion(r_a @ &ty::ReFree(_), &ty::ReVar(vid_b)) => {
160-
infcx.add_given(r_a, vid_b);
161-
}
162-
ImpliedBound::RegionSubParam(r_a, param_b) => {
163-
self.region_bound_pairs
164-
.push((r_a, GenericKind::Param(param_b)));
165-
}
166-
ImpliedBound::RegionSubProjection(r_a, projection_b) => {
167-
self.region_bound_pairs
168-
.push((r_a, GenericKind::Projection(projection_b)));
169-
}
170-
ImpliedBound::RegionSubRegion(r_a, r_b) => {
171-
// In principle, we could record (and take
172-
// advantage of) every relationship here, but
173-
// we are also free not to -- it simply means
174-
// strictly less that we can successfully type
175-
// check. Right now we only look for things
176-
// relationships between free regions. (It may
177-
// also be that we should revise our inference
178-
// system to be more general and to make use
179-
// of *every* relationship that arises here,
180-
// but presently we do not.)
181-
self.free_region_map.relate_regions(r_a, r_b);
182-
}
183-
}
184-
}
147+
let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span);
148+
self.add_outlives_bounds(Some(infcx), implied_bounds)
185149
}
186150
}
187151

188-
fn init_free_regions_from_predicates(&mut self) {
189-
debug!("init_free_regions_from_predicates()");
190-
for predicate in self.param_env.caller_bounds {
191-
debug!("init_free_regions_from_predicates: predicate={:?}", predicate);
192-
match *predicate {
193-
ty::Predicate::Projection(..) |
194-
ty::Predicate::Trait(..) |
195-
ty::Predicate::Equate(..) |
196-
ty::Predicate::Subtype(..) |
197-
ty::Predicate::WellFormed(..) |
198-
ty::Predicate::ObjectSafe(..) |
199-
ty::Predicate::ClosureKind(..) |
200-
ty::Predicate::TypeOutlives(..) |
201-
ty::Predicate::ConstEvaluatable(..) => {
202-
// No region bounds here
152+
/// Processes outlives bounds that are known to hold, whether from implied or other sources.
153+
///
154+
/// The `infcx` parameter is optional; if the implied bounds may
155+
/// contain inference variables, it should be supplied, in which
156+
/// case we will register "givens" on the inference context. (See
157+
/// `RegionConstraintData`.)
158+
fn add_outlives_bounds<I>(
159+
&mut self,
160+
infcx: Option<&InferCtxt<'a, 'gcx, 'tcx>>,
161+
outlives_bounds: I,
162+
) where
163+
I: IntoIterator<Item = OutlivesBound<'tcx>>,
164+
{
165+
// But also record other relationships, such as `T:'x`,
166+
// that don't go into the free-region-map but which we use
167+
// here.
168+
for outlives_bound in outlives_bounds {
169+
debug!("add_outlives_bounds: outlives_bound={:?}", outlives_bound);
170+
match outlives_bound {
171+
OutlivesBound::RegionSubRegion(r_a @ &ty::ReEarlyBound(_), &ty::ReVar(vid_b)) |
172+
OutlivesBound::RegionSubRegion(r_a @ &ty::ReFree(_), &ty::ReVar(vid_b)) => {
173+
infcx.expect("no infcx provided but region vars found").add_given(r_a, vid_b);
174+
}
175+
OutlivesBound::RegionSubParam(r_a, param_b) => {
176+
self.region_bound_pairs
177+
.push((r_a, GenericKind::Param(param_b)));
178+
}
179+
OutlivesBound::RegionSubProjection(r_a, projection_b) => {
180+
self.region_bound_pairs
181+
.push((r_a, GenericKind::Projection(projection_b)));
203182
}
204-
ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r_a, r_b))) => {
205-
self.free_region_map.relate_regions(r_b, r_a);
183+
OutlivesBound::RegionSubRegion(r_a, r_b) => {
184+
// In principle, we could record (and take
185+
// advantage of) every relationship here, but
186+
// we are also free not to -- it simply means
187+
// strictly less that we can successfully type
188+
// check. Right now we only look for things
189+
// relationships between free regions. (It may
190+
// also be that we should revise our inference
191+
// system to be more general and to make use
192+
// of *every* relationship that arises here,
193+
// but presently we do not.)
194+
self.free_region_map.relate_regions(r_a, r_b);
206195
}
207196
}
208197
}

src/librustc/infer/outlives/implied_bounds.rs

Lines changed: 63 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,32 @@ use ty::{self, Ty, TypeFoldable};
1616
use ty::outlives::Component;
1717
use ty::wf;
1818

19-
/// Implied bounds are region relationships that we deduce
20-
/// automatically. The idea is that (e.g.) a caller must check that a
21-
/// function's argument types are well-formed immediately before
22-
/// calling that fn, and hence the *callee* can assume that its
23-
/// argument types are well-formed. This may imply certain relationships
24-
/// between generic parameters. For example:
25-
///
26-
/// fn foo<'a,T>(x: &'a T)
27-
///
28-
/// can only be called with a `'a` and `T` such that `&'a T` is WF.
29-
/// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`.
19+
/// Outlives bounds are relationships between generic parameters,
20+
/// whether they both be regions (`'a: 'b`) or whether types are
21+
/// involved (`T: 'a`). These relationships can be extracted from the
22+
/// full set of predicates we understand or also from types (in which
23+
/// case they are called implied bounds). They are fed to the
24+
/// `OutlivesEnv` which in turn is supplied to the region checker and
25+
/// other parts of the inference system.
3026
#[derive(Debug)]
31-
pub enum ImpliedBound<'tcx> {
27+
pub enum OutlivesBound<'tcx> {
3228
RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
3329
RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
3430
RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>),
3531
}
3632

3733
impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
38-
/// Compute the implied bounds that a callee/impl can assume based on
39-
/// the fact that caller/projector has ensured that `ty` is WF. See
40-
/// the `ImpliedBound` type for more details.
34+
/// Implied bounds are region relationships that we deduce
35+
/// automatically. The idea is that (e.g.) a caller must check that a
36+
/// function's argument types are well-formed immediately before
37+
/// calling that fn, and hence the *callee* can assume that its
38+
/// argument types are well-formed. This may imply certain relationships
39+
/// between generic parameters. For example:
40+
///
41+
/// fn foo<'a,T>(x: &'a T)
42+
///
43+
/// can only be called with a `'a` and `T` such that `&'a T` is WF.
44+
/// For `&'a T` to be WF, `T: 'a` must hold. So we can assume `T: 'a`.
4145
///
4246
/// # Parameters
4347
///
@@ -48,13 +52,13 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
4852
/// - `ty`, the type that we are supposed to assume is WF.
4953
/// - `span`, a span to use when normalizing, hopefully not important,
5054
/// might be useful if a `bug!` occurs.
51-
pub fn implied_bounds(
55+
pub fn implied_outlives_bounds(
5256
&self,
5357
param_env: ty::ParamEnv<'tcx>,
5458
body_id: ast::NodeId,
5559
ty: Ty<'tcx>,
5660
span: Span,
57-
) -> Vec<ImpliedBound<'tcx>> {
61+
) -> Vec<OutlivesBound<'tcx>> {
5862
let tcx = self.tcx;
5963

6064
// Sometimes when we ask what it takes for T: WF, we get back that
@@ -76,8 +80,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
7680
// than the ultimate set. (Note: normally there won't be
7781
// unresolved inference variables here anyway, but there might be
7882
// during typeck under some circumstances.)
79-
let obligations =
80-
wf::obligations(self, param_env, body_id, ty, span).unwrap_or(vec![]);
83+
let obligations = wf::obligations(self, param_env, body_id, ty, span).unwrap_or(vec![]);
8184

8285
// NB: All of these predicates *ought* to be easily proven
8386
// true. In fact, their correctness is (mostly) implied by
@@ -105,7 +108,8 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
105108
obligations
106109
.iter()
107110
.filter(|o| o.predicate.has_infer_types())
108-
.cloned());
111+
.cloned(),
112+
);
109113

110114
// From the full set of obligations, just filter down to the
111115
// region relationships.
@@ -125,25 +129,21 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
125129
vec![]
126130
}
127131

128-
ty::Predicate::RegionOutlives(ref data) => {
129-
match data.no_late_bound_regions() {
130-
None => vec![],
131-
Some(ty::OutlivesPredicate(r_a, r_b)) => {
132-
vec![ImpliedBound::RegionSubRegion(r_b, r_a)]
133-
}
132+
ty::Predicate::RegionOutlives(ref data) => match data.no_late_bound_regions() {
133+
None => vec![],
134+
Some(ty::OutlivesPredicate(r_a, r_b)) => {
135+
vec![OutlivesBound::RegionSubRegion(r_b, r_a)]
134136
}
135-
}
137+
},
136138

137-
ty::Predicate::TypeOutlives(ref data) => {
138-
match data.no_late_bound_regions() {
139-
None => vec![],
140-
Some(ty::OutlivesPredicate(ty_a, r_b)) => {
141-
let ty_a = self.resolve_type_vars_if_possible(&ty_a);
142-
let components = tcx.outlives_components(ty_a);
143-
Self::implied_bounds_from_components(r_b, components)
144-
}
139+
ty::Predicate::TypeOutlives(ref data) => match data.no_late_bound_regions() {
140+
None => vec![],
141+
Some(ty::OutlivesPredicate(ty_a, r_b)) => {
142+
let ty_a = self.resolve_type_vars_if_possible(&ty_a);
143+
let components = tcx.outlives_components(ty_a);
144+
Self::implied_bounds_from_components(r_b, components)
145145
}
146-
}
146+
},
147147
}
148148
}));
149149
}
@@ -165,17 +165,17 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
165165
fn implied_bounds_from_components(
166166
sub_region: ty::Region<'tcx>,
167167
sup_components: Vec<Component<'tcx>>,
168-
) -> Vec<ImpliedBound<'tcx>> {
168+
) -> Vec<OutlivesBound<'tcx>> {
169169
sup_components
170170
.into_iter()
171171
.flat_map(|component| {
172172
match component {
173173
Component::Region(r) =>
174-
vec![ImpliedBound::RegionSubRegion(sub_region, r)],
174+
vec![OutlivesBound::RegionSubRegion(sub_region, r)],
175175
Component::Param(p) =>
176-
vec![ImpliedBound::RegionSubParam(sub_region, p)],
176+
vec![OutlivesBound::RegionSubParam(sub_region, p)],
177177
Component::Projection(p) =>
178-
vec![ImpliedBound::RegionSubProjection(sub_region, p)],
178+
vec![OutlivesBound::RegionSubProjection(sub_region, p)],
179179
Component::EscapingProjection(_) =>
180180
// If the projection has escaping regions, don't
181181
// try to infer any implied bounds even for its
@@ -193,3 +193,26 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
193193
.collect()
194194
}
195195
}
196+
197+
pub fn explicit_outlives_bounds<'tcx>(
198+
param_env: ty::ParamEnv<'tcx>,
199+
) -> impl Iterator<Item = OutlivesBound<'tcx>> + 'tcx {
200+
debug!("explicit_outlives_bounds()");
201+
param_env
202+
.caller_bounds
203+
.into_iter()
204+
.filter_map(move |predicate| match predicate {
205+
ty::Predicate::Projection(..) |
206+
ty::Predicate::Trait(..) |
207+
ty::Predicate::Equate(..) |
208+
ty::Predicate::Subtype(..) |
209+
ty::Predicate::WellFormed(..) |
210+
ty::Predicate::ObjectSafe(..) |
211+
ty::Predicate::ClosureKind(..) |
212+
ty::Predicate::TypeOutlives(..) |
213+
ty::Predicate::ConstEvaluatable(..) => None,
214+
ty::Predicate::RegionOutlives(ref data) => data.no_late_bound_regions().map(
215+
|ty::OutlivesPredicate(r_a, r_b)| OutlivesBound::RegionSubRegion(r_b, r_a),
216+
),
217+
})
218+
}

0 commit comments

Comments
 (0)