Skip to content

Commit bd65c8a

Browse files
committed
---
yaml --- r: 227324 b: refs/heads/auto c: a7c9a15 h: refs/heads/master v: v3
1 parent 6d24cc4 commit bd65c8a

File tree

2 files changed

+126
-108
lines changed

2 files changed

+126
-108
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503
88
refs/tags/release-0.3.1: 495bae036dfe5ec6ceafd3312b4dca48741e845b
99
refs/tags/release-0.4: e828ea2080499553b97dfe33b3f4d472b4562ad7
1010
refs/tags/release-0.5: 7e3bcfbf21278251ee936ad53e92e9b719702d73
11-
refs/heads/auto: a264440ab0f498e1ab77b17d24c3d6988c721c27
11+
refs/heads/auto: a7c9a15e0ee41e535bedf469f2784be38cadd945
1212
refs/tags/release-0.6: b4ebcfa1812664df5e142f0134a5faea3918544c
1313
refs/tags/0.1: b19db808c2793fe2976759b85a355c3ad8c8b336
1414
refs/tags/0.2: 1754d02027f2924bed83b0160ee340c7f41d5ea1

branches/auto/src/librustc/middle/outlives.rs

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

11-
// The outlines relation `T: 'a` or `'a: 'b`.
11+
// The outlines relation `T: 'a` or `'a: 'b`. This code frequently
12+
// refers to rules defined in RFC 1214 (`OutlivesFooBar`), so see that
13+
// RFC for reference.
1214

1315
use middle::infer::InferCtxt;
1416
use middle::ty::{self, RegionEscape, Ty};
@@ -67,123 +69,139 @@ pub fn components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
6769
}
6870

6971
fn compute_components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
70-
ty0: Ty<'tcx>,
72+
ty: Ty<'tcx>,
7173
out: &mut Vec<Component<'tcx>>) {
7274
// Descend through the types, looking for the various "base"
7375
// components and collecting them into `out`. This is not written
7476
// with `collect()` because of the need to sometimes skip subtrees
7577
// in the `subtys` iterator (e.g., when encountering a
7678
// projection).
77-
let mut subtys = ty0.walk();
78-
while let Some(ty) = subtys.next() {
79-
match ty.sty {
80-
ty::TyClosure(_, ref substs) => {
81-
// FIXME(#27086). We do not accumulate from substs, since they
82-
// don't represent reachable data. This means that, in
83-
// practice, some of the lifetime parameters might not
84-
// be in scope when the body runs, so long as there is
85-
// no reachable data with that lifetime. For better or
86-
// worse, this is consistent with fn types, however,
87-
// which can also encapsulate data in this fashion
88-
// (though it's somewhat harder, and typically
89-
// requires virtual dispatch).
90-
//
91-
// Note that changing this (in a naive way, at least)
92-
// causes regressions for what appears to be perfectly
93-
// reasonable code like this:
94-
//
95-
// ```
96-
// fn foo<'a>(p: &Data<'a>) {
97-
// bar(|q: &mut Parser| q.read_addr())
98-
// }
99-
// fn bar(p: Box<FnMut(&mut Parser)+'static>) {
100-
// }
101-
// ```
102-
//
103-
// Note that `p` (and `'a`) are not used in the
104-
// closure at all, but to meet the requirement that
105-
// the closure type `C: 'static` (so it can be coerced
106-
// to the object type), we get the requirement that
107-
// `'a: 'static` since `'a` appears in the closure
108-
// type `C`.
109-
//
110-
// A smarter fix might "prune" unused `func_substs` --
111-
// this would avoid breaking simple examples like
112-
// this, but would still break others (which might
113-
// indeed be invalid, depending on your POV). Pruning
114-
// would be a subtle process, since we have to see
115-
// what func/type parameters are used and unused,
116-
// taking into consideration UFCS and so forth.
117-
118-
for &upvar_ty in &substs.upvar_tys {
119-
compute_components(infcx, upvar_ty, out);
120-
}
121-
subtys.skip_current_subtree();
79+
match ty.sty {
80+
ty::TyClosure(_, ref substs) => {
81+
// FIXME(#27086). We do not accumulate from substs, since they
82+
// don't represent reachable data. This means that, in
83+
// practice, some of the lifetime parameters might not
84+
// be in scope when the body runs, so long as there is
85+
// no reachable data with that lifetime. For better or
86+
// worse, this is consistent with fn types, however,
87+
// which can also encapsulate data in this fashion
88+
// (though it's somewhat harder, and typically
89+
// requires virtual dispatch).
90+
//
91+
// Note that changing this (in a naive way, at least)
92+
// causes regressions for what appears to be perfectly
93+
// reasonable code like this:
94+
//
95+
// ```
96+
// fn foo<'a>(p: &Data<'a>) {
97+
// bar(|q: &mut Parser| q.read_addr())
98+
// }
99+
// fn bar(p: Box<FnMut(&mut Parser)+'static>) {
100+
// }
101+
// ```
102+
//
103+
// Note that `p` (and `'a`) are not used in the
104+
// closure at all, but to meet the requirement that
105+
// the closure type `C: 'static` (so it can be coerced
106+
// to the object type), we get the requirement that
107+
// `'a: 'static` since `'a` appears in the closure
108+
// type `C`.
109+
//
110+
// A smarter fix might "prune" unused `func_substs` --
111+
// this would avoid breaking simple examples like
112+
// this, but would still break others (which might
113+
// indeed be invalid, depending on your POV). Pruning
114+
// would be a subtle process, since we have to see
115+
// what func/type parameters are used and unused,
116+
// taking into consideration UFCS and so forth.
117+
118+
for &upvar_ty in &substs.upvar_tys {
119+
compute_components(infcx, upvar_ty, out);
122120
}
123-
ty::TyBareFn(..) | ty::TyTrait(..) => {
124-
subtys.skip_current_subtree();
121+
}
122+
123+
// Bare functions and traits are both binders. In the RFC,
124+
// this means we would add the bound regions to the "bound
125+
// regions list". In our representation, no such list is
126+
// maintained explicitly, because bound regions themselves can
127+
// be readily identified. However, because the outlives
128+
// relation did not used to be applied to fn/trait-object
129+
// arguments, we due wrap the resulting components in an
130+
// RFC1214 wrapper so we can issue warnings.
131+
ty::TyBareFn(..) | ty::TyTrait(..) => {
132+
// OutlivesFunction, OutlivesObject, OutlivesFragment
133+
let subcomponents = capture_components(infcx, ty);
134+
out.push(Component::RFC1214(subcomponents));
135+
}
136+
137+
// OutlivesTypeParameterEnv -- the actual checking that `X:'a`
138+
// is implied by the environment is done in regionck.
139+
ty::TyParam(p) => {
140+
out.push(Component::Param(p));
141+
}
142+
143+
// For projections, we prefer to generate an obligation like
144+
// `<P0 as Trait<P1...Pn>>::Foo: 'a`, because this gives the
145+
// regionck more ways to prove that it holds. However,
146+
// regionck is not (at least currently) prepared to deal with
147+
// higher-ranked regions that may appear in the
148+
// trait-ref. Therefore, if we see any higher-ranke regions,
149+
// we simply fallback to the most restrictive rule, which
150+
// requires that `Pi: 'a` for all `i`.
151+
ty::TyProjection(ref data) => {
152+
if !data.has_escaping_regions() {
153+
// best case: no escaping regions, so push the
154+
// projection and skip the subtree (thus generating no
155+
// constraints for Pi). This defers the choice between
156+
// the rules OutlivesProjectionEnv,
157+
// OutlivesProjectionTraitDef, and
158+
// OutlivesProjectionComponents to regionck.
159+
out.push(Component::Projection(*data));
160+
} else {
161+
// fallback case: hard code
162+
// OutlivesProjectionComponents. Continue walking
163+
// through and constrain Pi.
125164
let subcomponents = capture_components(infcx, ty);
126-
out.push(Component::RFC1214(subcomponents));
127-
}
128-
ty::TyParam(p) => {
129-
out.push(Component::Param(p));
130-
subtys.skip_current_subtree();
131-
}
132-
ty::TyProjection(ref data) => {
133-
// For projections, we prefer to generate an
134-
// obligation like `<P0 as Trait<P1...Pn>>::Foo: 'a`,
135-
// because this gives the regionck more ways to prove
136-
// that it holds. However, regionck is not (at least
137-
// currently) prepared to deal with higher-ranked
138-
// regions that may appear in the
139-
// trait-ref. Therefore, if we see any higher-ranke
140-
// regions, we simply fallback to the most restrictive
141-
// rule, which requires that `Pi: 'a` for all `i`.
142-
143-
if !data.has_escaping_regions() {
144-
// best case: no escaping regions, so push the
145-
// projection and skip the subtree (thus
146-
// generating no constraints for Pi).
147-
out.push(Component::Projection(*data));
148-
} else {
149-
// fallback case: continue walking through and
150-
// constrain Pi.
151-
let subcomponents = capture_components(infcx, ty);
152-
out.push(Component::EscapingProjection(subcomponents));
153-
}
154-
subtys.skip_current_subtree();
165+
out.push(Component::EscapingProjection(subcomponents));
155166
}
156-
ty::TyInfer(_) => {
157-
let ty = infcx.resolve_type_vars_if_possible(&ty);
158-
if let ty::TyInfer(infer_ty) = ty.sty {
159-
out.push(Component::UnresolvedInferenceVariable(infer_ty));
160-
} else {
161-
compute_components(infcx, ty, out);
162-
}
167+
}
168+
169+
// If we encounter an inference variable, try to resolve it
170+
// and proceed with resolved version. If we cannot resolve it,
171+
// then record the unresolved variable as a component.
172+
ty::TyInfer(_) => {
173+
let ty = infcx.resolve_type_vars_if_possible(&ty);
174+
if let ty::TyInfer(infer_ty) = ty.sty {
175+
out.push(Component::UnresolvedInferenceVariable(infer_ty));
176+
} else {
177+
compute_components(infcx, ty, out);
163178
}
179+
}
164180

165-
// Most types do not introduce any region binders, nor
166-
// involve any other subtle cases, and so the WF relation
167-
// simply constraints any regions referenced directly by
168-
// the type and then visits the types that are lexically
169-
// contained within. (The comments refer to relevant rules
170-
// from RFC1214.)
171-
ty::TyBool(..) | // OutlivesScalar
172-
ty::TyChar(..) | // OutlivesScalar
173-
ty::TyInt(..) | // OutlivesScalar
174-
ty::TyUint(..) | // OutlivesScalar
175-
ty::TyFloat(..) | // OutlivesScalar
176-
ty::TyEnum(..) | // OutlivesNominalType
177-
ty::TyStruct(..) | // OutlivesNominalType
178-
ty::TyBox(..) | // OutlivesNominalType (ish)
179-
ty::TyStr(..) | // OutlivesScalar (ish)
180-
ty::TyArray(..) | // ...
181-
ty::TySlice(..) | // ...
182-
ty::TyRawPtr(..) | // ...
183-
ty::TyRef(..) | // OutlivesReference
184-
ty::TyTuple(..) | // ...
185-
ty::TyError(..) => {
186-
push_region_constraints(out, ty.regions());
181+
// Most types do not introduce any region binders, nor
182+
// involve any other subtle cases, and so the WF relation
183+
// simply constraints any regions referenced directly by
184+
// the type and then visits the types that are lexically
185+
// contained within. (The comments refer to relevant rules
186+
// from RFC1214.)
187+
ty::TyBool(..) | // OutlivesScalar
188+
ty::TyChar(..) | // OutlivesScalar
189+
ty::TyInt(..) | // OutlivesScalar
190+
ty::TyUint(..) | // OutlivesScalar
191+
ty::TyFloat(..) | // OutlivesScalar
192+
ty::TyEnum(..) | // OutlivesNominalType
193+
ty::TyStruct(..) | // OutlivesNominalType
194+
ty::TyBox(..) | // OutlivesNominalType (ish)
195+
ty::TyStr(..) | // OutlivesScalar (ish)
196+
ty::TyArray(..) | // ...
197+
ty::TySlice(..) | // ...
198+
ty::TyRawPtr(..) | // ...
199+
ty::TyRef(..) | // OutlivesReference
200+
ty::TyTuple(..) | // ...
201+
ty::TyError(..) => {
202+
push_region_constraints(out, ty.regions());
203+
for subty in ty.walk_shallow() {
204+
compute_components(infcx, subty, out);
187205
}
188206
}
189207
}

0 commit comments

Comments
 (0)