Generic type parameters are flexible even for existential types
This commit is contained in:
parent
0d25ff8842
commit
cf01b514c8
9 changed files with 32 additions and 87 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue