diff options
| author | Oliver Scherer <github35764891676564198441@oli-obk.de> | 2019-01-25 22:57:31 +0100 |
|---|---|---|
| committer | Oliver Scherer <github35764891676564198441@oli-obk.de> | 2019-02-01 16:38:46 +0100 |
| commit | cf01b514c876656696e87672a1c118a3ce7817ed (patch) | |
| tree | 76de0b5d6d16e9add8564e6e546d5d41126096d4 | |
| parent | 0d25ff8842ca35b7eabd2d8a22669c5b2216ad82 (diff) | |
| download | rust-cf01b514c876656696e87672a1c118a3ce7817ed.tar.gz rust-cf01b514c876656696e87672a1c118a3ce7817ed.zip | |
Generic type parameters are flexible even for existential types
9 files changed, 32 insertions, 87 deletions
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index b0b266a61a5..e4fc1925eb3 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1346,7 +1346,16 @@ fn find_existential_constraints<'a, 'tcx>( // FIXME(oli-obk): trace the actual span from inference to improve errors let span = self.tcx.def_span(def_id); if let Some((prev_span, prev_ty)) = self.found { - if ty != prev_ty { + let mut ty = ty.walk().fuse(); + let mut prev_ty = prev_ty.walk().fuse(); + let iter_eq = (&mut ty).zip(&mut prev_ty).all(|(t, p)| match (&t.sty, &p.sty) { + // type parameters are equal to any other type parameter for the purpose of + // concrete type equality, as it is possible to obtain the same type just + // by passing matching parameters to a function. + (ty::Param(_), ty::Param(_)) => true, + _ => t == p, + }); + if !iter_eq || ty.next().is_some() || prev_ty.next().is_some() { // found different concrete types for the existential type let mut err = self.tcx.sess.struct_span_err( span, diff --git a/src/test/ui/existential_types/generic_duplicate_param_use.rs b/src/test/ui/existential_types/generic_duplicate_param_use.rs index 14d63ecc6bb..d08cd88c600 100644 --- a/src/test/ui/existential_types/generic_duplicate_param_use.rs +++ b/src/test/ui/existential_types/generic_duplicate_param_use.rs @@ -1,11 +1,13 @@ // compile-pass #![feature(existential_type)] +use std::fmt::Debug; + fn main() {} // test that unused generic parameters are ok -existential type Two<T, U>: 'static; +existential type Two<T, U>: Debug; -fn one<T: 'static>(t: T) -> Two<T, T> { +fn one<T: Debug>(t: T) -> Two<T, T> { t } diff --git a/src/test/ui/existential_types/generic_duplicate_param_use2.rs b/src/test/ui/existential_types/generic_duplicate_param_use2.rs index b6cb22da41d..c27fbb74cf1 100644 --- a/src/test/ui/existential_types/generic_duplicate_param_use2.rs +++ b/src/test/ui/existential_types/generic_duplicate_param_use2.rs @@ -1,15 +1,17 @@ // compile-pass #![feature(existential_type)] +use std::fmt::Debug; + fn main() {} // test that unused generic parameters are ok -existential type Two<T, U>: 'static; +existential type Two<T, U>: Debug; -fn one<T: 'static>(t: T) -> Two<T, T> { +fn one<T: Debug>(t: T) -> Two<T, T> { t } -fn two<T: 'static, U: 'static>(t: T, _: U) -> Two<T, U> { +fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> { t } diff --git a/src/test/ui/existential_types/generic_duplicate_param_use3.rs b/src/test/ui/existential_types/generic_duplicate_param_use3.rs index 43650a6a352..b4d1b26dbab 100644 --- a/src/test/ui/existential_types/generic_duplicate_param_use3.rs +++ b/src/test/ui/existential_types/generic_duplicate_param_use3.rs @@ -1,19 +1,21 @@ +// compile-pass #![feature(existential_type)] +use std::fmt::Debug; + fn main() {} // test that unused generic parameters are ok -existential type Two<T, U>: 'static; +existential type Two<T, U>: Debug; -fn one<T: 'static>(t: T) -> Two<T, T> { +fn one<T: Debug>(t: T) -> Two<T, T> { t } -fn two<T: 'static, U: 'static>(t: T, _: U) -> Two<T, U> { +fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> { t } -fn three<T: 'static, U: 'static>(_: T, u: U) -> Two<T, U> { - //~^ ERROR defining existential type use differs from previous +fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> { u } diff --git a/src/test/ui/existential_types/generic_duplicate_param_use3.stderr b/src/test/ui/existential_types/generic_duplicate_param_use3.stderr deleted file mode 100644 index 67c30ad648b..00000000000 --- a/src/test/ui/existential_types/generic_duplicate_param_use3.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error: defining existential type use differs from previous - --> $DIR/generic_duplicate_param_use3.rs:16:1 - | -LL | / fn three<T: 'static, U: 'static>(_: T, u: U) -> Two<T, U> { -LL | | //~^ ERROR defining existential type use differs from previous -LL | | u -LL | | } - | |_^ - | -note: previous use here - --> $DIR/generic_duplicate_param_use3.rs:8:1 - | -LL | / fn one<T: 'static>(t: T) -> Two<T, T> { -LL | | t -LL | | } - | |_^ - -error: aborting due to previous error - diff --git a/src/test/ui/existential_types/generic_duplicate_param_use4.rs b/src/test/ui/existential_types/generic_duplicate_param_use4.rs index 79df528d209..afab86c3ff0 100644 --- a/src/test/ui/existential_types/generic_duplicate_param_use4.rs +++ b/src/test/ui/existential_types/generic_duplicate_param_use4.rs @@ -1,15 +1,17 @@ +// compile-pass #![feature(existential_type)] +use std::fmt::Debug; + fn main() {} // test that unused generic parameters are ok -existential type Two<T, U>: 'static; +existential type Two<T, U>: Debug; -fn one<T: 'static>(t: T) -> Two<T, T> { +fn one<T: Debug>(t: T) -> Two<T, T> { t } -fn three<T: 'static, U: 'static>(_: T, u: U) -> Two<T, U> { -//~^ ERROR defining existential type use differs from previous +fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> { u } diff --git a/src/test/ui/existential_types/generic_duplicate_param_use4.stderr b/src/test/ui/existential_types/generic_duplicate_param_use4.stderr deleted file mode 100644 index e7a372e0e0c..00000000000 --- a/src/test/ui/existential_types/generic_duplicate_param_use4.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error: defining existential type use differs from previous - --> $DIR/generic_duplicate_param_use4.rs:12:1 - | -LL | / fn three<T: 'static, U: 'static>(_: T, u: U) -> Two<T, U> { -LL | | //~^ ERROR defining existential type use differs from previous -LL | | u -LL | | } - | |_^ - | -note: previous use here - --> $DIR/generic_duplicate_param_use4.rs:8:1 - | -LL | / fn one<T: 'static>(t: T) -> Two<T, T> { -LL | | t -LL | | } - | |_^ - -error: aborting due to previous error - diff --git a/src/test/ui/existential_types/generic_duplicate_param_use5.rs b/src/test/ui/existential_types/generic_duplicate_param_use5.rs deleted file mode 100644 index f9d336d759b..00000000000 --- a/src/test/ui/existential_types/generic_duplicate_param_use5.rs +++ /dev/null @@ -1,15 +0,0 @@ -#![feature(existential_type)] - -fn main() {} - -// test that unused generic parameters are ok -existential type Two<T, U>: 'static; - -fn one<T: 'static>(t: T) -> Two<T, T> { - t -} - -fn two<T: 'static, U: 'static>(t: T, _: U) -> Two<U, T> { -//~^ ERROR defining existential type use differs from previous - t -} diff --git a/src/test/ui/existential_types/generic_duplicate_param_use5.stderr b/src/test/ui/existential_types/generic_duplicate_param_use5.stderr deleted file mode 100644 index e2bf4a9e0df..00000000000 --- a/src/test/ui/existential_types/generic_duplicate_param_use5.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error: defining existential type use differs from previous - --> $DIR/generic_duplicate_param_use5.rs:12:1 - | -LL | / fn two<T: 'static, U: 'static>(t: T, _: U) -> Two<U, T> { -LL | | //~^ ERROR defining existential type use differs from previous -LL | | t -LL | | } - | |_^ - | -note: previous use here - --> $DIR/generic_duplicate_param_use5.rs:8:1 - | -LL | / fn one<T: 'static>(t: T) -> Two<T, T> { -LL | | t -LL | | } - | |_^ - -error: aborting due to previous error - |
