1
Fork 0

update comments

This commit is contained in:
lcnr 2024-02-27 17:39:36 +01:00
parent 300cffa2d5
commit af0d5082ee
3 changed files with 72 additions and 46 deletions

View file

@ -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: 'static>(T);

View file

@ -1,12 +1,8 @@
// Well-formedness of nested opaque types, i.e. `impl Sized` in
// `type Outer = impl Trait<Assoc = impl Sized>`.
// See the comments below.
//
//@ revisions: pass pass_sound fail
//@ [pass] check-fail
//@ [pass_sound] check-fail
//@ [fail] check-fail
// `type Outer = impl Trait<Assoc = impl Sized>`. 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: 'static>(T);
@ -23,46 +19,26 @@ impl<T> Trait<&'static T> for () {
type Out = IsStatic<T>;
}
// The hidden type for `impl Sized` is `IsStatic<T>`, which requires `T: 'static`.
// We know it is well-formed because it can *only* be referenced as a projection:
// <OuterOpaque<T> as Trait<&'static T>>::Out`.
// So any instantiation of the type already requires proving `T: 'static`.
#[cfg(pass)]
mod pass {
use super::*;
type OuterOpaque<T> = impl Trait<&'static T, Out = impl Sized>;
fn define<T>() -> OuterOpaque<T> {}
//[pass]~^ ERROR `T` may not live long enough
fn define_rpit<T>() -> 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
// <OuterOpaque1<T> 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<T> = impl Trait<&'static T, Out = impl Sized>;
fn define<T>() -> OuterOpaque1<T> {}
//~^ 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<T> = impl Trait<&'static T, Out = impl Sized>;
fn define<T>() -> OuterOpaque<T> {}
//[pass_sound]~^ ERROR `T` may not live long enough
fn define_rpit<T>() -> impl Trait<&'static T, Out = impl Sized> {}
//~^ ERROR the parameter type `T` may not live long enough
fn test<T>() {
let outer = define::<T>();
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<T>, so we require an explicit bound `T: 'static`.
#[cfg(fail)]
mod fail {
use super::*;
type InnerOpaque<T> = impl Sized;
type OuterOpaque<T> = impl Trait<&'static T, Out = InnerOpaque<T>>;
fn define<T>() -> OuterOpaque<T> {}
//[fail]~^ ERROR the parameter type `T` may not live long enough
}
// Similar to `define` but here `impl Sized` can be referenced directly as
// InnerOpaque<T>, so the `'static` bound is definitely required for
// soundness.
type InnerOpaque<T> = impl Sized;
type OuterOpaque2<T> = impl Trait<&'static T, Out = InnerOpaque<T>>;
fn define_nested_rpit<T>() -> OuterOpaque2<T> {}
//~^ ERROR the parameter type `T` may not live long enough
fn main() {}

View file

@ -0,0 +1,45 @@
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/wf-nested.rs:30:35
|
LL | fn define<T>() -> OuterOpaque1<T> {}
| ^^
| |
| 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<T: 'static>() -> OuterOpaque1<T> {}
| +++++++++
error[E0310]: the parameter type `T` may not live long enough
--> $DIR/wf-nested.rs:33:65
|
LL | fn define_rpit<T>() -> 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<T: 'static>() -> 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<T>() -> OuterOpaque2<T> {}
| ^^
| |
| 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<T: 'static>() -> OuterOpaque2<T> {}
| +++++++++
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0310`.