Skip to content

Commit 6e7bcff

Browse files
authored
Rollup merge of rust-lang#60409 - JohnTitor:error-for-existential-type, r=oli-obk
Require a trait in the bounds of existential types Fixes rust-lang#53090 r? @oli-obk
2 parents bc4a2ad + 748d978 commit 6e7bcff

16 files changed

+106
-14
lines changed

src/librustc_passes/ast_validation.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use syntax::ptr::P;
2020
use syntax::visit::{self, Visitor};
2121
use syntax::{span_err, struct_span_err, walk_list};
2222
use syntax_ext::proc_macro_decls::is_proc_macro_attr;
23-
use syntax_pos::Span;
23+
use syntax_pos::{Span, MultiSpan};
2424
use errors::Applicability;
2525
use log::debug;
2626

@@ -679,6 +679,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
679679
"unions cannot have zero fields");
680680
}
681681
}
682+
ItemKind::Existential(ref bounds, _) => {
683+
if !bounds.iter()
684+
.any(|b| if let GenericBound::Trait(..) = *b { true } else { false }) {
685+
let msp = MultiSpan::from_spans(bounds.iter()
686+
.map(|bound| bound.span()).collect());
687+
self.err_handler().span_err(msp, "at least one trait must be specified");
688+
}
689+
}
682690
_ => {}
683691
}
684692

src/test/run-pass/existential_type.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,14 @@ fn my_other_iter<U>(u: U) -> MyOtherIter<U> {
6868
}
6969

7070
trait Trait {}
71-
existential type GenericBound<'a, T: Trait>: 'a;
71+
existential type GenericBound<'a, T: Trait>: Sized + 'a;
7272

7373
fn generic_bound<'a, T: Trait + 'a>(t: T) -> GenericBound<'a, T> {
7474
t
7575
}
7676

7777
mod pass_through {
78-
pub existential type Passthrough<T>: 'static;
78+
pub existential type Passthrough<T>: Sized + 'static;
7979

8080
fn define_passthrough<T: 'static>(t: T) -> Passthrough<T> {
8181
t
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#![feature(existential_type)]
2+
3+
existential type Foo: 'static;
4+
//~^ ERROR: at least one trait must be specified
5+
6+
fn foo() -> Foo {
7+
"foo"
8+
}
9+
10+
fn bar() -> impl 'static { //~ ERROR: at least one trait must be specified
11+
"foo"
12+
}
13+
14+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: at least one trait must be specified
2+
--> $DIR/existential-types-with-no-traits.rs:3:23
3+
|
4+
LL | existential type Foo: 'static;
5+
| ^^^^^^^
6+
7+
error: at least one trait must be specified
8+
--> $DIR/existential-types-with-no-traits.rs:10:13
9+
|
10+
LL | fn bar() -> impl 'static {
11+
| ^^^^^^^^^^^^
12+
13+
error: aborting due to 2 previous errors
14+

src/test/ui/existential_types/generic_nondefining_use.rs

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ fn main() {}
44

55
existential type Cmp<T>: 'static;
66
//~^ ERROR could not find defining uses
7+
//~^^ ERROR: at least one trait must be specified
8+
79

810
// not a defining use, because it doesn't define *all* possible generics
911
fn cmp() -> Cmp<u32> { //~ ERROR defining existential type use does not fully define

src/test/ui/existential_types/generic_nondefining_use.stderr

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1+
error: at least one trait must be specified
2+
--> $DIR/generic_nondefining_use.rs:5:26
3+
|
4+
LL | existential type Cmp<T>: 'static;
5+
| ^^^^^^^
6+
17
error: defining existential type use does not fully define existential type
2-
--> $DIR/generic_nondefining_use.rs:9:1
8+
--> $DIR/generic_nondefining_use.rs:11:1
39
|
410
LL | / fn cmp() -> Cmp<u32> {
511
LL | | 5u32
@@ -12,5 +18,5 @@ error: could not find defining uses
1218
LL | existential type Cmp<T>: 'static;
1319
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1420

15-
error: aborting due to 2 previous errors
21+
error: aborting due to 3 previous errors
1622

src/test/ui/existential_types/generic_not_used.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
fn main() {}
44

55
existential type WrongGeneric<T: 'static>: 'static;
6+
//~^ ERROR: at least one trait must be specified
67

78
fn wrong_generic<U: 'static, V: 'static>(_: U, v: V) -> WrongGeneric<U> {
89
//~^ ERROR type parameter `V` is part of concrete type but not used in parameter list
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1+
error: at least one trait must be specified
2+
--> $DIR/generic_not_used.rs:5:44
3+
|
4+
LL | existential type WrongGeneric<T: 'static>: 'static;
5+
| ^^^^^^^
6+
17
error: type parameter `V` is part of concrete type but not used in parameter list for existential type
2-
--> $DIR/generic_not_used.rs:7:73
8+
--> $DIR/generic_not_used.rs:8:73
39
|
410
LL | fn wrong_generic<U: 'static, V: 'static>(_: U, v: V) -> WrongGeneric<U> {
511
| _________________________________________________________________________^
@@ -8,5 +14,5 @@ LL | | v
814
LL | | }
915
| |_^
1016

11-
error: aborting due to previous error
17+
error: aborting due to 2 previous errors
1218

src/test/ui/existential_types/generic_type_does_not_live_long_enough.rs

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ fn main() {
88

99
existential type WrongGeneric<T>: 'static;
1010
//~^ ERROR the parameter type `T` may not live long enough
11+
//~^^ ERROR: at least one trait must be specified
1112

1213
fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
1314
t

src/test/ui/existential_types/generic_type_does_not_live_long_enough.stderr

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
error: at least one trait must be specified
2+
--> $DIR/generic_type_does_not_live_long_enough.rs:9:35
3+
|
4+
LL | existential type WrongGeneric<T>: 'static;
5+
| ^^^^^^^
6+
17
error[E0308]: mismatched types
28
--> $DIR/generic_type_does_not_live_long_enough.rs:6:18
39
|
@@ -22,7 +28,7 @@ note: ...so that the type `T` will meet its required lifetime bounds
2228
LL | existential type WrongGeneric<T>: 'static;
2329
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2430

25-
error: aborting due to 2 previous errors
31+
error: aborting due to 3 previous errors
2632

2733
Some errors have detailed explanations: E0308, E0310.
2834
For more information about an error, try `rustc --explain E0308`.

src/test/ui/existential_types/generic_underconstrained.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ fn main() {}
44

55
trait Trait {}
66
existential type Underconstrained<T: Trait>: 'static; //~ ERROR the trait bound `T: Trait`
7+
//~^ ERROR: at least one trait must be specified
78

89
// no `Trait` bound
910
fn underconstrain<T>(_: T) -> Underconstrained<T> {

src/test/ui/existential_types/generic_underconstrained.stderr

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
error: at least one trait must be specified
2+
--> $DIR/generic_underconstrained.rs:6:46
3+
|
4+
LL | existential type Underconstrained<T: Trait>: 'static;
5+
| ^^^^^^^
6+
17
error[E0277]: the trait bound `T: Trait` is not satisfied
28
--> $DIR/generic_underconstrained.rs:6:1
39
|
@@ -7,6 +13,6 @@ LL | existential type Underconstrained<T: Trait>: 'static;
713
= help: consider adding a `where T: Trait` bound
814
= note: the return type of a function must have a statically known size
915

10-
error: aborting due to previous error
16+
error: aborting due to 2 previous errors
1117

1218
For more information about this error, try `rustc --explain E0277`.

src/test/ui/existential_types/generic_underconstrained2.rs

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ fn main() {}
44

55
existential type Underconstrained<T: std::fmt::Debug>: 'static;
66
//~^ ERROR `U` doesn't implement `std::fmt::Debug`
7+
//~^^ ERROR: at least one trait must be specified
78

89
// not a defining use, because it doesn't define *all* possible generics
910
fn underconstrained<U>(_: U) -> Underconstrained<U> {
@@ -12,6 +13,7 @@ fn underconstrained<U>(_: U) -> Underconstrained<U> {
1213

1314
existential type Underconstrained2<T: std::fmt::Debug>: 'static;
1415
//~^ ERROR `V` doesn't implement `std::fmt::Debug`
16+
//~^^ ERROR: at least one trait must be specified
1517

1618
// not a defining use, because it doesn't define *all* possible generics
1719
fn underconstrained2<U, V>(_: U, _: V) -> Underconstrained2<V> {

src/test/ui/existential_types/generic_underconstrained2.stderr

+14-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
error: at least one trait must be specified
2+
--> $DIR/generic_underconstrained2.rs:5:56
3+
|
4+
LL | existential type Underconstrained<T: std::fmt::Debug>: 'static;
5+
| ^^^^^^^
6+
7+
error: at least one trait must be specified
8+
--> $DIR/generic_underconstrained2.rs:14:57
9+
|
10+
LL | existential type Underconstrained2<T: std::fmt::Debug>: 'static;
11+
| ^^^^^^^
12+
113
error[E0277]: `U` doesn't implement `std::fmt::Debug`
214
--> $DIR/generic_underconstrained2.rs:5:1
315
|
@@ -9,7 +21,7 @@ LL | existential type Underconstrained<T: std::fmt::Debug>: 'static;
921
= note: the return type of a function must have a statically known size
1022

1123
error[E0277]: `V` doesn't implement `std::fmt::Debug`
12-
--> $DIR/generic_underconstrained2.rs:13:1
24+
--> $DIR/generic_underconstrained2.rs:14:1
1325
|
1426
LL | existential type Underconstrained2<T: std::fmt::Debug>: 'static;
1527
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
@@ -18,6 +30,6 @@ LL | existential type Underconstrained2<T: std::fmt::Debug>: 'static;
1830
= help: consider adding a `where V: std::fmt::Debug` bound
1931
= note: the return type of a function must have a statically known size
2032

21-
error: aborting due to 2 previous errors
33+
error: aborting due to 4 previous errors
2234

2335
For more information about this error, try `rustc --explain E0277`.

src/test/ui/existential_types/unused_generic_param.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1-
// compile-pass
21
#![feature(existential_type)]
32

43
fn main() {
54
}
65

7-
// test that unused generic parameters are ok
86
existential type PartiallyDefined<T>: 'static;
7+
//~^ ERROR: at least one trait must be specified
98

109
fn partially_defined<T: std::fmt::Debug>(_: T) -> PartiallyDefined<T> {
1110
4u32
1211
}
1312

14-
// test that unused generic parameters are ok
1513
existential type PartiallyDefined2<T>: 'static;
14+
//~^ ERROR: at least one trait must be specified
1615

1716
fn partially_defined2<T: std::fmt::Debug>(_: T) -> PartiallyDefined2<T> {
1817
4u32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: at least one trait must be specified
2+
--> $DIR/unused_generic_param.rs:6:39
3+
|
4+
LL | existential type PartiallyDefined<T>: 'static;
5+
| ^^^^^^^
6+
7+
error: at least one trait must be specified
8+
--> $DIR/unused_generic_param.rs:13:40
9+
|
10+
LL | existential type PartiallyDefined2<T>: 'static;
11+
| ^^^^^^^
12+
13+
error: aborting due to 2 previous errors
14+

0 commit comments

Comments
 (0)