Generic type parameters are flexible even for existential types

This commit is contained in:
Oliver Scherer 2019-01-25 22:57:31 +01:00
parent 0d25ff8842
commit cf01b514c8
9 changed files with 32 additions and 87 deletions

View file

@ -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,

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -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
}

View file

@ -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