about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Scherer <github35764891676564198441@oli-obk.de>2019-02-14 13:02:36 +0100
committerOliver Scherer <github35764891676564198441@oli-obk.de>2019-02-14 13:02:36 +0100
commiteb98d318b28cc177f608d57fb5b9b017235b515d (patch)
treecf1a1fc49128b7205f29ce4f18a773782d93d7cf
parentc93bce85e5e085274febf1ca71b551de3f51429c (diff)
downloadrust-eb98d318b28cc177f608d57fb5b9b017235b515d.tar.gz
rust-eb98d318b28cc177f608d57fb5b9b017235b515d.zip
Require defining uses to use generic parameters for all parameters of a generic existential type
-rw-r--r--src/librustc_typeck/collect.rs17
-rw-r--r--src/test/ui/existential_types/bound_reduction2.rs3
-rw-r--r--src/test/ui/existential_types/bound_reduction2.stderr16
-rw-r--r--src/test/ui/existential_types/generic_duplicate_param_use10.rs12
-rw-r--r--src/test/ui/existential_types/generic_duplicate_param_use9.rs20
-rw-r--r--src/test/ui/existential_types/generic_duplicate_param_use9.stderr18
-rw-r--r--src/test/ui/existential_types/generic_nondefining_use.rs3
-rw-r--r--src/test/ui/existential_types/generic_nondefining_use.stderr16
-rw-r--r--src/test/ui/existential_types/not_a_defining_use.rs1
-rw-r--r--src/test/ui/existential_types/not_a_defining_use.stderr19
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