Require defining uses to use generic parameters for all parameters of a generic existential type
This commit is contained in:
parent
c93bce85e5
commit
eb98d318b2
10 changed files with 98 additions and 27 deletions
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue