use implied bounds when checking opaque types
This commit is contained in:
parent
4a18324a4d
commit
d548747c85
7 changed files with 189 additions and 4 deletions
|
|
@ -0,0 +1,25 @@
|
|||
error[E0309]: the parameter type `T` may not live long enough
|
||||
--> $DIR/wf-in-associated-type.rs:36:23
|
||||
|
|
||||
LL | type Opaque = impl Sized + 'a;
|
||||
| ^^^^^^^^^^^^^^^ ...so that the type `&'a T` will meet its required lifetime bounds
|
||||
|
|
||||
help: consider adding an explicit lifetime bound...
|
||||
|
|
||||
LL | impl<'a, T: 'a> Trait<'a, T> for () {
|
||||
| ++++
|
||||
|
||||
error[E0309]: the parameter type `T` may not live long enough
|
||||
--> $DIR/wf-in-associated-type.rs:36:23
|
||||
|
|
||||
LL | type Opaque = impl Sized + 'a;
|
||||
| ^^^^^^^^^^^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at
|
||||
|
|
||||
help: consider adding an explicit lifetime bound...
|
||||
|
|
||||
LL | impl<'a, T: 'a> Trait<'a, T> for () {
|
||||
| ++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0309`.
|
||||
45
tests/ui/type-alias-impl-trait/wf-in-associated-type.rs
Normal file
45
tests/ui/type-alias-impl-trait/wf-in-associated-type.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
// WF check for impl Trait in associated type position.
|
||||
//
|
||||
// revisions: pass fail
|
||||
// [pass] check-pass
|
||||
// [fail] check-fail
|
||||
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
|
||||
// The hidden type here (`&'a T`) requires proving `T: 'a`.
|
||||
// We know it holds because of implied bounds from the impl header.
|
||||
#[cfg(pass)]
|
||||
mod pass {
|
||||
trait Trait<Req> {
|
||||
type Opaque1;
|
||||
fn constrain_opaque1(req: Req) -> Self::Opaque1;
|
||||
}
|
||||
|
||||
impl<'a, T> Trait<&'a T> for () {
|
||||
type Opaque1 = impl IntoIterator<Item = impl Sized + 'a>;
|
||||
fn constrain_opaque1(req: &'a T) -> Self::Opaque1 {
|
||||
[req]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The hidden type here (`&'a T`) requires proving `T: 'a`,
|
||||
// but that is not known to hold in the impl.
|
||||
#[cfg(fail)]
|
||||
mod fail {
|
||||
trait Trait<'a, T> {
|
||||
type Opaque;
|
||||
fn constrain_opaque(req: &'a T) -> Self::Opaque;
|
||||
}
|
||||
|
||||
impl<'a, T> Trait<'a, T> for () {
|
||||
type Opaque = impl Sized + 'a;
|
||||
//[fail]~^ ERROR the parameter type `T` may not live long enough
|
||||
//[fail]~| ERROR the parameter type `T` may not live long enough
|
||||
fn constrain_opaque(req: &'a T) -> Self::Opaque {
|
||||
req
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
19
tests/ui/type-alias-impl-trait/wf-nested.fail.stderr
Normal file
19
tests/ui/type-alias-impl-trait/wf-nested.fail.stderr
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
error[E0310]: the parameter type `T` may not live long enough
|
||||
--> $DIR/wf-nested.rs:55:27
|
||||
|
|
||||
LL | type InnerOpaque<T> = impl Sized;
|
||||
| ^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
|
||||
|
|
||||
note: ...that is required by this bound
|
||||
--> $DIR/wf-nested.rs:12:20
|
||||
|
|
||||
LL | struct IsStatic<T: 'static>(T);
|
||||
| ^^^^^^^
|
||||
help: consider adding an explicit lifetime bound...
|
||||
|
|
||||
LL | type InnerOpaque<T: 'static> = impl Sized;
|
||||
| +++++++++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0310`.
|
||||
14
tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr
Normal file
14
tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
error[E0310]: the parameter type `T` may not live long enough
|
||||
--> $DIR/wf-nested.rs:46:17
|
||||
|
|
||||
LL | let _ = outer.get();
|
||||
| ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
||||
|
|
||||
help: consider adding an explicit lifetime bound...
|
||||
|
|
||||
LL | fn test<T: 'static>() {
|
||||
| +++++++++
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0310`.
|
||||
60
tests/ui/type-alias-impl-trait/wf-nested.rs
Normal file
60
tests/ui/type-alias-impl-trait/wf-nested.rs
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
// 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-pass
|
||||
// [pass_sound] check-fail
|
||||
// [fail] check-fail
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
struct IsStatic<T: 'static>(T);
|
||||
|
||||
trait Trait<In> {
|
||||
type Out;
|
||||
|
||||
fn get(&self) -> Result<Self::Out, ()> {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
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> {}
|
||||
}
|
||||
|
||||
// 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> {}
|
||||
|
||||
fn test<T>() {
|
||||
let outer = define::<T>();
|
||||
let _ = outer.get(); //[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; //[fail]~ ERROR `T` may not live long enough
|
||||
type OuterOpaque<T> = impl Trait<&'static T, Out = InnerOpaque<T>>;
|
||||
fn define<T>() -> OuterOpaque<T> {}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue