Skip to content

Commit af0d508

Browse files
committedFeb 27, 2024
update comments
1 parent 300cffa commit af0d508

File tree

3 files changed

+74
-48
lines changed

3 files changed

+74
-48
lines changed
 

‎tests/ui/type-alias-impl-trait/wf-check-definition-site.rs

+5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
//
55
// `Opaque<'a> = Static<&'a str>`, vs
66
// `Opaque<'a> = Static<&'static str>`.
7+
//
8+
// The hidden type of the opaque ends up as `Static<'?0 str>`. When
9+
// computing member constraints we end up choosing `'a` for `?0` unless
10+
// `?0` is already required to outlive `'a`. We achieve this by checking
11+
// that `Static<'?0 str>` is well-formed.
712
#![feature(type_alias_impl_trait)]
813

914
struct Static<T: 'static>(T);
+24-48
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
// Well-formedness of nested opaque types, i.e. `impl Sized` in
2-
// `type Outer = impl Trait<Assoc = impl Sized>`.
3-
// See the comments below.
4-
//
5-
//@ revisions: pass pass_sound fail
6-
//@ [pass] check-fail
7-
//@ [pass_sound] check-fail
8-
//@ [fail] check-fail
9-
2+
// `type Outer = impl Trait<Assoc = impl Sized>`. We check that
3+
// the nested type is well-formed, even though this would also
4+
// be implied by the item bounds of the opaque being
5+
// well-formed. See the comments below.
106
#![feature(type_alias_impl_trait)]
117

128
struct IsStatic<T: 'static>(T);
@@ -23,46 +19,26 @@ impl<T> Trait<&'static T> for () {
2319
type Out = IsStatic<T>;
2420
}
2521

26-
// The hidden type for `impl Sized` is `IsStatic<T>`, which requires `T: 'static`.
27-
// We know it is well-formed because it can *only* be referenced as a projection:
28-
// <OuterOpaque<T> as Trait<&'static T>>::Out`.
29-
// So any instantiation of the type already requires proving `T: 'static`.
30-
#[cfg(pass)]
31-
mod pass {
32-
use super::*;
33-
type OuterOpaque<T> = impl Trait<&'static T, Out = impl Sized>;
34-
fn define<T>() -> OuterOpaque<T> {}
35-
//[pass]~^ ERROR `T` may not live long enough
36-
37-
fn define_rpit<T>() -> impl Trait<&'static T, Out = impl Sized> {}
38-
//[pass]~^ ERROR the parameter type `T` may not live long enough
39-
}
40-
41-
// Test the soundness of `pass` - We should require `T: 'static` at the use site.
42-
#[cfg(pass_sound)]
43-
mod pass_sound {
44-
use super::*;
45-
type OuterOpaque<T> = impl Trait<&'static T, Out = impl Sized>;
46-
fn define<T>() -> OuterOpaque<T> {}
47-
//[pass_sound]~^ ERROR `T` may not live long enough
4822

49-
fn test<T>() {
50-
let outer = define::<T>();
51-
let _ = outer.get();
52-
//[pass_sound]~^ ERROR `T` may not live long enough
53-
//[pass_sound]~| ERROR `T` may not live long enough
54-
}
55-
}
56-
57-
// Similar to `pass` but here `impl Sized` can be referenced directly as
58-
// InnerOpaque<T>, so we require an explicit bound `T: 'static`.
59-
#[cfg(fail)]
60-
mod fail {
61-
use super::*;
62-
type InnerOpaque<T> = impl Sized;
63-
type OuterOpaque<T> = impl Trait<&'static T, Out = InnerOpaque<T>>;
64-
fn define<T>() -> OuterOpaque<T> {}
65-
//[fail]~^ ERROR the parameter type `T` may not live long enough
66-
}
23+
// We could theoretically allow this (and previously did), as even
24+
// though the nested opaque is not well-formed, it can only be
25+
// used by normalizing the projection
26+
// <OuterOpaque1<T> as Trait<&'static T>>::Out
27+
// Assuming that we check that this projection is well-formed, the wf
28+
// of the nested opaque is implied.
29+
type OuterOpaque1<T> = impl Trait<&'static T, Out = impl Sized>;
30+
fn define<T>() -> OuterOpaque1<T> {}
31+
//~^ ERROR `T` may not live long enough
32+
33+
fn define_rpit<T>() -> impl Trait<&'static T, Out = impl Sized> {}
34+
//~^ ERROR the parameter type `T` may not live long enough
35+
36+
// Similar to `define` but here `impl Sized` can be referenced directly as
37+
// InnerOpaque<T>, so the `'static` bound is definitely required for
38+
// soundness.
39+
type InnerOpaque<T> = impl Sized;
40+
type OuterOpaque2<T> = impl Trait<&'static T, Out = InnerOpaque<T>>;
41+
fn define_nested_rpit<T>() -> OuterOpaque2<T> {}
42+
//~^ ERROR the parameter type `T` may not live long enough
6743

6844
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
error[E0310]: the parameter type `T` may not live long enough
2+
--> $DIR/wf-nested.rs:30:35
3+
|
4+
LL | fn define<T>() -> OuterOpaque1<T> {}
5+
| ^^
6+
| |
7+
| the parameter type `T` must be valid for the static lifetime...
8+
| ...so that the type `T` will meet its required lifetime bounds
9+
|
10+
help: consider adding an explicit lifetime bound
11+
|
12+
LL | fn define<T: 'static>() -> OuterOpaque1<T> {}
13+
| +++++++++
14+
15+
error[E0310]: the parameter type `T` may not live long enough
16+
--> $DIR/wf-nested.rs:33:65
17+
|
18+
LL | fn define_rpit<T>() -> impl Trait<&'static T, Out = impl Sized> {}
19+
| ^^
20+
| |
21+
| the parameter type `T` must be valid for the static lifetime...
22+
| ...so that the type `T` will meet its required lifetime bounds
23+
|
24+
help: consider adding an explicit lifetime bound
25+
|
26+
LL | fn define_rpit<T: 'static>() -> impl Trait<&'static T, Out = impl Sized> {}
27+
| +++++++++
28+
29+
error[E0310]: the parameter type `T` may not live long enough
30+
--> $DIR/wf-nested.rs:41:47
31+
|
32+
LL | fn define_nested_rpit<T>() -> OuterOpaque2<T> {}
33+
| ^^
34+
| |
35+
| the parameter type `T` must be valid for the static lifetime...
36+
| ...so that the type `T` will meet its required lifetime bounds
37+
|
38+
help: consider adding an explicit lifetime bound
39+
|
40+
LL | fn define_nested_rpit<T: 'static>() -> OuterOpaque2<T> {}
41+
| +++++++++
42+
43+
error: aborting due to 3 previous errors
44+
45+
For more information about this error, try `rustc --explain E0310`.

0 commit comments

Comments
 (0)