Skip to content

Commit

Permalink
update comments
Browse files Browse the repository at this point in the history
  • Loading branch information
lcnr committed Feb 27, 2024
1 parent 300cffa commit af0d508
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 48 deletions.
5 changes: 5 additions & 0 deletions tests/ui/type-alias-impl-trait/wf-check-definition-site.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
72 changes: 24 additions & 48 deletions tests/ui/type-alias-impl-trait/wf-nested.rs
Original file line number Diff line number Diff line change
@@ -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);
Expand All @@ -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
}

// 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 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
}
// 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

fn define_rpit<T>() -> impl Trait<&'static T, Out = impl Sized> {}
//~^ 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() {}
45 changes: 45 additions & 0 deletions tests/ui/type-alias-impl-trait/wf-nested.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit af0d508

Please sign in to comment.