diff options
| author | Oliver Scherer <github35764891676564198441@oli-obk.de> | 2019-02-14 13:02:36 +0100 |
|---|---|---|
| committer | Oliver Scherer <github35764891676564198441@oli-obk.de> | 2019-02-14 13:02:36 +0100 |
| commit | eb98d318b28cc177f608d57fb5b9b017235b515d (patch) | |
| tree | cf1a1fc49128b7205f29ce4f18a773782d93d7cf | |
| parent | c93bce85e5e085274febf1ca71b551de3f51429c (diff) | |
| download | rust-eb98d318b28cc177f608d57fb5b9b017235b515d.tar.gz rust-eb98d318b28cc177f608d57fb5b9b017235b515d.zip | |
Require defining uses to use generic parameters for all parameters of a generic existential type
10 files changed, 98 insertions, 27 deletions
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index b26a6a2292a..b50a165ba9c 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1385,10 +1385,19 @@ fn find_existential_constraints<'a, 'tcx>( .subst(self.tcx, substs) .walk() .filter_map(|t| match &t.sty { - ty::Param(p) => Some(*index_map.get(p).unwrap()), - _ => None, - }).collect(); - if let Some((prev_span, prev_ty, ref prev_indices)) = self.found { + ty::Param(p) => Some(*index_map.get(p).unwrap()), + _ => None, + }).collect(); + let is_param = |ty: ty::Ty| match ty.sty { + ty::Param(_) => true, + _ => false, + }; + if !substs.types().all(is_param) { + self.tcx.sess.span_err( + span, + "defining existential type use does not fully define existential type", + ); + } else if let Some((prev_span, prev_ty, ref prev_indices)) = self.found { let mut ty = concrete_type.walk().fuse(); let mut p_ty = prev_ty.walk().fuse(); let iter_eq = (&mut ty).zip(&mut p_ty).all(|(t, p)| match (&t.sty, &p.sty) { diff --git a/src/test/ui/existential_types/bound_reduction2.rs b/src/test/ui/existential_types/bound_reduction2.rs index d8ade50c79c..542e076d88d 100644 --- a/src/test/ui/existential_types/bound_reduction2.rs +++ b/src/test/ui/existential_types/bound_reduction2.rs @@ -8,11 +8,12 @@ trait TraitWithAssoc { } existential type Foo<V>: Trait<V>; +//~^ ERROR could not find defining uses trait Trait<U> {} impl<W> Trait<W> for () {} -fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> { //~ ERROR non-defining +fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> { //~ ERROR does not fully define () } diff --git a/src/test/ui/existential_types/bound_reduction2.stderr b/src/test/ui/existential_types/bound_reduction2.stderr index 8e822ca6d8b..f51f1c9a4e5 100644 --- a/src/test/ui/existential_types/bound_reduction2.stderr +++ b/src/test/ui/existential_types/bound_reduction2.stderr @@ -1,16 +1,16 @@ -error: non-defining existential type use in defining scope - --> $DIR/bound_reduction2.rs:16:1 +error: defining existential type use does not fully define existential type + --> $DIR/bound_reduction2.rs:17:1 | -LL | / fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> { //~ ERROR non-defining +LL | / fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> { //~ ERROR does not fully define LL | | () LL | | } | |_^ - | -note: used non-generic type <T as TraitWithAssoc>::Assoc for generic parameter - --> $DIR/bound_reduction2.rs:10:22 + +error: could not find defining uses + --> $DIR/bound_reduction2.rs:10:1 | LL | existential type Foo<V>: Trait<V>; - | ^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/src/test/ui/existential_types/generic_duplicate_param_use10.rs b/src/test/ui/existential_types/generic_duplicate_param_use10.rs new file mode 100644 index 00000000000..10f2c630582 --- /dev/null +++ b/src/test/ui/existential_types/generic_duplicate_param_use10.rs @@ -0,0 +1,12 @@ +// compile-pass +#![feature(existential_type)] + +use std::fmt::Debug; + +fn main() {} + +existential type Two<T, U>: Debug; + +fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> { + (t, 4u32) +} diff --git a/src/test/ui/existential_types/generic_duplicate_param_use9.rs b/src/test/ui/existential_types/generic_duplicate_param_use9.rs new file mode 100644 index 00000000000..4c6897298c4 --- /dev/null +++ b/src/test/ui/existential_types/generic_duplicate_param_use9.rs @@ -0,0 +1,20 @@ +#![feature(existential_type)] + +use std::fmt::Debug; + +fn main() {} + +existential type Two<A, B>: Debug; + +trait Foo { + type Bar: Debug; + const BAR: Self::Bar; +} + +fn two<T: Debug + Foo, U: Debug>(t: T, u: U) -> Two<T, U> { + (t, u, T::BAR) +} + +fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> { + (t, u, 42) //~^ ERROR concrete type differs from previous +} diff --git a/src/test/ui/existential_types/generic_duplicate_param_use9.stderr b/src/test/ui/existential_types/generic_duplicate_param_use9.stderr new file mode 100644 index 00000000000..a3ce480d66d --- /dev/null +++ b/src/test/ui/existential_types/generic_duplicate_param_use9.stderr @@ -0,0 +1,18 @@ +error: concrete type differs from previous defining existential type use + --> $DIR/generic_duplicate_param_use9.rs:18:1 + | +LL | / fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> { +LL | | (t, u, 42) //~^ ERROR concrete type differs from previous +LL | | } + | |_^ expected `(A, B, <A as Foo>::Bar)`, got `(A, B, i32)` + | +note: previous use here + --> $DIR/generic_duplicate_param_use9.rs:14:1 + | +LL | / fn two<T: Debug + Foo, U: Debug>(t: T, u: U) -> Two<T, U> { +LL | | (t, u, T::BAR) +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/existential_types/generic_nondefining_use.rs b/src/test/ui/existential_types/generic_nondefining_use.rs index caa8f0f2ee1..75af5d9570f 100644 --- a/src/test/ui/existential_types/generic_nondefining_use.rs +++ b/src/test/ui/existential_types/generic_nondefining_use.rs @@ -3,8 +3,9 @@ fn main() {} existential type Cmp<T>: 'static; +//~^ ERROR could not find defining uses // not a defining use, because it doesn't define *all* possible generics -fn cmp() -> Cmp<u32> { //~ ERROR non-defining existential type use in defining scope +fn cmp() -> Cmp<u32> { //~ ERROR defining existential type use does not fully define 5u32 } diff --git a/src/test/ui/existential_types/generic_nondefining_use.stderr b/src/test/ui/existential_types/generic_nondefining_use.stderr index 41877791e9a..8dd88006be9 100644 --- a/src/test/ui/existential_types/generic_nondefining_use.stderr +++ b/src/test/ui/existential_types/generic_nondefining_use.stderr @@ -1,16 +1,16 @@ -error: non-defining existential type use in defining scope - --> $DIR/generic_nondefining_use.rs:8:1 +error: defining existential type use does not fully define existential type + --> $DIR/generic_nondefining_use.rs:9:1 | -LL | / fn cmp() -> Cmp<u32> { //~ ERROR non-defining existential type use in defining scope +LL | / fn cmp() -> Cmp<u32> { //~ ERROR defining existential type use does not fully define LL | | 5u32 LL | | } | |_^ - | -note: used non-generic type u32 for generic parameter - --> $DIR/generic_nondefining_use.rs:5:22 + +error: could not find defining uses + --> $DIR/generic_nondefining_use.rs:5:1 | LL | existential type Cmp<T>: 'static; - | ^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/src/test/ui/existential_types/not_a_defining_use.rs b/src/test/ui/existential_types/not_a_defining_use.rs index 413cc6788c2..3f81f5177d0 100644 --- a/src/test/ui/existential_types/not_a_defining_use.rs +++ b/src/test/ui/existential_types/not_a_defining_use.rs @@ -7,6 +7,7 @@ fn main() {} existential type Two<T, U>: Debug; fn two<T: Debug>(t: T) -> Two<T, u32> { + //~^ ERROR defining existential type use does not fully define existential type (t, 4i8) } diff --git a/src/test/ui/existential_types/not_a_defining_use.stderr b/src/test/ui/existential_types/not_a_defining_use.stderr index a6ed5dbe0a9..288a32fc14e 100644 --- a/src/test/ui/existential_types/not_a_defining_use.stderr +++ b/src/test/ui/existential_types/not_a_defining_use.stderr @@ -1,5 +1,14 @@ +error: defining existential type use does not fully define existential type + --> $DIR/not_a_defining_use.rs:9:1 + | +LL | / fn two<T: Debug>(t: T) -> Two<T, u32> { +LL | | //~^ ERROR defining existential type use does not fully define existential type +LL | | (t, 4i8) +LL | | } + | |_^ + error: concrete type differs from previous defining existential type use - --> $DIR/not_a_defining_use.rs:29:1 + --> $DIR/not_a_defining_use.rs:30:1 | LL | / fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> { //~ concrete type differs from previous LL | | (t, <U as Bar>::FOO) @@ -7,12 +16,12 @@ LL | | } | |_^ expected `(T, i8)`, got `(T, <U as Bar>::Blub)` | note: previous use here - --> $DIR/not_a_defining_use.rs:9:1 + --> $DIR/not_a_defining_use.rs:14:1 | -LL | / fn two<T: Debug>(t: T) -> Two<T, u32> { -LL | | (t, 4i8) +LL | / fn three<T: Debug, U>(t: T) -> Two<T, U> { +LL | | (t, 5i8) LL | | } | |_^ -error: aborting due to previous error +error: aborting due to 2 previous errors |
