diff --git a/tests/ui/type-alias-impl-trait/wf-check-definition-site.rs b/tests/ui/type-alias-impl-trait/wf-check-definition-site.rs index 59c43574f8b..19dd4c17936 100644 --- a/tests/ui/type-alias-impl-trait/wf-check-definition-site.rs +++ b/tests/ui/type-alias-impl-trait/wf-check-definition-site.rs @@ -4,6 +4,11 @@ // // `Opaque<'a> = Static<&'a str>`, vs // `Opaque<'a> = Static<&'static str>`. +// +// The hidden type of the opaque ends up as `Static<'?0 str>`. When +// computing member constraints we end up choosing `'a` for `?0` unless +// `?0` is already required to outlive `'a`. We achieve this by checking +// that `Static<'?0 str>` is well-formed. #![feature(type_alias_impl_trait)] struct Static(T); diff --git a/tests/ui/type-alias-impl-trait/wf-nested.rs b/tests/ui/type-alias-impl-trait/wf-nested.rs index 7f070bbe6c2..56c524c6db0 100644 --- a/tests/ui/type-alias-impl-trait/wf-nested.rs +++ b/tests/ui/type-alias-impl-trait/wf-nested.rs @@ -1,12 +1,8 @@ // Well-formedness of nested opaque types, i.e. `impl Sized` in -// `type Outer = impl Trait`. -// See the comments below. -// -//@ revisions: pass pass_sound fail -//@ [pass] check-fail -//@ [pass_sound] check-fail -//@ [fail] check-fail - +// `type Outer = impl Trait`. We check that +// the nested type is well-formed, even though this would also +// be implied by the item bounds of the opaque being +// well-formed. See the comments below. #![feature(type_alias_impl_trait)] struct IsStatic(T); @@ -23,46 +19,26 @@ impl Trait<&'static T> for () { type Out = IsStatic; } -// The hidden type for `impl Sized` is `IsStatic`, which requires `T: 'static`. -// We know it is well-formed because it can *only* be referenced as a projection: -// as Trait<&'static T>>::Out`. -// So any instantiation of the type already requires proving `T: 'static`. -#[cfg(pass)] -mod pass { - use super::*; - type OuterOpaque = impl Trait<&'static T, Out = impl Sized>; - fn define() -> OuterOpaque {} - //[pass]~^ ERROR `T` may not live long enough - fn define_rpit() -> impl Trait<&'static T, Out = impl Sized> {} - //[pass]~^ ERROR the parameter type `T` may not live long enough -} +// We could theoretically allow this (and previously did), as even +// though the nested opaque is not well-formed, it can only be +// used by normalizing the projection +// as Trait<&'static T>>::Out +// Assuming that we check that this projection is well-formed, the wf +// of the nested opaque is implied. +type OuterOpaque1 = impl Trait<&'static T, Out = impl Sized>; +fn define() -> OuterOpaque1 {} +//~^ ERROR `T` may not live long enough -// Test the soundness of `pass` - We should require `T: 'static` at the use site. -#[cfg(pass_sound)] -mod pass_sound { - use super::*; - type OuterOpaque = impl Trait<&'static T, Out = impl Sized>; - fn define() -> OuterOpaque {} - //[pass_sound]~^ ERROR `T` may not live long enough +fn define_rpit() -> impl Trait<&'static T, Out = impl Sized> {} +//~^ ERROR the parameter type `T` may not live long enough - fn test() { - let outer = define::(); - let _ = outer.get(); - //[pass_sound]~^ ERROR `T` may not live long enough - //[pass_sound]~| ERROR `T` may not live long enough - } -} - -// Similar to `pass` but here `impl Sized` can be referenced directly as -// InnerOpaque, so we require an explicit bound `T: 'static`. -#[cfg(fail)] -mod fail { - use super::*; - type InnerOpaque = impl Sized; - type OuterOpaque = impl Trait<&'static T, Out = InnerOpaque>; - fn define() -> OuterOpaque {} - //[fail]~^ ERROR the parameter type `T` may not live long enough -} +// Similar to `define` but here `impl Sized` can be referenced directly as +// InnerOpaque, so the `'static` bound is definitely required for +// soundness. +type InnerOpaque = impl Sized; +type OuterOpaque2 = impl Trait<&'static T, Out = InnerOpaque>; +fn define_nested_rpit() -> OuterOpaque2 {} +//~^ ERROR the parameter type `T` may not live long enough fn main() {} diff --git a/tests/ui/type-alias-impl-trait/wf-nested.stderr b/tests/ui/type-alias-impl-trait/wf-nested.stderr new file mode 100644 index 00000000000..6d50e11c5da --- /dev/null +++ b/tests/ui/type-alias-impl-trait/wf-nested.stderr @@ -0,0 +1,45 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/wf-nested.rs:30:35 + | +LL | fn define() -> OuterOpaque1 {} + | ^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | fn define() -> OuterOpaque1 {} + | +++++++++ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/wf-nested.rs:33:65 + | +LL | fn define_rpit() -> impl Trait<&'static T, Out = impl Sized> {} + | ^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | fn define_rpit() -> impl Trait<&'static T, Out = impl Sized> {} + | +++++++++ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/wf-nested.rs:41:47 + | +LL | fn define_nested_rpit() -> OuterOpaque2 {} + | ^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound + | +LL | fn define_nested_rpit() -> OuterOpaque2 {} + | +++++++++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0310`.