Skip to content
Permalink
Browse files

Require defining uses to use generic parameters for all parameters of…

… a generic existential type
  • Loading branch information...
oli-obk committed Feb 14, 2019
1 parent c93bce8 commit eb98d318b28cc177f608d57fb5b9b017235b515d
@@ -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,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.
You can’t perform that action at this time.