From cf01b514c876656696e87672a1c118a3ce7817ed Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 25 Jan 2019 22:57:31 +0100 Subject: [PATCH] Generic type parameters are flexible even for existential types --- src/librustc_typeck/collect.rs | 11 ++++++++++- .../generic_duplicate_param_use.rs | 6 ++++-- .../generic_duplicate_param_use2.rs | 8 +++++--- .../generic_duplicate_param_use3.rs | 12 +++++++----- .../generic_duplicate_param_use3.stderr | 19 ------------------- .../generic_duplicate_param_use4.rs | 10 ++++++---- .../generic_duplicate_param_use4.stderr | 19 ------------------- .../generic_duplicate_param_use5.rs | 15 --------------- .../generic_duplicate_param_use5.stderr | 19 ------------------- 9 files changed, 32 insertions(+), 87 deletions(-) delete mode 100644 src/test/ui/existential_types/generic_duplicate_param_use3.stderr delete mode 100644 src/test/ui/existential_types/generic_duplicate_param_use4.stderr delete mode 100644 src/test/ui/existential_types/generic_duplicate_param_use5.rs delete mode 100644 src/test/ui/existential_types/generic_duplicate_param_use5.stderr diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index b0b266a61a5b..e4fc1925eb37 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 14d63ecc6bb5..d08cd88c600d 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: 'static; +existential type Two: Debug; -fn one(t: T) -> Two { +fn one(t: T) -> Two { 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 b6cb22da41d7..c27fbb74cf19 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: 'static; +existential type Two: Debug; -fn one(t: T) -> Two { +fn one(t: T) -> Two { t } -fn two(t: T, _: U) -> Two { +fn two(t: T, _: U) -> Two { 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 43650a6a3529..b4d1b26dbabd 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: 'static; +existential type Two: Debug; -fn one(t: T) -> Two { +fn one(t: T) -> Two { t } -fn two(t: T, _: U) -> Two { +fn two(t: T, _: U) -> Two { t } -fn three(_: T, u: U) -> Two { - //~^ ERROR defining existential type use differs from previous +fn three(_: T, u: U) -> Two { 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 67c30ad648b3..000000000000 --- 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, u: U) -> Two { -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: T) -> Two { -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 79df528d209c..afab86c3ff07 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: 'static; +existential type Two: Debug; -fn one(t: T) -> Two { +fn one(t: T) -> Two { t } -fn three(_: T, u: U) -> Two { -//~^ ERROR defining existential type use differs from previous +fn three(_: T, u: U) -> Two { 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 e7a372e0e0c9..000000000000 --- 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, u: U) -> Two { -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: T) -> Two { -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 f9d336d759b6..000000000000 --- 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: 'static; - -fn one(t: T) -> Two { - t -} - -fn two(t: T, _: U) -> Two { -//~^ 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 e2bf4a9e0dfe..000000000000 --- 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: T, _: U) -> Two { -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: T) -> Two { -LL | | t -LL | | } - | |_^ - -error: aborting due to previous error -