From 44df36567b91388e677ff29f6ac3fe5a4f9ab001 Mon Sep 17 00:00:00 2001 From: toidiu Date: Thu, 26 Jul 2018 20:25:27 -0400 Subject: [PATCH 1/5] feature gate for inferring 'static lifetimes --- src/librustc_typeck/outlives/utils.rs | 31 ++++++++++++++----- src/libsyntax/feature_gate.rs | 9 ++++++ .../dont-infer-static.rs | 23 ++++++++++++++ .../dont-infer-static.stderr | 17 ++++++++++ .../rfc-2093-infer-outlives/infer-static.rs | 25 +++++++++++++++ .../infer-static.stderr | 12 +++++++ 6 files changed, 110 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/rfc-2093-infer-outlives/dont-infer-static.rs create mode 100644 src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr create mode 100644 src/test/ui/rfc-2093-infer-outlives/infer-static.rs create mode 100644 src/test/ui/rfc-2093-infer-outlives/infer-static.stderr diff --git a/src/librustc_typeck/outlives/utils.rs b/src/librustc_typeck/outlives/utils.rs index 5cb1822b04e9d..0d833c50d7e3b 100644 --- a/src/librustc_typeck/outlives/utils.rs +++ b/src/librustc_typeck/outlives/utils.rs @@ -27,7 +27,7 @@ pub fn insert_outlives_predicate<'tcx>( ) { // If the `'a` region is bound within the field type itself, we // don't want to propagate this constraint to the header. - if !is_free_region(outlived_region) { + if !is_free_region(tcx, outlived_region) { return; } @@ -120,7 +120,7 @@ pub fn insert_outlives_predicate<'tcx>( } UnpackedKind::Lifetime(r) => { - if !is_free_region(r) { + if !is_free_region(tcx, r) { return; } required_predicates.insert(ty::OutlivesPredicate(kind, outlived_region)); @@ -128,19 +128,36 @@ pub fn insert_outlives_predicate<'tcx>( } } -fn is_free_region(region: Region<'_>) -> bool { +fn is_free_region<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, region: Region<'_>) -> bool { // First, screen for regions that might appear in a type header. match region { - // *These* correspond to `T: 'a` relationships where `'a` is - // either declared on the type or `'static`: + // These correspond to `T: 'a` relationships: // // struct Foo<'a, T> { // field: &'a T, // this would generate a ReEarlyBound referencing `'a` - // field2: &'static T, // this would generate a ReStatic // } // // We care about these, so fall through. - RegionKind::ReStatic | RegionKind::ReEarlyBound(_) => true, + RegionKind::ReEarlyBound(_) => true, + + // These correspond to `T: 'static` relationships which can be + // rather surprising. We are therefore putting this behind a + // feature flag: + // + // struct Foo<'a, T> { + // field: &'static T, // this would generate a ReStatic + // } + RegionKind::ReStatic => { + if tcx + .sess + .features_untracked() + .infer_static_outlives_requirements + { + true + } else { + false + } + } // Late-bound regions can appear in `fn` types: // diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 30137439e7740..087fec097191b 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -396,6 +396,9 @@ declare_features! ( // Infer outlives requirements; RFC 2093 (active, infer_outlives_requirements, "1.26.0", Some(44493), None), + // Infer outlives requirements; RFC 2093 + (active, infer_static_outlives_requirements, "1.26.0", Some(44493), None), + // Multiple patterns with `|` in `if let` and `while let` (active, if_while_or_patterns, "1.26.0", Some(48215), None), @@ -1057,6 +1060,12 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG "infer outlives requirements is an experimental feature", cfg_fn!(infer_outlives_requirements))), + // RFC #2093 + ("infer_static_outlives_requirements", Normal, Gated(Stability::Unstable, + "infer_static_outlives_requirements", + "infer 'static lifetime requirements", + cfg_fn!(infer_static_outlives_requirements))), + // RFC 2070 ("panic_implementation", Normal, Gated(Stability::Unstable, "panic_implementation", diff --git a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.rs b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.rs new file mode 100644 index 0000000000000..c70170112778f --- /dev/null +++ b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.rs @@ -0,0 +1,23 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-linelength + +#![feature(infer_outlives_requirements)] + +struct Foo { + bar: Bar //~ ERROR 16:5: 16:16: the parameter type `U` may not live long enough [E0310] +} +struct Bar { + x: T, +} + +fn main() {} + diff --git a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr new file mode 100644 index 0000000000000..38cc215ea99c4 --- /dev/null +++ b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr @@ -0,0 +1,17 @@ +error[E0310]: the parameter type `U` may not live long enough + --> $DIR/dont-infer-static.rs:16:5 + | +LL | struct Foo { + | - help: consider adding an explicit lifetime bound `U: 'static`... +LL | bar: Bar //~ ERROR 16:5: 16:16: the parameter type `U` may not live long enough [E0310] + | ^^^^^^^^^^^ + | +note: ...so that the type `U` will meet its required lifetime bounds + --> $DIR/dont-infer-static.rs:16:5 + | +LL | bar: Bar //~ ERROR 16:5: 16:16: the parameter type `U` may not live long enough [E0310] + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/rfc-2093-infer-outlives/infer-static.rs b/src/test/ui/rfc-2093-infer-outlives/infer-static.rs new file mode 100644 index 0000000000000..bdcf31491aede --- /dev/null +++ b/src/test/ui/rfc-2093-infer-outlives/infer-static.rs @@ -0,0 +1,25 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] +#![feature(infer_outlives_requirements)] +#![feature(infer_static_outlives_requirements)] + +#[rustc_outlives] +struct Foo { //~ ERROR 16:1: 18:2: rustc_outlives + bar: Bar +} +struct Bar { + x: T, +} + +fn main() {} + + diff --git a/src/test/ui/rfc-2093-infer-outlives/infer-static.stderr b/src/test/ui/rfc-2093-infer-outlives/infer-static.stderr new file mode 100644 index 0000000000000..f167e522df650 --- /dev/null +++ b/src/test/ui/rfc-2093-infer-outlives/infer-static.stderr @@ -0,0 +1,12 @@ +error: rustc_outlives + --> $DIR/infer-static.rs:16:1 + | +LL | / struct Foo { //~ ERROR 16:1: 18:2: rustc_outlives +LL | | bar: Bar +LL | | } + | |_^ + | + = note: U : 'static + +error: aborting due to previous error + From 429ae93c09055a1fde14ef4cbf807bdfcbe65584 Mon Sep 17 00:00:00 2001 From: toidiu Date: Thu, 26 Jul 2018 20:32:01 -0400 Subject: [PATCH 2/5] some comment about not infering static lifetimes test --- src/test/ui/rfc-2093-infer-outlives/dont-infer-static.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.rs b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.rs index c70170112778f..72d5127c294dc 100644 --- a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.rs +++ b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.rs @@ -12,8 +12,14 @@ #![feature(infer_outlives_requirements)] +/* + * We don't infer `T: 'static` outlives relationships by default. + * Instead an additional feature gate `infer_static_outlives_requirements` + * is required. + */ + struct Foo { - bar: Bar //~ ERROR 16:5: 16:16: the parameter type `U` may not live long enough [E0310] + bar: Bar //~ ERROR 22:5: 22:16: the parameter type `U` may not live long enough [E0310] } struct Bar { x: T, From 0fd7fee5c639f8cdbec8c50e86316e19e61fbb5f Mon Sep 17 00:00:00 2001 From: toidiu Date: Thu, 26 Jul 2018 22:58:03 -0400 Subject: [PATCH 3/5] fix test and add feature gate test --- ...gate-infer_static_outlives_requirements.rs | 22 +++++++++++++++++++ ...-infer_static_outlives_requirements.stderr | 17 ++++++++++++++ .../dont-infer-static.stderr | 8 +++---- 3 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/feature-gate-infer_static_outlives_requirements.rs create mode 100644 src/test/ui/feature-gate-infer_static_outlives_requirements.stderr diff --git a/src/test/ui/feature-gate-infer_static_outlives_requirements.rs b/src/test/ui/feature-gate-infer_static_outlives_requirements.rs new file mode 100644 index 0000000000000..7b68449859e96 --- /dev/null +++ b/src/test/ui/feature-gate-infer_static_outlives_requirements.rs @@ -0,0 +1,22 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Needs an explicit where clause stating outlives condition. (RFC 2093) + +// Type T needs to outlive lifetime 'static. +struct Foo { + bar: Bar //~ ERROR 15:5: 15:16: the parameter type `U` may not live long enough [E0310] +} +struct Bar { + x: T, +} + + +fn main() { } diff --git a/src/test/ui/feature-gate-infer_static_outlives_requirements.stderr b/src/test/ui/feature-gate-infer_static_outlives_requirements.stderr new file mode 100644 index 0000000000000..13022b901a76f --- /dev/null +++ b/src/test/ui/feature-gate-infer_static_outlives_requirements.stderr @@ -0,0 +1,17 @@ +error[E0310]: the parameter type `U` may not live long enough + --> $DIR/feature-gate-infer_static_outlives_requirements.rs:15:5 + | +LL | struct Foo { + | - help: consider adding an explicit lifetime bound `U: 'static`... +LL | bar: Bar //~ ERROR 15:5: 15:16: the parameter type `U` may not live long enough [E0310] + | ^^^^^^^^^^^ + | +note: ...so that the type `U` will meet its required lifetime bounds + --> $DIR/feature-gate-infer_static_outlives_requirements.rs:15:5 + | +LL | bar: Bar //~ ERROR 15:5: 15:16: the parameter type `U` may not live long enough [E0310] + | ^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr index 38cc215ea99c4..775ac215e190d 100644 --- a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr @@ -1,15 +1,15 @@ error[E0310]: the parameter type `U` may not live long enough - --> $DIR/dont-infer-static.rs:16:5 + --> $DIR/dont-infer-static.rs:22:5 | LL | struct Foo { | - help: consider adding an explicit lifetime bound `U: 'static`... -LL | bar: Bar //~ ERROR 16:5: 16:16: the parameter type `U` may not live long enough [E0310] +LL | bar: Bar //~ ERROR 22:5: 22:16: the parameter type `U` may not live long enough [E0310] | ^^^^^^^^^^^ | note: ...so that the type `U` will meet its required lifetime bounds - --> $DIR/dont-infer-static.rs:16:5 + --> $DIR/dont-infer-static.rs:22:5 | -LL | bar: Bar //~ ERROR 16:5: 16:16: the parameter type `U` may not live long enough [E0310] +LL | bar: Bar //~ ERROR 22:5: 22:16: the parameter type `U` may not live long enough [E0310] | ^^^^^^^^^^^ error: aborting due to previous error From 3bc6becf8bfb63492f738ab011c7edaf6fc8a298 Mon Sep 17 00:00:00 2001 From: toidiu Date: Fri, 27 Jul 2018 00:02:58 -0400 Subject: [PATCH 4/5] fix tidy --- src/test/ui/rfc-2093-infer-outlives/infer-static.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/ui/rfc-2093-infer-outlives/infer-static.rs b/src/test/ui/rfc-2093-infer-outlives/infer-static.rs index bdcf31491aede..aeca18c24b3db 100644 --- a/src/test/ui/rfc-2093-infer-outlives/infer-static.rs +++ b/src/test/ui/rfc-2093-infer-outlives/infer-static.rs @@ -22,4 +22,3 @@ struct Bar { fn main() {} - From 130e3ab31b28c9839e2f04c98c4b62c6f1c215a3 Mon Sep 17 00:00:00 2001 From: toidiu Date: Fri, 27 Jul 2018 10:18:06 -0400 Subject: [PATCH 5/5] add section in book --- .../infer-static-outlives-requirements.md | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/doc/unstable-book/src/language-features/infer-static-outlives-requirements.md diff --git a/src/doc/unstable-book/src/language-features/infer-static-outlives-requirements.md b/src/doc/unstable-book/src/language-features/infer-static-outlives-requirements.md new file mode 100644 index 0000000000000..f50472fb41e31 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/infer-static-outlives-requirements.md @@ -0,0 +1,45 @@ +# `infer_static_outlives_requirements` + +The tracking issue for this feature is: [#44493] + +[#44493]: https://github.com/rust-lang/rust/issues/44493 + +------------------------ +The `infer_static_outlives_requirements` feature indicates that certain +`'static` outlives requirements can be infered by the compiler rather than +stating them explicitly. + +Note: It is an accompanying feature to `infer_outlives_requirements`, +which must be enabled to infer outlives requirements. + +For example, currently generic struct definitions that contain +references, require where-clauses of the form T: 'static. By using +this feature the outlives predicates will be infered, although +they may still be written explicitly. + +```rust,ignore (pseudo-Rust) +struct Foo where U: 'static { // <-- currently required + bar: Bar +} +struct Bar { + x: T, +} +``` + + +## Examples: + +```rust,ignore (pseudo-Rust) +#![feature(infer_outlives_requirements)] +#![feature(infer_static_outlives_requirements)] + +#[rustc_outlives] +// Implicitly infer U: 'static +struct Foo { + bar: Bar +} +struct Bar { + x: T, +} +``` +