elaborate T: 'a
dependencies
This commit is contained in:
parent
ce340af738
commit
e77cc9c983
6 changed files with 212 additions and 20 deletions
|
@ -1,3 +1,4 @@
|
|||
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
|
@ -11,6 +12,7 @@
|
|||
use hir::def_id::DefId;
|
||||
use ty::subst::{Subst, Substs};
|
||||
use ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef};
|
||||
use ty::outlives::Component;
|
||||
use util::common::ErrorReported;
|
||||
use util::nodemap::FnvHashSet;
|
||||
|
||||
|
@ -166,27 +168,63 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> {
|
|||
ty::Predicate::ClosureKind(..) => {
|
||||
// Nothing to elaborate when waiting for a closure's kind to be inferred.
|
||||
}
|
||||
ty::Predicate::RegionOutlives(..) |
|
||||
ty::Predicate::TypeOutlives(..) => {
|
||||
// Currently, we do not "elaborate" predicates like
|
||||
// `'a : 'b` or `T : 'a`. We could conceivably do
|
||||
// more here. For example,
|
||||
|
||||
ty::Predicate::RegionOutlives(..) => {
|
||||
// Nothing to elaborate from `'a: 'b`.
|
||||
}
|
||||
|
||||
ty::Predicate::TypeOutlives(ref data) => {
|
||||
// We know that `T: 'a` for some type `T`. We can
|
||||
// often elaborate this. For example, if we know that
|
||||
// `[U]: 'a`, that implies that `U: 'a`. Similarly, if
|
||||
// we know `&'a U: 'b`, then we know that `'a: 'b` and
|
||||
// `U: 'b`.
|
||||
//
|
||||
// &'a int : 'b
|
||||
//
|
||||
// implies that
|
||||
//
|
||||
// 'a : 'b
|
||||
//
|
||||
// and we could get even more if we took WF
|
||||
// constraints into account. For example,
|
||||
//
|
||||
// &'a &'b int : 'c
|
||||
//
|
||||
// implies that
|
||||
//
|
||||
// 'b : 'a
|
||||
// 'a : 'c
|
||||
// We can basically ignore bound regions here. So for
|
||||
// example `for<'c> Foo<'a,'c>: 'b` can be elaborated to
|
||||
// `'a: 'b`.
|
||||
|
||||
// Ignore `for<'a> T: 'a` -- we might in the future
|
||||
// consider this as evidence that `Foo: 'static`, but
|
||||
// I'm a bit wary of such constructions and so for now
|
||||
// I want to be conservative. --nmatsakis
|
||||
let ty_max = data.skip_binder().0;
|
||||
let r_min = data.skip_binder().1;
|
||||
if r_min.is_bound() {
|
||||
return;
|
||||
}
|
||||
|
||||
let visited = &mut self.visited;
|
||||
self.stack.extend(
|
||||
tcx.outlives_components(ty_max)
|
||||
.into_iter()
|
||||
.filter_map(|component| match component {
|
||||
Component::Region(r) => if r.is_bound() {
|
||||
None
|
||||
} else {
|
||||
Some(ty::Predicate::RegionOutlives(
|
||||
ty::Binder(ty::OutlivesPredicate(r, r_min))))
|
||||
},
|
||||
|
||||
Component::Param(p) => {
|
||||
let ty = tcx.mk_param(p.idx, p.name);
|
||||
Some(ty::Predicate::TypeOutlives(
|
||||
ty::Binder(ty::OutlivesPredicate(ty, r_min))))
|
||||
},
|
||||
|
||||
Component::UnresolvedInferenceVariable(_) => {
|
||||
None
|
||||
},
|
||||
|
||||
Component::Projection(_) |
|
||||
Component::EscapingProjection(_) => {
|
||||
// We can probably do more here. This
|
||||
// corresponds to a case like `<T as
|
||||
// Foo<'a>>::U: 'b`.
|
||||
None
|
||||
},
|
||||
})
|
||||
.filter(|p| visited.insert(p)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,15 @@
|
|||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Regression test for #18937.
|
||||
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
27
src/test/compile-fail/traits-elaborate-type-region-proj.rs
Normal file
27
src/test/compile-fail/traits-elaborate-type-region-proj.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
// Test that we elaborate `Type: 'region` constraints and infer various important things.
|
||||
|
||||
trait Master<'a, T: ?Sized, U> {
|
||||
fn foo() where T: 'a;
|
||||
}
|
||||
|
||||
// `U::Item: 'a` does not imply that `U: 'a`
|
||||
impl<'a, U: Iterator> Master<'a, U::Item, U> for () {
|
||||
fn foo() where U: 'a { }
|
||||
//~^ ERROR parameter type `V` may not live long enough
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
// Test that we elaborate `Type: 'region` constraints and infer various important things.
|
||||
|
||||
trait Master<'a, T: ?Sized, U> {
|
||||
fn foo() where T: 'a;
|
||||
}
|
||||
|
||||
// `U: 'a` does not imply `V: 'a`
|
||||
impl<'a, U, V> Master<'a, U, V> for () {
|
||||
fn foo() where V: 'a { }
|
||||
//~^ ERROR parameter type `V` may not live long enough
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
30
src/test/run-pass/issue-18937-1.rs
Normal file
30
src/test/run-pass/issue-18937-1.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that we are able to type-check this example. In particular,
|
||||
// knowing that `T: 'a` allows us to deduce that `[U]: 'a` (because
|
||||
// when `T=[U]` it implies that `U: 'a`).
|
||||
//
|
||||
// Regr. test for live code we found in the wild when fixing #18937.
|
||||
|
||||
pub trait Leak<T : ?Sized> {
|
||||
fn leak<'a>(self) -> &'a T where T: 'a;
|
||||
}
|
||||
|
||||
impl<U> Leak<[U]> for Vec<U> {
|
||||
fn leak<'a>(mut self) -> &'a [U] where [U]: 'a {
|
||||
let r: *mut [U] = &mut self[..];
|
||||
std::mem::forget(self);
|
||||
unsafe { &mut *r }
|
||||
}
|
||||
}
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
58
src/test/run-pass/traits-elaborate-type-region.rs
Normal file
58
src/test/run-pass/traits-elaborate-type-region.rs
Normal file
|
@ -0,0 +1,58 @@
|
|||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
// Test that we elaborate `Type: 'region` constraints and infer various important things.
|
||||
|
||||
trait Master<'a, T: ?Sized> {
|
||||
fn foo() where T: 'a;
|
||||
}
|
||||
|
||||
// [U]: 'a => U: 'a
|
||||
impl<'a, U> Master<'a, [U]> for () {
|
||||
fn foo() where U: 'a { }
|
||||
}
|
||||
|
||||
// &'b U: 'a => 'b: 'a, U: 'a
|
||||
impl<'a, 'b, U> Master<'a, &'b U> for () {
|
||||
fn foo() where 'b: 'a, U: 'a { }
|
||||
}
|
||||
|
||||
// &'b [U]: 'a => 'b: 'a, U: 'a
|
||||
impl<'a, 'b, U> Master<'a, &'b [U]> for () {
|
||||
fn foo() where 'b: 'a, U: 'a { }
|
||||
}
|
||||
|
||||
// Foo<'b>: 'a => 'b: 'a
|
||||
struct Foo<'a> { x: &'a () }
|
||||
impl<'a, 'b> Master<'a, Foo<'b>> for () {
|
||||
fn foo() where 'b: 'a { }
|
||||
}
|
||||
|
||||
// Bar<'b, T>: 'a => 'b: 'a, T: 'a
|
||||
struct Bar<'a, T: 'a> { x: &'a T }
|
||||
impl<'a, 'b, T> Master<'a, Bar<'b, T>> for () {
|
||||
fn foo() where 'b: 'a, T: 'a { }
|
||||
}
|
||||
|
||||
// fn(T): 'a => T: 'a
|
||||
impl<'a, T> Master<'a, fn(T)> for () {
|
||||
fn foo() where T: 'a { }
|
||||
}
|
||||
|
||||
// fn() -> T: 'a => T: 'a
|
||||
impl<'a, T> Master<'a, fn() -> T> for () {
|
||||
fn foo() where T: 'a { }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
Loading…
Add table
Reference in a new issue