Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[beta] back out #53793 - stabilize outlives requirements #54877

Merged
merged 2 commits into from
Oct 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# `infer_outlives_requirements`

The tracking issue for this feature is: [#44493]

[#44493]: https://github.com/rust-lang/rust/issues/44493

------------------------
The `infer_outlives_requirements` feature indicates that certain
outlives requirements can be inferred by the compiler rather than
stating them explicitly.

For example, currently generic struct definitions that contain
references, require where-clauses of the form T: 'a. By using
this feature the outlives predicates will be inferred, although
they may still be written explicitly.

```rust,ignore (pseudo-Rust)
struct Foo<'a, T>
where T: 'a // <-- currently required
{
bar: &'a T,
}
```


## Examples:


```rust,ignore (pseudo-Rust)
#![feature(infer_outlives_requirements)]

// Implicitly infer T: 'a
struct Foo<'a, T> {
bar: &'a T,
}
```

```rust,ignore (pseudo-Rust)
#![feature(infer_outlives_requirements)]

// Implicitly infer `U: 'b`
struct Foo<'b, U> {
bar: Bar<'b, U>
}

struct Bar<'a, T> where T: 'a {
x: &'a (),
y: T,
}
```

```rust,ignore (pseudo-Rust)
#![feature(infer_outlives_requirements)]

// Implicitly infer `b': 'a`
struct Foo<'a, 'b, T> {
x: &'a &'b T
}
```

```rust,ignore (pseudo-Rust)
#![feature(infer_outlives_requirements)]

// Implicitly infer `<T as std::iter::Iterator>::Item : 'a`
struct Foo<'a, T: Iterator> {
bar: &'a T::Item
```
1 change: 1 addition & 0 deletions src/liballoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
#![cfg_attr(not(test), feature(fn_traits))]
#![cfg_attr(not(test), feature(generator_trait))]
#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![cfg_attr(test, feature(test))]

#![feature(allocator_api)]
Expand Down
1 change: 1 addition & 0 deletions src/liballoc_jemalloc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#![feature(libc)]
#![feature(linkage)]
#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(staged_api)]
#![feature(rustc_attrs)]
#![cfg_attr(dummy_jemalloc, allow(dead_code, unused_extern_crates))]
Expand Down
1 change: 1 addition & 0 deletions src/liballoc_system/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#![feature(allocator_api)]
#![feature(core_intrinsics)]
#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(staged_api)]
#![feature(rustc_attrs)]
#![cfg_attr(any(unix, target_os = "cloudabi", target_os = "redox"), feature(libc))]
Expand Down
1 change: 1 addition & 0 deletions src/libarena/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#![feature(core_intrinsics)]
#![feature(dropck_eyepatch)]
#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(raw_vec_internals)]
#![cfg_attr(test, feature(test))]

Expand Down
1 change: 1 addition & 0 deletions src/libcore/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
#![feature(link_llvm_intrinsics)]
#![feature(never_type)]
#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(exhaustive_patterns)]
#![feature(macro_at_most_once_rep)]
#![feature(no_core)]
Expand Down
1 change: 1 addition & 0 deletions src/libfmt_macros/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
test(attr(deny(warnings))))]

#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]

pub use self::Piece::*;
pub use self::Position::*;
Expand Down
1 change: 1 addition & 0 deletions src/libgraphviz/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@
test(attr(allow(unused_variables), deny(warnings))))]

#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(str_escape)]

use self::LabelText::*;
Expand Down
1 change: 1 addition & 0 deletions src/libpanic_abort/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#![feature(core_intrinsics)]
#![feature(libc)]
#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(panic_runtime)]
#![feature(staged_api)]
#![feature(rustc_attrs)]
Expand Down
1 change: 1 addition & 0 deletions src/libpanic_unwind/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#![feature(lang_items)]
#![feature(libc)]
#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(panic_unwind)]
#![feature(raw)]
#![feature(staged_api)]
Expand Down
1 change: 1 addition & 0 deletions src/libproc_macro/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))]

#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(rustc_private)]
#![feature(staged_api)]
#![feature(lang_items)]
Expand Down
1 change: 1 addition & 0 deletions src/libprofiler_builtins/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@
issue = "0")]
#![allow(unused_features)]
#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(staged_api)]
90 changes: 38 additions & 52 deletions src/librustc/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1232,54 +1232,41 @@ let x: i32 = "I am not a number!";
"##,

E0309: r##"
The type definition contains some field whose type
requires an outlives annotation. Outlives annotations
(e.g., `T: 'a`) are used to guarantee that all the data in T is valid
for at least the lifetime `'a`. This scenario most commonly
arises when the type contains an associated type reference
like `<T as SomeTrait<'a>>::Output`, as shown in this example:
Types in type definitions have lifetimes associated with them that represent
how long the data stored within them is guaranteed to be live. This lifetime
must be as long as the data needs to be alive, and missing the constraint that
denotes this will cause this error.

```compile_fail,E0309
// This won't compile because the applicable impl of
// `SomeTrait` (below) requires that `T: 'a`, but the struct does
// not have a matching where-clause.
// This won't compile because T is not constrained, meaning the data
// stored in it is not guaranteed to last as long as the reference
struct Foo<'a, T> {
foo: <T as SomeTrait<'a>>::Output,
}

trait SomeTrait<'a> {
type Output;
}

impl<'a, T> SomeTrait<'a> for T
where
T: 'a,
{
type Output = u32;
foo: &'a T
}
```

Here, the where clause `T: 'a` that appears on the impl is not known to be
satisfied on the struct. To make this example compile, you have to add
a where-clause like `T: 'a` to the struct definition:
This will compile, because it has the constraint on the type parameter:

```
struct Foo<'a, T>
where
T: 'a,
{
foo: <T as SomeTrait<'a>>::Output
struct Foo<'a, T: 'a> {
foo: &'a T
}
```

trait SomeTrait<'a> {
type Output;
To see why this is important, consider the case where `T` is itself a reference
(e.g., `T = &str`). If we don't include the restriction that `T: 'a`, the
following code would be perfectly legal:

```compile_fail,E0309
struct Foo<'a, T> {
foo: &'a T
}

impl<'a, T> SomeTrait<'a> for T
where
T: 'a,
{
type Output = u32;
fn main() {
let v = "42".to_string();
let f = Foo{foo: &v};
drop(v);
println!("{}", f.foo); // but we've already dropped v!
}
```
"##,
Expand Down Expand Up @@ -1478,31 +1465,30 @@ A reference has a longer lifetime than the data it references.
Erroneous code example:

```compile_fail,E0491
trait SomeTrait<'a> {
type Output;
// struct containing a reference requires a lifetime parameter,
// because the data the reference points to must outlive the struct (see E0106)
struct Struct<'a> {
ref_i32: &'a i32,
}

impl<'a, T> SomeTrait<'a> for T {
type Output = &'a T; // compile error E0491
// However, a nested struct like this, the signature itself does not tell
// whether 'a outlives 'b or the other way around.
// So it could be possible that 'b of reference outlives 'a of the data.
struct Nested<'a, 'b> {
ref_struct: &'b Struct<'a>, // compile error E0491
}
```

Here, the problem is that a reference type like `&'a T` is only valid
if all the data in T outlives the lifetime `'a`. But this impl as written
is applicable to any lifetime `'a` and any type `T` -- we have no guarantee
that `T` outlives `'a`. To fix this, you can add a where clause like
`where T: 'a`.
To fix this issue, you can specify a bound to the lifetime like below:

```
trait SomeTrait<'a> {
type Output;
struct Struct<'a> {
ref_i32: &'a i32,
}

impl<'a, T> SomeTrait<'a> for T
where
T: 'a,
{
type Output = &'a T; // compile error E0491
// 'a: 'b means 'a outlives 'b
struct Nested<'a: 'b, 'b> {
ref_struct: &'b Struct<'a>,
}
```
"##,
Expand Down
1 change: 1 addition & 0 deletions src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
#![feature(exhaustive_patterns)]
#![feature(extern_types)]
#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(non_exhaustive)]
#![feature(proc_macro_internals)]
#![feature(quote)]
Expand Down
1 change: 1 addition & 0 deletions src/librustc_allocator/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
// except according to those terms.

#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(rustc_private)]

#[macro_use] extern crate log;
Expand Down
1 change: 1 addition & 0 deletions src/librustc_apfloat/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#![forbid(unsafe_code)]

#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(try_from)]
// See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
#[allow(unused_extern_crates)]
Expand Down
1 change: 1 addition & 0 deletions src/librustc_asan/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#![sanitizer_runtime]
#![feature(alloc_system)]
#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(sanitizer_runtime)]
#![feature(staged_api)]
#![no_std]
Expand Down
1 change: 1 addition & 0 deletions src/librustc_borrowck/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#![allow(non_camel_case_types)]

#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(quote)]

#![recursion_limit="256"]
Expand Down
1 change: 1 addition & 0 deletions src/librustc_codegen_llvm/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#![allow(unused_attributes)]
#![feature(libc)]
#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(quote)]
#![feature(range_contains)]
#![feature(rustc_diagnostic_macros)]
Expand Down
1 change: 1 addition & 0 deletions src/librustc_codegen_utils/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#![feature(box_syntax)]
#![feature(custom_attribute)]
#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![allow(unused_attributes)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
Expand Down
1 change: 1 addition & 0 deletions src/librustc_cratesio_shim/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#![allow(unused_extern_crates)]

#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]

extern crate bitflags;
extern crate log;
Expand Down
1 change: 1 addition & 0 deletions src/librustc_data_structures/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#![feature(optin_builtin_traits)]
#![cfg_attr(stage0, feature(macro_vis_matcher))]
#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(allow_internal_unstable)]
#![feature(vec_resize_with)]

Expand Down
1 change: 1 addition & 0 deletions src/librustc_driver/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#![feature(box_syntax)]
#![cfg_attr(unix, feature(libc))]
#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(option_replace)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
Expand Down
1 change: 1 addition & 0 deletions src/librustc_errors/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#![feature(range_contains)]
#![cfg_attr(unix, feature(libc))]
#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(optin_builtin_traits)]

extern crate atty;
Expand Down
1 change: 1 addition & 0 deletions src/librustc_incremental/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
html_root_url = "https://doc.rust-lang.org/nightly/")]

#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(specialization)]

#![recursion_limit="256"]
Expand Down
1 change: 1 addition & 0 deletions src/librustc_lint/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#![feature(box_syntax)]
#![cfg_attr(stage0, feature(macro_vis_matcher))]
#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
#![feature(macro_at_most_once_rep)]
Expand Down
1 change: 1 addition & 0 deletions src/librustc_llvm/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
// except according to those terms.

#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(static_nobundle)]

#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
Expand Down
1 change: 1 addition & 0 deletions src/librustc_lsan/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#![sanitizer_runtime]
#![feature(alloc_system)]
#![cfg_attr(not(stage0), feature(nll))]
#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(sanitizer_runtime)]
#![feature(staged_api)]
#![no_std]
Expand Down
Loading