Skip to content

Commit e77cc9c

Browse files
committed
elaborate T: 'a dependencies
1 parent ce340af commit e77cc9c

File tree

6 files changed

+212
-20
lines changed

6 files changed

+212
-20
lines changed

src/librustc/traits/util.rs

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
23
// file at the top-level directory of this distribution and at
34
// http://rust-lang.org/COPYRIGHT.
@@ -11,6 +12,7 @@
1112
use hir::def_id::DefId;
1213
use ty::subst::{Subst, Substs};
1314
use ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef};
15+
use ty::outlives::Component;
1416
use util::common::ErrorReported;
1517
use util::nodemap::FnvHashSet;
1618

@@ -166,27 +168,63 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> {
166168
ty::Predicate::ClosureKind(..) => {
167169
// Nothing to elaborate when waiting for a closure's kind to be inferred.
168170
}
169-
ty::Predicate::RegionOutlives(..) |
170-
ty::Predicate::TypeOutlives(..) => {
171-
// Currently, we do not "elaborate" predicates like
172-
// `'a : 'b` or `T : 'a`. We could conceivably do
173-
// more here. For example,
174-
//
175-
// &'a int : 'b
176-
//
177-
// implies that
178-
//
179-
// 'a : 'b
180-
//
181-
// and we could get even more if we took WF
182-
// constraints into account. For example,
183-
//
184-
// &'a &'b int : 'c
185-
//
186-
// implies that
171+
172+
ty::Predicate::RegionOutlives(..) => {
173+
// Nothing to elaborate from `'a: 'b`.
174+
}
175+
176+
ty::Predicate::TypeOutlives(ref data) => {
177+
// We know that `T: 'a` for some type `T`. We can
178+
// often elaborate this. For example, if we know that
179+
// `[U]: 'a`, that implies that `U: 'a`. Similarly, if
180+
// we know `&'a U: 'b`, then we know that `'a: 'b` and
181+
// `U: 'b`.
187182
//
188-
// 'b : 'a
189-
// 'a : 'c
183+
// We can basically ignore bound regions here. So for
184+
// example `for<'c> Foo<'a,'c>: 'b` can be elaborated to
185+
// `'a: 'b`.
186+
187+
// Ignore `for<'a> T: 'a` -- we might in the future
188+
// consider this as evidence that `Foo: 'static`, but
189+
// I'm a bit wary of such constructions and so for now
190+
// I want to be conservative. --nmatsakis
191+
let ty_max = data.skip_binder().0;
192+
let r_min = data.skip_binder().1;
193+
if r_min.is_bound() {
194+
return;
195+
}
196+
197+
let visited = &mut self.visited;
198+
self.stack.extend(
199+
tcx.outlives_components(ty_max)
200+
.into_iter()
201+
.filter_map(|component| match component {
202+
Component::Region(r) => if r.is_bound() {
203+
None
204+
} else {
205+
Some(ty::Predicate::RegionOutlives(
206+
ty::Binder(ty::OutlivesPredicate(r, r_min))))
207+
},
208+
209+
Component::Param(p) => {
210+
let ty = tcx.mk_param(p.idx, p.name);
211+
Some(ty::Predicate::TypeOutlives(
212+
ty::Binder(ty::OutlivesPredicate(ty, r_min))))
213+
},
214+
215+
Component::UnresolvedInferenceVariable(_) => {
216+
None
217+
},
218+
219+
Component::Projection(_) |
220+
Component::EscapingProjection(_) => {
221+
// We can probably do more here. This
222+
// corresponds to a case like `<T as
223+
// Foo<'a>>::U: 'b`.
224+
None
225+
},
226+
})
227+
.filter(|p| visited.insert(p)));
190228
}
191229
}
192230
}

src/test/compile-fail/issue-18937.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
// Copyright 2016 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+
// Regression test for #18937.
12+
113
use std::fmt;
214

315
#[derive(Debug)]
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2016 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+
#![allow(dead_code)]
12+
13+
// Test that we elaborate `Type: 'region` constraints and infer various important things.
14+
15+
trait Master<'a, T: ?Sized, U> {
16+
fn foo() where T: 'a;
17+
}
18+
19+
// `U::Item: 'a` does not imply that `U: 'a`
20+
impl<'a, U: Iterator> Master<'a, U::Item, U> for () {
21+
fn foo() where U: 'a { }
22+
//~^ ERROR parameter type `V` may not live long enough
23+
}
24+
25+
fn main() {
26+
println!("Hello, world!");
27+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2016 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+
#![allow(dead_code)]
12+
13+
// Test that we elaborate `Type: 'region` constraints and infer various important things.
14+
15+
trait Master<'a, T: ?Sized, U> {
16+
fn foo() where T: 'a;
17+
}
18+
19+
// `U: 'a` does not imply `V: 'a`
20+
impl<'a, U, V> Master<'a, U, V> for () {
21+
fn foo() where V: 'a { }
22+
//~^ ERROR parameter type `V` may not live long enough
23+
}
24+
25+
fn main() {
26+
println!("Hello, world!");
27+
}

src/test/run-pass/issue-18937-1.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2016 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+
// Test that we are able to type-check this example. In particular,
12+
// knowing that `T: 'a` allows us to deduce that `[U]: 'a` (because
13+
// when `T=[U]` it implies that `U: 'a`).
14+
//
15+
// Regr. test for live code we found in the wild when fixing #18937.
16+
17+
pub trait Leak<T : ?Sized> {
18+
fn leak<'a>(self) -> &'a T where T: 'a;
19+
}
20+
21+
impl<U> Leak<[U]> for Vec<U> {
22+
fn leak<'a>(mut self) -> &'a [U] where [U]: 'a {
23+
let r: *mut [U] = &mut self[..];
24+
std::mem::forget(self);
25+
unsafe { &mut *r }
26+
}
27+
}
28+
fn main() {
29+
println!("Hello, world!");
30+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright 2016 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+
#![allow(dead_code)]
12+
13+
// Test that we elaborate `Type: 'region` constraints and infer various important things.
14+
15+
trait Master<'a, T: ?Sized> {
16+
fn foo() where T: 'a;
17+
}
18+
19+
// [U]: 'a => U: 'a
20+
impl<'a, U> Master<'a, [U]> for () {
21+
fn foo() where U: 'a { }
22+
}
23+
24+
// &'b U: 'a => 'b: 'a, U: 'a
25+
impl<'a, 'b, U> Master<'a, &'b U> for () {
26+
fn foo() where 'b: 'a, U: 'a { }
27+
}
28+
29+
// &'b [U]: 'a => 'b: 'a, U: 'a
30+
impl<'a, 'b, U> Master<'a, &'b [U]> for () {
31+
fn foo() where 'b: 'a, U: 'a { }
32+
}
33+
34+
// Foo<'b>: 'a => 'b: 'a
35+
struct Foo<'a> { x: &'a () }
36+
impl<'a, 'b> Master<'a, Foo<'b>> for () {
37+
fn foo() where 'b: 'a { }
38+
}
39+
40+
// Bar<'b, T>: 'a => 'b: 'a, T: 'a
41+
struct Bar<'a, T: 'a> { x: &'a T }
42+
impl<'a, 'b, T> Master<'a, Bar<'b, T>> for () {
43+
fn foo() where 'b: 'a, T: 'a { }
44+
}
45+
46+
// fn(T): 'a => T: 'a
47+
impl<'a, T> Master<'a, fn(T)> for () {
48+
fn foo() where T: 'a { }
49+
}
50+
51+
// fn() -> T: 'a => T: 'a
52+
impl<'a, T> Master<'a, fn() -> T> for () {
53+
fn foo() where T: 'a { }
54+
}
55+
56+
fn main() {
57+
println!("Hello, world!");
58+
}

0 commit comments

Comments
 (0)