diff options
Diffstat (limited to 'src/test/ui/nll/ty-outlives')
43 files changed, 2762 insertions, 0 deletions
diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.rs b/src/test/ui/nll/ty-outlives/impl-trait-captures.rs new file mode 100644 index 000000000..67b31b8bc --- /dev/null +++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.rs @@ -0,0 +1,15 @@ +// compile-flags:-Zverbose + +#![allow(warnings)] + +trait Foo<'a> { +} + +impl<'a, T> Foo<'a> for T { } + +fn foo<'a, T>(x: &T) -> impl Foo<'a> { + x + //~^ ERROR captures lifetime that does not appear in bounds +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr new file mode 100644 index 000000000..330c6fafa --- /dev/null +++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -0,0 +1,16 @@ +error[E0700]: hidden type for `Opaque(DefId(0:11 ~ impl_trait_captures[1afc]::foo::{opaque#0}), [ReStatic, T, ReEarlyBound(0, 'a)])` captures lifetime that does not appear in bounds + --> $DIR/impl-trait-captures.rs:11:5 + | +LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { + | -- hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_)) T` captures the anonymous lifetime defined here +LL | x + | ^ + | +help: to declare that the `impl Trait` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_))` lifetime bound + | +LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_)) { + | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs b/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs new file mode 100644 index 000000000..68ccb51fc --- /dev/null +++ b/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs @@ -0,0 +1,38 @@ +// compile-flags:-Zverbose + +#![allow(warnings)] + +use std::fmt::Debug; + +fn no_region<'a, T>(x: Box<T>) -> impl Debug + 'a +where + T: Debug, +{ + x + //~^ ERROR the parameter type `T` may not live long enough [E0309] +} + +fn correct_region<'a, T>(x: Box<T>) -> impl Debug + 'a +where + T: 'a + Debug, +{ + x +} + +fn wrong_region<'a, 'b, T>(x: Box<T>) -> impl Debug + 'a +where + T: 'b + Debug, +{ + x + //~^ ERROR the parameter type `T` may not live long enough [E0309] +} + +fn outlives_region<'a, 'b, T>(x: Box<T>) -> impl Debug + 'a +where + T: 'b + Debug, + 'b: 'a, +{ + x +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr b/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr new file mode 100644 index 000000000..64b08a9b3 --- /dev/null +++ b/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr @@ -0,0 +1,25 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/impl-trait-outlives.rs:11:5 + | +LL | x + | ^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | T: Debug + 'a, + | ++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/impl-trait-outlives.rs:26:5 + | +LL | x + | ^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | T: 'b + Debug + 'a, + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/issue-53789-1.rs b/src/test/ui/nll/ty-outlives/issue-53789-1.rs new file mode 100644 index 000000000..a5201d4bb --- /dev/null +++ b/src/test/ui/nll/ty-outlives/issue-53789-1.rs @@ -0,0 +1,87 @@ +// Regression test for #53789. +// +// check-pass + +use std::collections::BTreeMap; + +trait ValueTree { + type Value; +} + +trait Strategy { + type Value: ValueTree; +} + +type StrategyFor<A> = StrategyType<'static, A>; +type StrategyType<'a, A> = <A as Arbitrary<'a>>::Strategy; + +impl<K: ValueTree, V: ValueTree> Strategy for (K, V) { + type Value = TupleValueTree<(K, V)>; +} + +impl<K: ValueTree, V: ValueTree> ValueTree for TupleValueTree<(K, V)> { + type Value = BTreeMapValueTree<K, V>; +} + +struct TupleValueTree<T> { + tree: T, +} + +struct BTreeMapStrategy<K, V>(std::marker::PhantomData<(K, V)>) +where + K: Strategy, + V: Strategy; + +struct BTreeMapValueTree<K, V>(std::marker::PhantomData<(K, V)>) +where + K: ValueTree, + V: ValueTree; + +impl<K, V> Strategy for BTreeMapStrategy<K, V> +where + K: Strategy, + V: Strategy, +{ + type Value = BTreeMapValueTree<K::Value, V::Value>; +} + +impl<K, V> ValueTree for BTreeMapValueTree<K, V> +where + K: ValueTree, + V: ValueTree, +{ + type Value = BTreeMap<K::Value, V::Value>; +} + +trait Arbitrary<'a>: Sized { + fn arbitrary_with(args: Self::Parameters) -> Self::Strategy; + type Parameters; + type Strategy: Strategy<Value = Self::ValueTree>; + type ValueTree: ValueTree<Value = Self>; +} + +impl<'a, A, B> Arbitrary<'a> for BTreeMap<A, B> +where + A: Arbitrary<'static>, + B: Arbitrary<'static>, + StrategyFor<A>: 'static, + StrategyFor<B>: 'static, +{ + type ValueTree = <Self::Strategy as Strategy>::Value; + type Parameters = (A::Parameters, B::Parameters); + type Strategy = BTreeMapStrategy<A::Strategy, B::Strategy>; + fn arbitrary_with(args: Self::Parameters) -> BTreeMapStrategy<A::Strategy, B::Strategy> { + let (a, b) = args; + btree_map(any_with::<A>(a), any_with::<B>(b)) + } +} + +fn btree_map<K: Strategy + 'static, V: Strategy>(key: K, value: V) -> BTreeMapStrategy<K, V> { + unimplemented!() +} + +fn any_with<'a, A: Arbitrary<'a>>(args: A::Parameters) -> StrategyType<'a, A> { + unimplemented!() +} + +fn main() { } diff --git a/src/test/ui/nll/ty-outlives/issue-53789-2.rs b/src/test/ui/nll/ty-outlives/issue-53789-2.rs new file mode 100644 index 000000000..5109a0e4a --- /dev/null +++ b/src/test/ui/nll/ty-outlives/issue-53789-2.rs @@ -0,0 +1,249 @@ +// Regression test for #53789. +// +// check-pass + +use std::cmp::Ord; +use std::collections::BTreeMap; +use std::ops::Range; + +macro_rules! valuetree { + () => { + type ValueTree = <Self::Strategy as $crate::Strategy>::Value; + }; +} + +macro_rules! product_unpack { + ($factor: pat) => { + ($factor,) + }; + ($($factor: pat),*) => { + ( $( $factor ),* ) + }; + ($($factor: pat),*,) => { + ( $( $factor ),* ) + }; +} + +macro_rules! product_type { + ($factor: ty) => { + ($factor,) + }; + ($($factor: ty),*) => { + ( $( $factor, )* ) + }; + ($($factor: ty),*,) => { + ( $( $factor, )* ) + }; +} + +macro_rules! default { + ($type: ty, $val: expr) => { + impl Default for $type { + fn default() -> Self { + $val.into() + } + } + }; +} + +// Pervasive internal sugar +macro_rules! mapfn { + ($(#[$meta:meta])* [$($vis:tt)*] + fn $name:ident[$($gen:tt)*]($parm:ident: $input:ty) -> $output:ty { + $($body:tt)* + }) => { + $(#[$meta])* + #[derive(Clone, Copy)] + $($vis)* struct $name; + impl $($gen)* statics::MapFn<$input> for $name { + type Output = $output; + } + } +} + +macro_rules! opaque_strategy_wrapper { + ($(#[$smeta:meta])* pub struct $stratname:ident + [$($sgen:tt)*][$($swhere:tt)*] + ($innerstrat:ty) -> $stratvtty:ty; + + $(#[$vmeta:meta])* pub struct $vtname:ident + [$($vgen:tt)*][$($vwhere:tt)*] + ($innervt:ty) -> $actualty:ty; + ) => { + $(#[$smeta])* struct $stratname $($sgen)* (std::marker::PhantomData<(K, V)>) + $($swhere)*; + + $(#[$vmeta])* struct $vtname $($vgen)* ($innervt) $($vwhere)*; + + impl $($sgen)* Strategy for $stratname $($sgen)* $($swhere)* { + type Value = $stratvtty; + } + + impl $($vgen)* ValueTree for $vtname $($vgen)* $($vwhere)* { + type Value = $actualty; + } + } +} + +trait ValueTree { + type Value; +} + +trait Strategy { + type Value: ValueTree; +} + +#[derive(Clone)] +struct VecStrategy<T: Strategy> { + element: T, + size: Range<usize>, +} + +fn vec<T: Strategy>(element: T, size: Range<usize>) -> VecStrategy<T> { + VecStrategy { element: element, size: size } +} + +type ValueFor<S> = <<S as Strategy>::Value as ValueTree>::Value; + +trait Arbitrary<'a>: Sized { + fn arbitrary_with(args: Self::Parameters) -> Self::Strategy; + + type Parameters: Default; + type Strategy: Strategy<Value = Self::ValueTree>; + type ValueTree: ValueTree<Value = Self>; +} + +type StrategyFor<A> = StrategyType<'static, A>; +type StrategyType<'a, A> = <A as Arbitrary<'a>>::Strategy; + +//#[derive(Clone, PartialEq, Eq, Hash, Debug, From, Into)] +struct SizeBounds(Range<usize>); +default!(SizeBounds, 0..100); + +impl From<Range<usize>> for SizeBounds { + fn from(high: Range<usize>) -> Self { + unimplemented!() + } +} + +impl From<SizeBounds> for Range<usize> { + fn from(high: SizeBounds) -> Self { + unimplemented!() + } +} + +fn any_with<'a, A: Arbitrary<'a>>(args: A::Parameters) -> StrategyType<'a, A> { + unimplemented!() +} + +impl<K: ValueTree, V: ValueTree> Strategy for (K, V) +where + <K as ValueTree>::Value: Ord, +{ + type Value = TupleValueTree<(K, V)>; +} + +impl<K: ValueTree, V: ValueTree> ValueTree for TupleValueTree<(K, V)> +where + <K as ValueTree>::Value: Ord, +{ + type Value = BTreeMapValueTree<K, V>; +} + +#[derive(Clone)] +struct VecValueTree<T: ValueTree> { + elements: Vec<T>, +} + +#[derive(Clone, Copy)] +struct TupleValueTree<T> { + tree: T, +} + +opaque_strategy_wrapper! { + #[derive(Clone)] + pub struct BTreeMapStrategy[<K, V>] + [where K : Strategy, V : Strategy, ValueFor<K> : Ord]( + statics::Filter<statics::Map<VecStrategy<(K,V)>, + VecToBTreeMap>, MinSize>) + -> BTreeMapValueTree<K::Value, V::Value>; + + #[derive(Clone)] + pub struct BTreeMapValueTree[<K, V>] + [where K : ValueTree, V : ValueTree, K::Value : Ord]( + statics::Filter<statics::Map<VecValueTree<TupleValueTree<(K, V)>>, + VecToBTreeMap>, MinSize>) + -> BTreeMap<K::Value, V::Value>; +} + +type RangedParams2<A, B> = product_type![SizeBounds, A, B]; + +impl<'a, A, B> Arbitrary<'a> for BTreeMap<A, B> +where + A: Arbitrary<'static> + Ord, + B: Arbitrary<'static>, + StrategyFor<A>: 'static, + StrategyFor<B>: 'static, +{ + valuetree!(); + type Parameters = RangedParams2<A::Parameters, B::Parameters>; + type Strategy = BTreeMapStrategy<A::Strategy, B::Strategy>; + fn arbitrary_with(args: Self::Parameters) -> Self::Strategy { + let product_unpack![range, a, b] = args; + btree_map(any_with::<A>(a), any_with::<B>(b), range.into()) + } +} + +#[derive(Clone, Copy)] +struct MinSize(usize); + +mapfn! { + [] fn VecToBTreeMap[<K : Ord, V>] + (vec: Vec<(K, V)>) -> BTreeMap<K, V> + { + vec.into_iter().collect() + } +} + +fn btree_map<K: Strategy + 'static, V: Strategy + 'static>( + key: K, + value: V, + size: Range<usize>, +) -> BTreeMapStrategy<K, V> +where + ValueFor<K>: Ord, +{ + unimplemented!() +} + +mod statics { + pub(super) trait MapFn<T> { + type Output; + } + + #[derive(Clone)] + pub struct Filter<S, F> { + source: S, + fun: F, + } + + impl<S, F> Filter<S, F> { + pub fn new(source: S, whence: String, filter: F) -> Self { + unimplemented!() + } + } + + #[derive(Clone)] + pub struct Map<S, F> { + source: S, + fun: F, + } + + impl<S, F> Map<S, F> { + pub fn new(source: S, fun: F) -> Self { + unimplemented!() + } + } +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/issue-55756.rs b/src/test/ui/nll/ty-outlives/issue-55756.rs new file mode 100644 index 000000000..e1a3bc3c4 --- /dev/null +++ b/src/test/ui/nll/ty-outlives/issue-55756.rs @@ -0,0 +1,37 @@ +// Regression test for #55756. +// +// In this test, the result of `self.callee` is a projection `<D as +// Database<'?0>>::Guard`. As it may contain a destructor, the dropck +// rules require that this type outlivess the scope of `state`. Unfortunately, +// our region inference is not smart enough to figure out how to +// translate a requirement like +// +// <D as Database<'0>>::guard: 'r +// +// into a requirement that `'0: 'r` -- in particular, it fails to do +// so because it *also* knows that `<D as Database<'a>>::Guard: 'a` +// from the trait definition. Faced with so many choices, the current +// solver opts to do nothing. +// +// Fixed by tweaking the solver to recognize that the constraint from +// the environment duplicates one from the trait. +// +// check-pass + +#![crate_type="lib"] + +pub trait Database<'a> { + type Guard: 'a; +} + +pub struct Stateful<'a, D: 'a>(&'a D); + +impl<'b, D: for <'a> Database<'a>> Stateful<'b, D> { + pub fn callee<'a>(&'a self) -> <D as Database<'a>>::Guard { + unimplemented!() + } + pub fn caller<'a>(&'a self) -> <D as Database<'a>>::Guard { + let state = self.callee(); + unimplemented!() + } +} diff --git a/src/test/ui/nll/ty-outlives/projection-body.rs b/src/test/ui/nll/ty-outlives/projection-body.rs new file mode 100644 index 000000000..b03a539eb --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-body.rs @@ -0,0 +1,27 @@ +// Test that when we infer the lifetime to a subset of the fn body, it +// works out. +// +// check-pass + +trait MyTrait<'a> { + type Output; +} + +fn foo1<T>() +where + for<'x> T: MyTrait<'x>, +{ + // Here the region `'c` in `<T as MyTrait<'c>>::Output` will be + // inferred to a subset of the fn body. + let x = bar::<T::Output>(); + drop(x); +} + +fn bar<'a, T>() -> &'a () +where + T: 'a, +{ + &() +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/projection-implied-bounds.rs b/src/test/ui/nll/ty-outlives/projection-implied-bounds.rs new file mode 100644 index 000000000..e1dac0824 --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-implied-bounds.rs @@ -0,0 +1,40 @@ +// Test that we can deduce when projections like `T::Item` outlive the +// function body. Test that this does not imply that `T: 'a` holds. + +// compile-flags:-Zverbose + +use std::cell::Cell; + +fn twice<F, T>(mut value: T, mut f: F) +where + F: FnMut(&T, Cell<&Option<T::Item>>), + T: Iterator, +{ + let mut n = value.next(); + f(&value, Cell::new(&n)); + f(&value, Cell::new(&n)); +} + +fn generic1<T: Iterator>(value: T) { + // No error here: + twice(value, |value_ref, item| invoke1(item)); +} + +fn invoke1<'a, T>(x: Cell<&'a Option<T>>) +where + T: 'a, +{ +} + +fn generic2<T: Iterator>(value: T) { + twice(value, |value_ref, item| invoke2(value_ref, item)); + //~^ ERROR the parameter type `T` may not live long enough +} + +fn invoke2<'a, T, U>(a: &T, b: Cell<&'a Option<U>>) +where + T: 'a, +{ +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr b/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr new file mode 100644 index 000000000..3b9b2956c --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr @@ -0,0 +1,14 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/projection-implied-bounds.rs:30:18 + | +LL | twice(value, |value_ref, item| invoke2(value_ref, item)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn generic2<T: Iterator + 'static>(value: T) { + | +++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`. diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs new file mode 100644 index 000000000..2d9c008c7 --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs @@ -0,0 +1,55 @@ +// compile-flags:-Zverbose + +// Tests closures that propagate an outlives relationship to their +// creator where the subject is a projection with no regions (`<T as +// Iterator>::Item`, to be exact). + +#![allow(warnings)] +#![feature(rustc_attrs)] + +trait Anything { } + +impl<T> Anything for T { } + +fn with_signature<'a, T, F>(x: Box<T>, op: F) -> Box<dyn Anything + 'a> + where F: FnOnce(Box<T>) -> Box<dyn Anything + 'a> +{ + op(x) +} + +#[rustc_regions] +fn no_region<'a, T>(x: Box<T>) -> Box<dyn Anything + 'a> +where + T: Iterator, +{ + with_signature(x, |mut y| Box::new(y.next())) + //~^ ERROR the associated type `<T as Iterator>::Item` may not live long enough +} + +#[rustc_regions] +fn correct_region<'a, T>(x: Box<T>) -> Box<dyn Anything + 'a> +where + T: 'a + Iterator, +{ + with_signature(x, |mut y| Box::new(y.next())) +} + +#[rustc_regions] +fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<dyn Anything + 'a> +where + T: 'b + Iterator, +{ + with_signature(x, |mut y| Box::new(y.next())) + //~^ ERROR the associated type `<T as Iterator>::Item` may not live long enough +} + +#[rustc_regions] +fn outlives_region<'a, 'b, T>(x: Box<T>) -> Box<dyn Anything + 'a> +where + T: 'b + Iterator, + 'b: 'a, +{ + with_signature(x, |mut y| Box::new(y.next())) +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr new file mode 100644 index 000000000..feab24769 --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr @@ -0,0 +1,132 @@ +note: external requirements + --> $DIR/projection-no-regions-closure.rs:25:23 + | +LL | with_signature(x, |mut y| Box::new(y.next())) + | ^^^^^^^ + | + = note: defining type: no_region::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#2r)>, + (), + ] + = note: number of external vids: 3 + = note: where <T as std::iter::Iterator>::Item: '_#2r + +note: no external requirements + --> $DIR/projection-no-regions-closure.rs:21:1 + | +LL | / fn no_region<'a, T>(x: Box<T>) -> Box<dyn Anything + 'a> +LL | | where +LL | | T: Iterator, +LL | | { +LL | | with_signature(x, |mut y| Box::new(y.next())) +LL | | +LL | | } + | |_^ + | + = note: defining type: no_region::<'_#1r, T> + +error[E0309]: the associated type `<T as Iterator>::Item` may not live long enough + --> $DIR/projection-no-regions-closure.rs:25:23 + | +LL | with_signature(x, |mut y| Box::new(y.next())) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`... + = note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds + +note: external requirements + --> $DIR/projection-no-regions-closure.rs:34:23 + | +LL | with_signature(x, |mut y| Box::new(y.next())) + | ^^^^^^^ + | + = note: defining type: correct_region::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#2r)>, + (), + ] + = note: number of external vids: 3 + = note: where <T as std::iter::Iterator>::Item: '_#2r + +note: no external requirements + --> $DIR/projection-no-regions-closure.rs:30:1 + | +LL | / fn correct_region<'a, T>(x: Box<T>) -> Box<dyn Anything + 'a> +LL | | where +LL | | T: 'a + Iterator, +LL | | { +LL | | with_signature(x, |mut y| Box::new(y.next())) +LL | | } + | |_^ + | + = note: defining type: correct_region::<'_#1r, T> + +note: external requirements + --> $DIR/projection-no-regions-closure.rs:42:23 + | +LL | with_signature(x, |mut y| Box::new(y.next())) + | ^^^^^^^ + | + = note: defining type: wrong_region::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#3r)>, + (), + ] + = note: number of external vids: 4 + = note: where <T as std::iter::Iterator>::Item: '_#3r + +note: no external requirements + --> $DIR/projection-no-regions-closure.rs:38:1 + | +LL | / fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<dyn Anything + 'a> +LL | | where +LL | | T: 'b + Iterator, +LL | | { +LL | | with_signature(x, |mut y| Box::new(y.next())) +LL | | +LL | | } + | |_^ + | + = note: defining type: wrong_region::<'_#1r, '_#2r, T> + +error[E0309]: the associated type `<T as Iterator>::Item` may not live long enough + --> $DIR/projection-no-regions-closure.rs:42:23 + | +LL | with_signature(x, |mut y| Box::new(y.next())) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`... + = note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds + +note: external requirements + --> $DIR/projection-no-regions-closure.rs:52:23 + | +LL | with_signature(x, |mut y| Box::new(y.next())) + | ^^^^^^^ + | + = note: defining type: outlives_region::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn Anything + '_#3r)>, + (), + ] + = note: number of external vids: 4 + = note: where <T as std::iter::Iterator>::Item: '_#3r + +note: no external requirements + --> $DIR/projection-no-regions-closure.rs:47:1 + | +LL | / fn outlives_region<'a, 'b, T>(x: Box<T>) -> Box<dyn Anything + 'a> +LL | | where +LL | | T: 'b + Iterator, +LL | | 'b: 'a, +LL | | { +LL | | with_signature(x, |mut y| Box::new(y.next())) +LL | | } + | |_^ + | + = note: defining type: outlives_region::<'_#1r, '_#2r, T> + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs new file mode 100644 index 000000000..a10a0366a --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs @@ -0,0 +1,40 @@ +// compile-flags:-Zverbose + +#![allow(warnings)] + +trait Anything { } + +impl<T> Anything for T { } + +fn no_region<'a, T>(mut x: T) -> Box<dyn Anything + 'a> +where + T: Iterator, +{ + Box::new(x.next()) + //~^ ERROR the associated type `<T as Iterator>::Item` may not live long enough +} + +fn correct_region<'a, T>(mut x: T) -> Box<dyn Anything + 'a> +where + T: 'a + Iterator, +{ + Box::new(x.next()) +} + +fn wrong_region<'a, 'b, T>(mut x: T) -> Box<dyn Anything + 'a> +where + T: 'b + Iterator, +{ + Box::new(x.next()) + //~^ ERROR the associated type `<T as Iterator>::Item` may not live long enough +} + +fn outlives_region<'a, 'b, T>(mut x: T) -> Box<dyn Anything + 'a> +where + T: 'b + Iterator, + 'b: 'a, +{ + Box::new(x.next()) +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr new file mode 100644 index 000000000..e0ff544fe --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr @@ -0,0 +1,21 @@ +error[E0309]: the associated type `<T as Iterator>::Item` may not live long enough + --> $DIR/projection-no-regions-fn.rs:13:5 + | +LL | Box::new(x.next()) + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`... + = note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds + +error[E0309]: the associated type `<T as Iterator>::Item` may not live long enough + --> $DIR/projection-no-regions-fn.rs:28:5 + | +LL | Box::new(x.next()) + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`... + = note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.rs b/src/test/ui/nll/ty-outlives/projection-one-region-closure.rs new file mode 100644 index 000000000..af361e990 --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.rs @@ -0,0 +1,83 @@ +// Test cases where we constrain `<T as Anything<'b>>::AssocType` to +// outlive `'a` and there are no bounds in the trait definition of +// `Anything`. This means that the constraint can only be satisfied in two +// ways: +// +// - by ensuring that `T: 'a` and `'b: 'a`, or +// - by something in the where clauses. +// +// As of this writing, the where clause option does not work because +// of limitations in our region inferencing system (this is true both +// with and without NLL). See `projection_outlives`. +// +// Ensuring that both `T: 'a` and `'b: 'a` holds does work (`elements_outlive`). + +// compile-flags:-Zverbose + +#![allow(warnings)] +#![feature(rustc_attrs)] + +use std::cell::Cell; + +trait Anything<'a> { + type AssocType; +} + +fn with_signature<'a, T, F>(cell: Cell<&'a ()>, t: T, op: F) +where + F: FnOnce(Cell<&'a ()>, T), +{ + op(cell, t) +} + +fn require<'a, 'b, T>(_cell: Cell<&'a ()>, _t: T) +where + T: Anything<'b>, + T::AssocType: 'a, +{ +} + +#[rustc_regions] +fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, +{ + with_signature(cell, t, |cell, t| require(cell, t)); + //~^ ERROR the parameter type `T` may not live long enough + //~| ERROR +} + +#[rustc_regions] +fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, + 'a: 'a, +{ + with_signature(cell, t, |cell, t| require(cell, t)); + //~^ ERROR the parameter type `T` may not live long enough + //~| ERROR +} + +#[rustc_regions] +fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, + T::AssocType: 'a, +{ + // We are projecting `<T as Anything<'b>>::AssocType`, and we know + // that this outlives `'a` because of the where-clause. + + with_signature(cell, t, |cell, t| require(cell, t)); +} + +#[rustc_regions] +fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, + T: 'a, + 'b: 'a, +{ + with_signature(cell, t, |cell, t| require(cell, t)); +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr new file mode 100644 index 000000000..98063bd0a --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr @@ -0,0 +1,167 @@ +note: external requirements + --> $DIR/projection-one-region-closure.rs:45:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: no_relationships_late::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), + ] + = note: late-bound region is '_#3r + = note: number of external vids: 4 + = note: where T: '_#2r + = note: where '_#1r: '_#2r + +note: no external requirements + --> $DIR/projection-one-region-closure.rs:41:1 + | +LL | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, +LL | | { +... | +LL | | +LL | | } + | |_^ + | + = note: defining type: no_relationships_late::<'_#1r, T> + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/projection-one-region-closure.rs:45:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | T: Anything<'b> + 'a, + | ++++ + +error: lifetime may not live long enough + --> $DIR/projection-one-region-closure.rs:45:39 + | +LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +note: external requirements + --> $DIR/projection-one-region-closure.rs:56:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + = note: number of external vids: 4 + = note: where T: '_#3r + = note: where '_#2r: '_#3r + +note: no external requirements + --> $DIR/projection-one-region-closure.rs:51:1 + | +LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, +LL | | 'a: 'a, +... | +LL | | +LL | | } + | |_^ + | + = note: defining type: no_relationships_early::<'_#1r, '_#2r, T> + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/projection-one-region-closure.rs:56:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | T: Anything<'b> + 'a, + | ++++ + +error: lifetime may not live long enough + --> $DIR/projection-one-region-closure.rs:56:39 + | +LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +note: external requirements + --> $DIR/projection-one-region-closure.rs:70:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: projection_outlives::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + = note: number of external vids: 4 + = note: where <T as Anything<ReEarlyBound(1, 'b)>>::AssocType: '_#3r + +note: no external requirements + --> $DIR/projection-one-region-closure.rs:62:1 + | +LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, +LL | | T::AssocType: 'a, +... | +LL | | with_signature(cell, t, |cell, t| require(cell, t)); +LL | | } + | |_^ + | + = note: defining type: projection_outlives::<'_#1r, '_#2r, T> + +note: external requirements + --> $DIR/projection-one-region-closure.rs:80:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: elements_outlive::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + = note: number of external vids: 4 + = note: where T: '_#3r + = note: where '_#2r: '_#3r + +note: no external requirements + --> $DIR/projection-one-region-closure.rs:74:1 + | +LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, +LL | | T: 'a, +... | +LL | | with_signature(cell, t, |cell, t| require(cell, t)); +LL | | } + | |_^ + | + = note: defining type: elements_outlive::<'_#1r, '_#2r, T> + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs new file mode 100644 index 000000000..6f8513491 --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs @@ -0,0 +1,84 @@ +// Test cases where we constrain `<T as Anything<'b>>::AssocType` to +// outlive `'a` and there is a unique bound in the trait definition of +// `Anything` -- i.e., we know that `AssocType` outlives `'b`. In this +// case, the best way to satisfy the trait bound is to show that `'b: +// 'a`, which can be done in various ways. + +// compile-flags:-Zverbose + +#![allow(warnings)] +#![feature(rustc_attrs)] + +use std::cell::Cell; + +trait Anything<'a> { + type AssocType: 'a; +} + +fn with_signature<'a, T, F>(cell: Cell<&'a ()>, t: T, op: F) +where + F: FnOnce(Cell<&'a ()>, T), +{ + op(cell, t) +} + +fn require<'a, 'b, T>(_cell: Cell<&'a ()>, _t: T) +where + T: Anything<'b>, + T::AssocType: 'a, +{ +} + +#[rustc_regions] +fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, +{ + with_signature(cell, t, |cell, t| require(cell, t)); + //~^ ERROR +} + +#[rustc_regions] +fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, + 'a: 'a, +{ + with_signature(cell, t, |cell, t| require(cell, t)); + //~^ ERROR +} + +#[rustc_regions] +fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, + T::AssocType: 'a, +{ + // We are projecting `<T as Anything<'b>>::AssocType`, and we know + // that this outlives `'a` because of the where-clause. + + with_signature(cell, t, |cell, t| require(cell, t)); +} + +#[rustc_regions] +fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, + 'b: 'a, +{ + with_signature(cell, t, |cell, t| require(cell, t)); +} + +#[rustc_regions] +fn one_region<'a, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'a>, +{ + // Note that in this case the closure still propagates an external + // requirement between two variables in its signature, but the + // creator maps both those two region variables to `'a` on its + // side. + with_signature(cell, t, |cell, t| require(cell, t)); +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr new file mode 100644 index 000000000..45e61bcbd --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr @@ -0,0 +1,169 @@ +note: external requirements + --> $DIR/projection-one-region-trait-bound-closure.rs:37:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: no_relationships_late::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), + ] + = note: late-bound region is '_#3r + = note: number of external vids: 4 + = note: where '_#1r: '_#2r + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-closure.rs:33:1 + | +LL | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, +LL | | { +LL | | with_signature(cell, t, |cell, t| require(cell, t)); +LL | | +LL | | } + | |_^ + | + = note: defining type: no_relationships_late::<'_#1r, T> + +error: lifetime may not live long enough + --> $DIR/projection-one-region-trait-bound-closure.rs:37:39 + | +LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +note: external requirements + --> $DIR/projection-one-region-trait-bound-closure.rs:47:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + = note: number of external vids: 4 + = note: where '_#2r: '_#3r + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-closure.rs:42:1 + | +LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, +LL | | 'a: 'a, +... | +LL | | +LL | | } + | |_^ + | + = note: defining type: no_relationships_early::<'_#1r, '_#2r, T> + +error: lifetime may not live long enough + --> $DIR/projection-one-region-trait-bound-closure.rs:47:39 + | +LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +note: external requirements + --> $DIR/projection-one-region-trait-bound-closure.rs:60:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: projection_outlives::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + = note: number of external vids: 4 + = note: where <T as Anything<ReEarlyBound(1, 'b)>>::AssocType: '_#3r + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-closure.rs:52:1 + | +LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, +LL | | T::AssocType: 'a, +... | +LL | | with_signature(cell, t, |cell, t| require(cell, t)); +LL | | } + | |_^ + | + = note: defining type: projection_outlives::<'_#1r, '_#2r, T> + +note: external requirements + --> $DIR/projection-one-region-trait-bound-closure.rs:69:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: elements_outlive::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + = note: number of external vids: 4 + = note: where '_#2r: '_#3r + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-closure.rs:64:1 + | +LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, +LL | | 'b: 'a, +LL | | { +LL | | with_signature(cell, t, |cell, t| require(cell, t)); +LL | | } + | |_^ + | + = note: defining type: elements_outlive::<'_#1r, '_#2r, T> + +note: external requirements + --> $DIR/projection-one-region-trait-bound-closure.rs:81:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: one_region::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), + ] + = note: number of external vids: 3 + = note: where '_#1r: '_#2r + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-closure.rs:73:1 + | +LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'a>, +LL | | { +... | +LL | | with_signature(cell, t, |cell, t| require(cell, t)); +LL | | } + | |_^ + | + = note: defining type: one_region::<'_#1r, T> + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs new file mode 100644 index 000000000..7c0a3bc72 --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs @@ -0,0 +1,88 @@ +// Test cases where we constrain `<T as Anything<'b>>::AssocType` to +// outlive `'static`. In this case, we don't get any errors, and in fact +// we don't even propagate constraints from the closures to the callers. + +// compile-flags:-Zverbose +// check-pass + +#![allow(warnings)] +#![feature(rustc_attrs)] + +use std::cell::Cell; + +trait Anything<'a> { + type AssocType: 'static; +} + +fn with_signature<'a, T, F>(cell: Cell<&'a ()>, t: T, op: F) +where + F: FnOnce(Cell<&'a ()>, T), +{ + op(cell, t) +} + +fn require<'a, 'b, T>(_cell: Cell<&'a ()>, _t: T) +where + T: Anything<'b>, + T::AssocType: 'a, +{ +} + +#[rustc_regions] +fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, +{ + with_signature(cell, t, |cell, t| require(cell, t)); +} + +#[rustc_regions] +fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, + 'a: 'a, +{ + with_signature(cell, t, |cell, t| require(cell, t)); +} + +#[rustc_regions] +fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, + T::AssocType: 'a, +{ + // This error is unfortunate. This code ought to type-check: we + // are projecting `<T as Anything<'b>>::AssocType`, and we know + // that this outlives `'a` because of the where-clause. However, + // the way the region checker works, we don't register this + // outlives obligation, and hence we get an error: this is because + // what we see is a projection like `<T as + // Anything<'?0>>::AssocType`, and we don't yet know if `?0` will + // equal `'b` or not, so we ignore the where-clause. Obviously we + // can do better here with a more involved verification step. + + with_signature(cell, t, |cell, t| require(cell, t)); +} + +#[rustc_regions] +fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b>, + 'b: 'a, +{ + with_signature(cell, t, |cell, t| require(cell, t)); +} + +#[rustc_regions] +fn one_region<'a, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'a>, +{ + // Note that in this case the closure still propagates an external + // requirement between two variables in its signature, but the + // creator maps both those two region variables to `'a` on its + // side. + with_signature(cell, t, |cell, t| require(cell, t)); +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr new file mode 100644 index 000000000..f2549205b --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr @@ -0,0 +1,130 @@ +note: no external requirements + --> $DIR/projection-one-region-trait-bound-static-closure.rs:36:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: no_relationships_late::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), + ] + = note: late-bound region is '_#3r + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-static-closure.rs:32:1 + | +LL | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, +LL | | { +LL | | with_signature(cell, t, |cell, t| require(cell, t)); +LL | | } + | |_^ + | + = note: defining type: no_relationships_late::<'_#1r, T> + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-static-closure.rs:45:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: no_relationships_early::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-static-closure.rs:40:1 + | +LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, +LL | | 'a: 'a, +LL | | { +LL | | with_signature(cell, t, |cell, t| require(cell, t)); +LL | | } + | |_^ + | + = note: defining type: no_relationships_early::<'_#1r, '_#2r, T> + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-static-closure.rs:64:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: projection_outlives::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-static-closure.rs:49:1 + | +LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, +LL | | T::AssocType: 'a, +... | +LL | | with_signature(cell, t, |cell, t| require(cell, t)); +LL | | } + | |_^ + | + = note: defining type: projection_outlives::<'_#1r, '_#2r, T> + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-static-closure.rs:73:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: elements_outlive::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-static-closure.rs:68:1 + | +LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b>, +LL | | 'b: 'a, +LL | | { +LL | | with_signature(cell, t, |cell, t| require(cell, t)); +LL | | } + | |_^ + | + = note: defining type: elements_outlive::<'_#1r, '_#2r, T> + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-static-closure.rs:85:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: one_region::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), + ] + +note: no external requirements + --> $DIR/projection-one-region-trait-bound-static-closure.rs:77:1 + | +LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'a>, +LL | | { +... | +LL | | with_signature(cell, t, |cell, t| require(cell, t)); +LL | | } + | |_^ + | + = note: defining type: one_region::<'_#1r, T> + diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs new file mode 100644 index 000000000..7b4a3c03a --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs @@ -0,0 +1,112 @@ +// Test cases where we constrain `<T as Anything<'a, 'b>>::AssocType` +// to outlive `'a` and there are two bounds in the trait definition of +// `Anything` -- i.e., we know that `AssocType` outlives `'a` and +// `'b`. In this case, it's not clear what is the best way to satisfy +// the trait bound, and hence we propagate it to the caller as a type +// test. + +// compile-flags:-Zverbose + +#![allow(warnings)] +#![feature(rustc_attrs)] + +use std::cell::Cell; + +trait Anything<'a, 'b> { + type AssocType: 'a + 'b; +} + +fn with_signature<'a, T, F>(cell: Cell<&'a ()>, t: T, op: F) +where + F: FnOnce(Cell<&'a ()>, T), +{ + op(cell, t) +} + +fn require<'a, 'b, 'c, T>(_cell: Cell<&'a ()>, _t: T) +where + T: Anything<'b, 'c>, + T::AssocType: 'a, +{ +} + +#[rustc_regions] +fn no_relationships_late<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b, 'c>, +{ + with_signature(cell, t, |cell, t| require(cell, t)); + //~^ ERROR may not live long enough +} + +#[rustc_regions] +fn no_relationships_early<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b, 'c>, + 'a: 'a, +{ + with_signature(cell, t, |cell, t| require(cell, t)); + //~^ ERROR may not live long enough +} + +#[rustc_regions] +fn projection_outlives<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b, 'c>, + T::AssocType: 'a, +{ + // We are projecting `<T as Anything<'b>>::AssocType`, and we know + // that this outlives `'a` because of the where-clause. + + with_signature(cell, t, |cell, t| require(cell, t)); +} + +#[rustc_regions] +fn elements_outlive1<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b, 'c>, + 'b: 'a, +{ + with_signature(cell, t, |cell, t| require(cell, t)); +} + +#[rustc_regions] +fn elements_outlive2<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b, 'c>, + 'c: 'a, +{ + with_signature(cell, t, |cell, t| require(cell, t)); +} + +#[rustc_regions] +fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b, 'b>, +{ + with_signature(cell, t, |cell, t| require(cell, t)); + //~^ ERROR lifetime may not live long enough +} + +#[rustc_regions] +fn two_regions_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'b, 'b>, + 'b: 'a, +{ + with_signature(cell, t, |cell, t| require(cell, t)); +} + +#[rustc_regions] +fn one_region<'a, T>(cell: Cell<&'a ()>, t: T) +where + T: Anything<'a, 'a>, +{ + // Note that in this case the closure still propagates an external + // requirement between two variables in its signature, but the + // creator maps both those two region variables to `'a` on its + // side. + with_signature(cell, t, |cell, t| require(cell, t)); +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr new file mode 100644 index 000000000..8e1b6fa2e --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr @@ -0,0 +1,260 @@ +note: external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:38:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: no_relationships_late::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + = note: late-bound region is '_#4r + = note: number of external vids: 5 + = note: where <T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType: '_#3r + +note: no external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:34:1 + | +LL | / fn no_relationships_late<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b, 'c>, +LL | | { +LL | | with_signature(cell, t, |cell, t| require(cell, t)); +LL | | +LL | | } + | |_^ + | + = note: defining type: no_relationships_late::<'_#1r, '_#2r, T> + +error[E0309]: the associated type `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType` may not live long enough + --> $DIR/projection-two-region-trait-bound-closure.rs:38:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType: 'a`... + = note: ...so that the type `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType` will meet its required lifetime bounds + +note: external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:48:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: no_relationships_early::<'_#1r, '_#2r, '_#3r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)), + (), + ] + = note: number of external vids: 5 + = note: where <T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType: '_#4r + +note: no external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:43:1 + | +LL | / fn no_relationships_early<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b, 'c>, +LL | | 'a: 'a, +... | +LL | | +LL | | } + | |_^ + | + = note: defining type: no_relationships_early::<'_#1r, '_#2r, '_#3r, T> + +error[E0309]: the associated type `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType` may not live long enough + --> $DIR/projection-two-region-trait-bound-closure.rs:48:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType: 'a`... + = note: ...so that the type `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType` will meet its required lifetime bounds + +note: external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:61:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: projection_outlives::<'_#1r, '_#2r, '_#3r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)), + (), + ] + = note: number of external vids: 5 + = note: where <T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType: '_#4r + +note: no external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:53:1 + | +LL | / fn projection_outlives<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b, 'c>, +LL | | T::AssocType: 'a, +... | +LL | | with_signature(cell, t, |cell, t| require(cell, t)); +LL | | } + | |_^ + | + = note: defining type: projection_outlives::<'_#1r, '_#2r, '_#3r, T> + +note: external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:70:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: elements_outlive1::<'_#1r, '_#2r, '_#3r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)), + (), + ] + = note: number of external vids: 5 + = note: where <T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType: '_#4r + +note: no external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:65:1 + | +LL | / fn elements_outlive1<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b, 'c>, +LL | | 'b: 'a, +LL | | { +LL | | with_signature(cell, t, |cell, t| require(cell, t)); +LL | | } + | |_^ + | + = note: defining type: elements_outlive1::<'_#1r, '_#2r, '_#3r, T> + +note: external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:79:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: elements_outlive2::<'_#1r, '_#2r, '_#3r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#4r ()>, T)), + (), + ] + = note: number of external vids: 5 + = note: where <T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType: '_#4r + +note: no external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:74:1 + | +LL | / fn elements_outlive2<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b, 'c>, +LL | | 'c: 'a, +LL | | { +LL | | with_signature(cell, t, |cell, t| require(cell, t)); +LL | | } + | |_^ + | + = note: defining type: elements_outlive2::<'_#1r, '_#2r, '_#3r, T> + +note: external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:87:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: two_regions::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), + ] + = note: late-bound region is '_#3r + = note: number of external vids: 4 + = note: where <T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(0, 'b)>>::AssocType: '_#2r + +note: no external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:83:1 + | +LL | / fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b, 'b>, +LL | | { +LL | | with_signature(cell, t, |cell, t| require(cell, t)); +LL | | +LL | | } + | |_^ + | + = note: defining type: two_regions::<'_#1r, T> + +error: lifetime may not live long enough + --> $DIR/projection-two-region-trait-bound-closure.rs:87:29 + | +LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ closure body requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +note: external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:97:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: two_regions_outlive::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + = note: number of external vids: 4 + = note: where <T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(1, 'b)>>::AssocType: '_#3r + +note: no external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:92:1 + | +LL | / fn two_regions_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'b, 'b>, +LL | | 'b: 'a, +LL | | { +LL | | with_signature(cell, t, |cell, t| require(cell, t)); +LL | | } + | |_^ + | + = note: defining type: two_regions_outlive::<'_#1r, '_#2r, T> + +note: external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:109:29 + | +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^ + | + = note: defining type: one_region::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), + ] + = note: number of external vids: 3 + = note: where <T as Anything<ReEarlyBound(0, 'a), ReEarlyBound(0, 'a)>>::AssocType: '_#2r + +note: no external requirements + --> $DIR/projection-two-region-trait-bound-closure.rs:101:1 + | +LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T) +LL | | where +LL | | T: Anything<'a, 'a>, +LL | | { +... | +LL | | with_signature(cell, t, |cell, t| require(cell, t)); +LL | | } + | |_^ + | + = note: defining type: one_region::<'_#1r, T> + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.rs b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.rs new file mode 100644 index 000000000..dce88b88c --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.rs @@ -0,0 +1,34 @@ +// Test that we are able to establish that `<T as +// MyTrait<'a>>::Output` outlives `'b` here. We need to prove however +// that `<T as MyTrait<'a>>::Output` outlives `'a`, so we also have to +// prove that `'b: 'a`. + +trait MyTrait<'a> { + type Output; +} + +fn foo1<'a, 'b, T>() -> &'a () +where + T: MyTrait<'a>, + <T as MyTrait<'a>>::Output: 'b, +{ + bar::<T::Output>() //~ ERROR may not live long enough +} + +fn foo2<'a, 'b, T>() -> &'a () +where + T: MyTrait<'a>, + <T as MyTrait<'a>>::Output: 'b, + 'b: 'a, +{ + bar::<T::Output>() // OK +} + +fn bar<'a, T>() -> &'a () +where + T: 'a, +{ + &() +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr new file mode 100644 index 000000000..b4435fe06 --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr @@ -0,0 +1,12 @@ +error[E0309]: the associated type `<T as MyTrait<'_>>::Output` may not live long enough + --> $DIR/projection-where-clause-env-wrong-bound.rs:15:5 + | +LL | bar::<T::Output>() + | ^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `<T as MyTrait<'_>>::Output: 'a`... + = note: ...so that the type `<T as MyTrait<'_>>::Output` will meet its required lifetime bounds + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.rs b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.rs new file mode 100644 index 000000000..987148dce --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.rs @@ -0,0 +1,25 @@ +// Test that if we need to prove that `<T as MyTrait<'a>>::Output: +// 'a`, but we only know that `<T as MyTrait<'b>>::Output: 'a`, that +// doesn't suffice. + +trait MyTrait<'a> { + type Output; +} + +fn foo1<'a, 'b, T>() -> &'a () +where + for<'x> T: MyTrait<'x>, + <T as MyTrait<'b>>::Output: 'a, +{ + bar::<<T as MyTrait<'a>>::Output>() + //~^ ERROR the associated type `<T as MyTrait<'_>>::Output` may not live long enough +} + +fn bar<'a, T>() -> &'a () +where + T: 'a, +{ + &() +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr new file mode 100644 index 000000000..ddeaf3c1f --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr @@ -0,0 +1,12 @@ +error[E0309]: the associated type `<T as MyTrait<'_>>::Output` may not live long enough + --> $DIR/projection-where-clause-env-wrong-lifetime.rs:14:5 + | +LL | bar::<<T as MyTrait<'a>>::Output>() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding an explicit lifetime bound `<T as MyTrait<'_>>::Output: 'a`... + = note: ...so that the type `<T as MyTrait<'_>>::Output` will meet its required lifetime bounds + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-env.rs b/src/test/ui/nll/ty-outlives/projection-where-clause-env.rs new file mode 100644 index 000000000..a41116232 --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-where-clause-env.rs @@ -0,0 +1,28 @@ +// Test that when we have a `<T as MyTrait<'a>>::Output: 'a` +// relationship in the environment we take advantage of it. In this +// case, that means we **don't** have to prove that `T: 'a`. +// +// Regression test for #53121. +// +// check-pass + +trait MyTrait<'a> { + type Output; +} + +fn foo<'a, T>() -> &'a () +where + T: MyTrait<'a>, + <T as MyTrait<'a>>::Output: 'a, +{ + bar::<T::Output>() +} + +fn bar<'a, T>() -> &'a () +where + T: 'a, +{ + &() +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-none.rs b/src/test/ui/nll/ty-outlives/projection-where-clause-none.rs new file mode 100644 index 000000000..bb201e5c0 --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-where-clause-none.rs @@ -0,0 +1,24 @@ +// Test that we are NOT able to establish that `<T as +// MyTrait<'a>>::Output: 'a` outlives `'a` here -- we have only one +// recourse, which is to prove that `T: 'a` and `'a: 'a`, but we don't +// know that `T: 'a`. + +trait MyTrait<'a> { + type Output; +} + +fn foo<'a, T>() -> &'a () +where + T: MyTrait<'a>, +{ + bar::<T::Output>() //~ ERROR the parameter type `T` may not live long enough +} + +fn bar<'a, T>() -> &'a () +where + T: 'a, +{ + &() +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-none.stderr b/src/test/ui/nll/ty-outlives/projection-where-clause-none.stderr new file mode 100644 index 000000000..0df44644d --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-where-clause-none.stderr @@ -0,0 +1,14 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/projection-where-clause-none.rs:14:5 + | +LL | bar::<T::Output>() + | ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | T: MyTrait<'a> + 'a, + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-trait.rs b/src/test/ui/nll/ty-outlives/projection-where-clause-trait.rs new file mode 100644 index 000000000..1a40d3b4c --- /dev/null +++ b/src/test/ui/nll/ty-outlives/projection-where-clause-trait.rs @@ -0,0 +1,25 @@ +// Test that we are able to establish that `<T as +// MyTrait<'a>>::Output: 'a` outlives `'a` (because the trait says +// so). +// +// check-pass + +trait MyTrait<'a> { + type Output: 'a; +} + +fn foo<'a, T>() -> &'a () +where + T: MyTrait<'a>, +{ + bar::<T::Output>() +} + +fn bar<'a, T>() -> &'a () +where + T: 'a, +{ + &() +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs new file mode 100644 index 000000000..4d8380599 --- /dev/null +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs @@ -0,0 +1,39 @@ +// compile-flags:-Zverbose + +#![allow(warnings)] +#![feature(rustc_attrs)] + +use std::cell::Cell; + +// Invoke in such a way that the callee knows: +// +// - 'a: 'x +// +// and it must prove that `T: 'x`. Callee passes along `T: 'a`. +fn twice<'a, F, T>(v: Cell<&'a ()>, value: T, mut f: F) +where + F: for<'x> FnMut(Option<Cell<&'a &'x ()>>, &T), +{ + f(None, &value); + f(None, &value); +} + +#[rustc_regions] +fn generic<T>(value: T) { + let cell = Cell::new(&()); + twice(cell, value, |a, b| invoke(a, b)); +} + +#[rustc_regions] +fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) { + twice(cell, value, |a, b| invoke(a, b)); + //~^ ERROR the parameter type `T` may not live long enough +} + +fn invoke<'a, 'x, T>(x: Option<Cell<&'x &'a ()>>, y: &T) +where + T: 'x, +{ +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr new file mode 100644 index 000000000..12c76d198 --- /dev/null +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -0,0 +1,65 @@ +note: external requirements + --> $DIR/ty-param-closure-approximate-lower-bound.rs:24:24 + | +LL | twice(cell, value, |a, b| invoke(a, b)); + | ^^^^^^ + | + = note: defining type: generic::<T>::{closure#0} with closure substs [ + i16, + for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) T)), + (), + ] + = note: number of external vids: 2 + = note: where T: '_#1r + +note: no external requirements + --> $DIR/ty-param-closure-approximate-lower-bound.rs:22:1 + | +LL | / fn generic<T>(value: T) { +LL | | let cell = Cell::new(&()); +LL | | twice(cell, value, |a, b| invoke(a, b)); +LL | | } + | |_^ + | + = note: defining type: generic::<T> + +note: external requirements + --> $DIR/ty-param-closure-approximate-lower-bound.rs:29:24 + | +LL | twice(cell, value, |a, b| invoke(a, b)); + | ^^^^^^ + | + = note: defining type: generic_fail::<T>::{closure#0} with closure substs [ + i16, + for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) T)), + (), + ] + = note: late-bound region is '_#2r + = note: number of external vids: 3 + = note: where T: '_#1r + +note: no external requirements + --> $DIR/ty-param-closure-approximate-lower-bound.rs:28:1 + | +LL | / fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) { +LL | | twice(cell, value, |a, b| invoke(a, b)); +LL | | +LL | | } + | |_^ + | + = note: defining type: generic_fail::<T> + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/ty-param-closure-approximate-lower-bound.rs:29:24 + | +LL | twice(cell, value, |a, b| invoke(a, b)); + | ^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn generic_fail<'a, T: 'a>(cell: Cell<&'a ()>, value: T) { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs new file mode 100644 index 000000000..4343c3aee --- /dev/null +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs @@ -0,0 +1,53 @@ +// compile-flags:-Zverbose + +#![allow(warnings)] +#![feature(rustc_attrs)] + +use std::fmt::Debug; + +fn with_signature<'a, T, F>(x: Box<T>, op: F) -> Box<dyn Debug + 'a> + where F: FnOnce(Box<T>) -> Box<dyn Debug + 'a> +{ + op(x) +} + +#[rustc_regions] +fn no_region<'a, T>(x: Box<T>) -> Box<dyn Debug + 'a> +where + T: Debug, +{ + // Here, the closure winds up being required to prove that `T: + // 'a`. In principle, it could know that, except that it is + // type-checked in a fully generic way, and hence it winds up with + // a propagated requirement that `T: '_#2`, where `'_#2` appears + // in the return type. The caller makes the mapping from `'_#2` to + // `'a` (and subsequently reports an error). + + with_signature(x, |y| y) + //~^ ERROR the parameter type `T` may not live long enough +} + +fn correct_region<'a, T>(x: Box<T>) -> Box<Debug + 'a> +where + T: 'a + Debug, +{ + x +} + +fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a> +where + T: 'b + Debug, +{ + x + //~^ ERROR the parameter type `T` may not live long enough +} + +fn outlives_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a> +where + T: 'b + Debug, + 'b: 'a, +{ + x +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr new file mode 100644 index 000000000..35741859d --- /dev/null +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr @@ -0,0 +1,53 @@ +note: external requirements + --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:23 + | +LL | with_signature(x, |y| y) + | ^^^ + | + = note: defining type: no_region::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::boxed::Box<T>,)) -> std::boxed::Box<(dyn std::fmt::Debug + '_#2r)>, + (), + ] + = note: number of external vids: 3 + = note: where T: '_#2r + +note: no external requirements + --> $DIR/ty-param-closure-outlives-from-return-type.rs:15:1 + | +LL | / fn no_region<'a, T>(x: Box<T>) -> Box<dyn Debug + 'a> +LL | | where +LL | | T: Debug, +LL | | { +... | +LL | | +LL | | } + | |_^ + | + = note: defining type: no_region::<'_#1r, T> + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:23 + | +LL | with_signature(x, |y| y) + | ^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | T: Debug + 'a, + | ++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/ty-param-closure-outlives-from-return-type.rs:41:5 + | +LL | x + | ^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | T: 'b + Debug + 'a, + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs new file mode 100644 index 000000000..d7702def3 --- /dev/null +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs @@ -0,0 +1,83 @@ +// Test that we can propagate `T: 'a` obligations to our caller. See +// `correct_region` for an explanation of how this test is setup; it's +// somewhat intricate. + +// compile-flags:-Zverbose + +#![allow(warnings)] +#![feature(rustc_attrs)] + +use std::cell::Cell; + +fn with_signature<'a, T, F>(a: Cell<&'a ()>, b: T, op: F) +where + F: FnOnce(Cell<&'a ()>, T), +{ + op(a, b) +} + +fn require<'a, T>(_a: &Cell<&'a ()>, _b: &T) +where + T: 'a, +{ +} + +#[rustc_regions] +fn no_region<'a, T>(a: Cell<&'a ()>, b: T) { + with_signature(a, b, |x, y| { + //~^ ERROR the parameter type `T` may not live long enough + // + // See `correct_region`, which explains the point of this + // test. The only difference is that, in the case of this + // function, there is no where clause *anywhere*, and hence we + // get an error (but reported by the closure creator). + require(&x, &y) + }) +} + +#[rustc_regions] +fn correct_region<'a, T>(a: Cell<&'a ()>, b: T) +where + T: 'a, +{ + with_signature(a, b, |x, y| { + // Key point of this test: + // + // The *closure* is being type-checked with all of its free + // regions "universalized". In particular, it does not know + // that `x` has the type `Cell<&'a ()>`, but rather treats it + // as if the type of `x` is `Cell<&'A ()>`, where `'A` is some + // fresh, independent region distinct from the `'a` which + // appears in the environment. The call to `require` here + // forces us then to prove that `T: 'A`, but the closure + // cannot do it on its own. It has to surface this requirement + // to its creator (which knows that `'a == 'A`). + require(&x, &y) + }) +} + +#[rustc_regions] +fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T) +where + T: 'b, +{ + with_signature(a, b, |x, y| { + //~^ ERROR the parameter type `T` may not live long enough + // See `correct_region` + require(&x, &y) + }) +} + +#[rustc_regions] +fn outlives_region<'a, 'b, T>(a: Cell<&'a ()>, b: T) +where + T: 'b, + 'b: 'a, +{ + with_signature(a, b, |x, y| { + // See `correct_region` + require(&x, &y) + }) +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr new file mode 100644 index 000000000..0261bc39e --- /dev/null +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr @@ -0,0 +1,151 @@ +note: external requirements + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:27:26 + | +LL | with_signature(a, b, |x, y| { + | ^^^^^^ + | + = note: defining type: no_region::<T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#1r ()>, T)), + (), + ] + = note: late-bound region is '_#2r + = note: number of external vids: 3 + = note: where T: '_#1r + +note: no external requirements + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:26:1 + | +LL | / fn no_region<'a, T>(a: Cell<&'a ()>, b: T) { +LL | | with_signature(a, b, |x, y| { +LL | | +LL | | // +... | +LL | | }) +LL | | } + | |_^ + | + = note: defining type: no_region::<T> + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:27:26 + | +LL | with_signature(a, b, |x, y| { + | __________________________^ +LL | | +LL | | // +LL | | // See `correct_region`, which explains the point of this +... | +LL | | require(&x, &y) +LL | | }) + | |_____^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn no_region<'a, T: 'a>(a: Cell<&'a ()>, b: T) { + | ++++ + +note: external requirements + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:43:26 + | +LL | with_signature(a, b, |x, y| { + | ^^^^^^ + | + = note: defining type: correct_region::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), + ] + = note: number of external vids: 3 + = note: where T: '_#2r + +note: no external requirements + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:39:1 + | +LL | / fn correct_region<'a, T>(a: Cell<&'a ()>, b: T) +LL | | where +LL | | T: 'a, +LL | | { +... | +LL | | }) +LL | | } + | |_^ + | + = note: defining type: correct_region::<'_#1r, T> + +note: external requirements + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26 + | +LL | with_signature(a, b, |x, y| { + | ^^^^^^ + | + = note: defining type: wrong_region::<'_#1r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#2r ()>, T)), + (), + ] + = note: late-bound region is '_#3r + = note: number of external vids: 4 + = note: where T: '_#2r + +note: no external requirements + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:60:1 + | +LL | / fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T) +LL | | where +LL | | T: 'b, +LL | | { +... | +LL | | }) +LL | | } + | |_^ + | + = note: defining type: wrong_region::<'_#1r, T> + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26 + | +LL | with_signature(a, b, |x, y| { + | __________________________^ +LL | | +LL | | // See `correct_region` +LL | | require(&x, &y) +LL | | }) + | |_____^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | T: 'b + 'a, + | ++++ + +note: external requirements + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:77:26 + | +LL | with_signature(a, b, |x, y| { + | ^^^^^^ + | + = note: defining type: outlives_region::<'_#1r, '_#2r, T>::{closure#0} with closure substs [ + i32, + extern "rust-call" fn((std::cell::Cell<&'_#3r ()>, T)), + (), + ] + = note: number of external vids: 4 + = note: where T: '_#3r + +note: no external requirements + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:72:1 + | +LL | / fn outlives_region<'a, 'b, T>(a: Cell<&'a ()>, b: T) +LL | | where +LL | | T: 'b, +LL | | 'b: 'a, +... | +LL | | }) +LL | | } + | |_^ + | + = note: defining type: outlives_region::<'_#1r, '_#2r, T> + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs b/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs new file mode 100644 index 000000000..98239f416 --- /dev/null +++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs @@ -0,0 +1,27 @@ +// Test that we assume that universal types like `T` outlive the +// function body. + +#![allow(warnings)] + +use std::cell::Cell; + +// No errors here, because `'a` is local to the body. +fn region_within_body<T>(t: T) { + let some_int = 22; + let cell = Cell::new(&some_int); + outlives(cell, t) +} + +// Error here, because T: 'a is not satisfied. +fn region_static<'a, T>(cell: Cell<&'a usize>, t: T) { + outlives(cell, t) + //~^ ERROR the parameter type `T` may not live long enough +} + +fn outlives<'a, T>(x: Cell<&'a usize>, y: T) +where + T: 'a, +{ +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr new file mode 100644 index 000000000..5fb69255d --- /dev/null +++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr @@ -0,0 +1,14 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/ty-param-fn-body.rs:17:5 + | +LL | outlives(cell, t) + | ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn region_static<'a, T: 'a>(cell: Cell<&'a usize>, t: T) { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn.rs b/src/test/ui/nll/ty-outlives/ty-param-fn.rs new file mode 100644 index 000000000..4393a3b41 --- /dev/null +++ b/src/test/ui/nll/ty-outlives/ty-param-fn.rs @@ -0,0 +1,36 @@ +#![allow(warnings)] + +use std::fmt::Debug; + +fn no_region<'a, T>(x: Box<T>) -> Box<Debug + 'a> +where + T: Debug, +{ + x + //~^ ERROR the parameter type `T` may not live long enough +} + +fn correct_region<'a, T>(x: Box<T>) -> Box<Debug + 'a> +where + T: 'a + Debug, +{ + x +} + +fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a> +where + T: 'b + Debug, +{ + x + //~^ ERROR the parameter type `T` may not live long enough +} + +fn outlives_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a> +where + T: 'b + Debug, + 'b: 'a, +{ + x +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn.stderr new file mode 100644 index 000000000..825b26d2f --- /dev/null +++ b/src/test/ui/nll/ty-outlives/ty-param-fn.stderr @@ -0,0 +1,25 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/ty-param-fn.rs:9:5 + | +LL | x + | ^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | T: Debug + 'a, + | ++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/ty-param-fn.rs:24:5 + | +LL | x + | ^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | T: 'b + Debug + 'a, + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/src/test/ui/nll/ty-outlives/ty-param-implied-bounds.rs b/src/test/ui/nll/ty-outlives/ty-param-implied-bounds.rs new file mode 100644 index 000000000..9042844e8 --- /dev/null +++ b/src/test/ui/nll/ty-outlives/ty-param-implied-bounds.rs @@ -0,0 +1,28 @@ +// compile-flags:-Zverbose +// check-pass + +// Test that we assume that universal types like `T` outlive the +// function body. + +use std::cell::Cell; + +fn twice<F, T>(value: T, mut f: F) +where + F: FnMut(Cell<&T>), +{ + f(Cell::new(&value)); + f(Cell::new(&value)); +} + +fn generic<T>(value: T) { + // No error here: + twice(value, |r| invoke(r)); +} + +fn invoke<'a, T>(x: Cell<&'a T>) +where + T: 'a, +{ +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/wf-unreachable.rs b/src/test/ui/nll/ty-outlives/wf-unreachable.rs new file mode 100644 index 000000000..c6f4c4afa --- /dev/null +++ b/src/test/ui/nll/ty-outlives/wf-unreachable.rs @@ -0,0 +1,52 @@ +// Test that we check that user type annotations are well-formed, even in dead +// code. + +fn uninit<'a>() { + return; + let x: &'static &'a (); //~ ERROR lifetime may not live long enough +} + +fn var_type<'a>() { + return; + let x: &'static &'a () = &&(); //~ ERROR lifetime may not live long enough +} + +fn uninit_infer<'a>() { + let x: &'static &'a _; //~ ERROR lifetime may not live long enough + x = && (); +} + +fn infer<'a>() { + return; + let x: &'static &'a _ = &&(); //~ ERROR lifetime may not live long enough +} + +fn uninit_no_var<'a>() { + return; + let _: &'static &'a (); //~ ERROR lifetime may not live long enough +} + +fn no_var<'a>() { + return; + let _: &'static &'a () = &&(); //~ ERROR lifetime may not live long enough +} + +fn infer_no_var<'a>() { + return; + let _: &'static &'a _ = &&(); //~ ERROR lifetime may not live long enough +} + +trait X<'a, 'b> {} + +struct C<'a, 'b, T: X<'a, 'b>>(T, &'a (), &'b ()); + +impl X<'_, '_> for i32 {} +impl<'a> X<'a, 'a> for () {} + +// This type annotation is not well-formed because we substitute `()` for `_`. +fn required_substs<'a>() { + return; + let _: C<'static, 'a, _> = C((), &(), &()); //~ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/src/test/ui/nll/ty-outlives/wf-unreachable.stderr b/src/test/ui/nll/ty-outlives/wf-unreachable.stderr new file mode 100644 index 000000000..a62157f44 --- /dev/null +++ b/src/test/ui/nll/ty-outlives/wf-unreachable.stderr @@ -0,0 +1,73 @@ +error: lifetime may not live long enough + --> $DIR/wf-unreachable.rs:6:12 + | +LL | fn uninit<'a>() { + | -- lifetime `'a` defined here +LL | return; +LL | let x: &'static &'a (); + | ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/wf-unreachable.rs:11:12 + | +LL | fn var_type<'a>() { + | -- lifetime `'a` defined here +LL | return; +LL | let x: &'static &'a () = &&(); + | ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/wf-unreachable.rs:15:12 + | +LL | fn uninit_infer<'a>() { + | -- lifetime `'a` defined here +LL | let x: &'static &'a _; + | ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/wf-unreachable.rs:21:12 + | +LL | fn infer<'a>() { + | -- lifetime `'a` defined here +LL | return; +LL | let x: &'static &'a _ = &&(); + | ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/wf-unreachable.rs:26:12 + | +LL | fn uninit_no_var<'a>() { + | -- lifetime `'a` defined here +LL | return; +LL | let _: &'static &'a (); + | ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/wf-unreachable.rs:31:12 + | +LL | fn no_var<'a>() { + | -- lifetime `'a` defined here +LL | return; +LL | let _: &'static &'a () = &&(); + | ^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/wf-unreachable.rs:36:12 + | +LL | fn infer_no_var<'a>() { + | -- lifetime `'a` defined here +LL | return; +LL | let _: &'static &'a _ = &&(); + | ^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/wf-unreachable.rs:49:12 + | +LL | fn required_substs<'a>() { + | -- lifetime `'a` defined here +LL | return; +LL | let _: C<'static, 'a, _> = C((), &(), &()); + | ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: aborting due to 8 previous errors + |