Skip to content

Commit 2305bbf

Browse files
committed
---
yaml --- r: 232361 b: refs/heads/try c: 9289552 h: refs/heads/master i: 232359: 0f038a1 v: v3
1 parent daf4f60 commit 2305bbf

File tree

8 files changed

+818
-63
lines changed

8 files changed

+818
-63
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: edeb4f1c86cbf6af8ef9874d4b3af50f721ea1b8
33
refs/heads/snap-stage3: 1af31d4974e33027a68126fa5a5a3c2c6491824f
4-
refs/heads/try: 4561607403e1595d5ecbf36716711bc0076506f0
4+
refs/heads/try: 928955296e28cea5045fb726d6e3fb47780f8c48
55
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
66
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
77
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try/src/librustc/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ pub mod middle {
130130
pub mod lang_items;
131131
pub mod liveness;
132132
pub mod mem_categorization;
133+
pub mod outlives;
133134
pub mod pat_util;
134135
pub mod privacy;
135136
pub mod reachable;
@@ -144,6 +145,7 @@ pub mod middle {
144145
pub mod ty_match;
145146
pub mod ty_relate;
146147
pub mod ty_walk;
148+
pub mod wf;
147149
pub mod weak_lang_items;
148150
}
149151

branches/try/src/librustc/middle/free_region.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
//! This file defines
1212
13-
use middle::implicator::Implication;
13+
use middle::wf::ImpliedBound;
1414
use middle::ty::{self, FreeRegion};
1515
use util::common::can_reach;
1616
use util::nodemap::{FnvHashMap, FnvHashSet};
@@ -30,18 +30,19 @@ impl FreeRegionMap {
3030
FreeRegionMap { map: FnvHashMap(), statics: FnvHashSet() }
3131
}
3232

33-
pub fn relate_free_regions_from_implications<'tcx>(&mut self,
34-
implications: &[Implication<'tcx>])
33+
pub fn relate_free_regions_from_implied_bounds<'tcx>(&mut self,
34+
implied_bounds: &[ImpliedBound<'tcx>])
3535
{
36-
for implication in implications {
37-
debug!("implication: {:?}", implication);
38-
match *implication {
39-
Implication::RegionSubRegion(_, ty::ReFree(free_a), ty::ReFree(free_b)) => {
36+
debug!("relate_free_regions_from_implied_bounds()");
37+
for implied_bound in implied_bounds {
38+
debug!("implied bound: {:?}", implied_bound);
39+
match *implied_bound {
40+
ImpliedBound::RegionSubRegion(ty::ReFree(free_a), ty::ReFree(free_b)) => {
4041
self.relate_free_regions(free_a, free_b);
4142
}
42-
Implication::RegionSubRegion(..) |
43-
Implication::RegionSubGeneric(..) |
44-
Implication::Predicate(..) => {
43+
ImpliedBound::RegionSubRegion(..) |
44+
ImpliedBound::RegionSubParam(..) |
45+
ImpliedBound::RegionSubProjection(..) => {
4546
}
4647
}
4748
}

branches/try/src/librustc/middle/implicator.rs

Lines changed: 1 addition & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,7 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
278278

279279
for predicate in predicates.predicates.as_slice() {
280280
match *predicate {
281-
ty::Predicate::Trait(ref data) => {
282-
self.accumulate_from_assoc_types_transitive(data);
283-
}
281+
ty::Predicate::Trait(..) => { }
284282
ty::Predicate::Equate(..) => { }
285283
ty::Predicate::Projection(..) => { }
286284
ty::Predicate::RegionOutlives(ref data) => {
@@ -349,53 +347,6 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
349347
}
350348
}
351349

352-
/// Given that there is a requirement that `Foo<X> : 'a`, where
353-
/// `Foo` is declared like `struct Foo<T> where T : SomeTrait`,
354-
/// this code finds all the associated types defined in
355-
/// `SomeTrait` (and supertraits) and adds a requirement that `<X
356-
/// as SomeTrait>::N : 'a` (where `N` is some associated type
357-
/// defined in `SomeTrait`). This rule only applies to
358-
/// trait-bounds that are not higher-ranked, because we cannot
359-
/// project out of a HRTB. This rule helps code using associated
360-
/// types to compile, see Issue #22246 for an example.
361-
fn accumulate_from_assoc_types_transitive(&mut self,
362-
data: &ty::PolyTraitPredicate<'tcx>)
363-
{
364-
debug!("accumulate_from_assoc_types_transitive({:?})",
365-
data);
366-
367-
for poly_trait_ref in traits::supertraits(self.tcx(), data.to_poly_trait_ref()) {
368-
match self.tcx().no_late_bound_regions(&poly_trait_ref) {
369-
Some(trait_ref) => { self.accumulate_from_assoc_types(trait_ref); }
370-
None => { }
371-
}
372-
}
373-
}
374-
375-
fn accumulate_from_assoc_types(&mut self,
376-
trait_ref: ty::TraitRef<'tcx>)
377-
{
378-
debug!("accumulate_from_assoc_types({:?})",
379-
trait_ref);
380-
381-
let trait_def_id = trait_ref.def_id;
382-
let trait_def = self.tcx().lookup_trait_def(trait_def_id);
383-
let assoc_type_projections: Vec<_> =
384-
trait_def.associated_type_names
385-
.iter()
386-
.map(|&name| self.tcx().mk_projection(trait_ref.clone(), name))
387-
.collect();
388-
debug!("accumulate_from_assoc_types: assoc_type_projections={:?}",
389-
assoc_type_projections);
390-
let tys = match self.fully_normalize(&assoc_type_projections) {
391-
Ok(tys) => { tys }
392-
Err(ErrorReported) => { return; }
393-
};
394-
for ty in tys {
395-
self.accumulate_from_ty(ty);
396-
}
397-
}
398-
399350
fn accumulate_from_object_ty(&mut self,
400351
ty: Ty<'tcx>,
401352
region_bound: ty::Region,
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// The outlines relation `T: 'a` or `'a: 'b`.
12+
13+
use middle::infer::InferCtxt;
14+
use middle::ty::{self, RegionEscape, Ty};
15+
16+
#[derive(Debug)]
17+
pub enum Component<'tcx> {
18+
Region(ty::Region),
19+
Param(ty::ParamTy),
20+
UnresolvedInferenceVariable(ty::InferTy),
21+
22+
// Projections like `T::Foo` are tricky because a constraint like
23+
// `T::Foo: 'a` can be satisfied in so many ways. There may be a
24+
// where-clause that says `T::Foo: 'a`, or the defining trait may
25+
// include a bound like `type Foo: 'static`, or -- in the most
26+
// conservative way -- we can prove that `T: 'a` (more generally,
27+
// that all components in the projection outlive `'a`). This code
28+
// is not in a position to judge which is the best technique, so
29+
// we just product the projection as a component and leave it to
30+
// the consumer to decide (but see `EscapingProjection` below).
31+
Projection(ty::ProjectionTy<'tcx>),
32+
33+
// In the case where a projection has escaping regions -- meaning
34+
// regions bound within the type itself -- we always use
35+
// the most conservative rule, which requires that all components
36+
// outlive the bound. So for example if we had a type like this:
37+
//
38+
// for<'a> Trait1< <T as Trait2<'a,'b>>::Foo >
39+
// ~~~~~~~~~~~~~~~~~~~~~~~~~
40+
//
41+
// then the inner projection (underlined) has an escaping region
42+
// `'a`. We consider that outer trait `'c` to meet a bound if `'b`
43+
// outlives `'b: 'c`, and we don't consider whether the trait
44+
// declares that `Foo: 'static` etc. Therefore, we just return the
45+
// free components of such a projection (in this case, `'b`).
46+
//
47+
// However, in the future, we may want to get smarter, and
48+
// actually return a "higher-ranked projection" here. Therefore,
49+
// we mark that these components are part of an escaping
50+
// projection, so that implied bounds code can avoid relying on
51+
// them. This gives us room to improve the regionck reasoning in
52+
// the future without breaking backwards compat.
53+
EscapingProjection(Vec<Component<'tcx>>),
54+
55+
RFC1214(Vec<Component<'tcx>>),
56+
}
57+
58+
/// Returns all the things that must outlive `'a` for the condition
59+
/// `ty0: 'a` to hold.
60+
pub fn components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
61+
ty0: Ty<'tcx>)
62+
-> Vec<Component<'tcx>> {
63+
let mut components = vec![];
64+
compute_components(infcx, ty0, &mut components);
65+
debug!("outlives({:?}) = {:?}", ty0, components);
66+
components
67+
}
68+
69+
fn compute_components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
70+
ty0: Ty<'tcx>,
71+
out: &mut Vec<Component<'tcx>>) {
72+
// Descend through the types, looking for the various "base"
73+
// components and collecting them into `out`. This is not written
74+
// with `collect()` because of the need to sometimes skip subtrees
75+
// in the `subtys` iterator (e.g., when encountering a
76+
// 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();
122+
}
123+
ty::TyBareFn(..) | ty::TyTrait(..) => {
124+
subtys.skip_current_subtree();
125+
let temp = capture_components(infcx, ty);
126+
out.push(Component::RFC1214(temp));
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 reions, 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 temp = capture_components(infcx, ty);
152+
out.push(Component::EscapingProjection(temp));
153+
}
154+
subtys.skip_current_subtree();
155+
}
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+
}
163+
}
164+
_ => {
165+
// for all other types, just constrain the regions and
166+
// keep walking to find any other types.
167+
push_region_constraints(out, ty.regions());
168+
}
169+
}
170+
}
171+
}
172+
173+
fn capture_components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
174+
ty: Ty<'tcx>)
175+
-> Vec<Component<'tcx>> {
176+
let mut temp = vec![];
177+
push_region_constraints(&mut temp, ty.regions());
178+
for subty in ty.walk_shallow() {
179+
compute_components(infcx, subty, &mut temp);
180+
}
181+
temp
182+
}
183+
184+
fn push_region_constraints<'tcx>(out: &mut Vec<Component<'tcx>>, regions: Vec<ty::Region>) {
185+
for r in regions {
186+
if !r.is_bound() {
187+
out.push(Component::Region(r));
188+
}
189+
}
190+
}
191+

0 commit comments

Comments
 (0)