Skip to content

Commit

Permalink
Require defining uses to use generic parameters for all parameters of…
Browse files Browse the repository at this point in the history
… a generic existential type
  • Loading branch information
oli-obk committed Feb 14, 2019
1 parent c93bce8 commit eb98d31
Show file tree
Hide file tree
Showing 10 changed files with 98 additions and 27 deletions.
17 changes: 13 additions & 4 deletions src/librustc_typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
3 changes: 2 additions & 1 deletion src/test/ui/existential_types/bound_reduction2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
()
}
16 changes: 8 additions & 8 deletions src/test/ui/existential_types/bound_reduction2.stderr
Original file line number Diff line number Diff line change
@@ -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

12 changes: 12 additions & 0 deletions src/test/ui/existential_types/generic_duplicate_param_use10.rs
Original file line number Diff line number Diff line change
@@ -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)
}
20 changes: 20 additions & 0 deletions src/test/ui/existential_types/generic_duplicate_param_use9.rs
Original file line number Diff line number Diff line change
@@ -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
}
18 changes: 18 additions & 0 deletions src/test/ui/existential_types/generic_duplicate_param_use9.stderr
Original file line number Diff line number Diff line change
@@ -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 changes: 2 additions & 1 deletion src/test/ui/existential_types/generic_nondefining_use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
16 changes: 8 additions & 8 deletions src/test/ui/existential_types/generic_nondefining_use.stderr
Original file line number Diff line number Diff line change
@@ -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

1 change: 1 addition & 0 deletions src/test/ui/existential_types/not_a_defining_use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down
19 changes: 14 additions & 5 deletions src/test/ui/existential_types/not_a_defining_use.stderr
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
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)
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

0 comments on commit eb98d31

Please sign in to comment.