Skip to content

Instantly share code, notes, and snippets.

@Centril
Last active March 6, 2019 18:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Centril/2470b7f89657da457ed25078a9cdab72 to your computer and use it in GitHub Desktop.
Save Centril/2470b7f89657da457ed25078a9cdab72 to your computer and use it in GitHub Desktop.
Tests for RFC 2289, Associated type bounds
// run-pass
use core::fmt::Debug;
use core::iter::{Empty, Once};
use core::ops::Range;
trait Lam<Binder> { type App; }
#[derive(Clone)]
struct L1;
impl<'a> Lam<&'a u8> for L1 { type App = u8; }
#[derive(Clone)]
struct L2;
impl<'a, 'b> Lam<&'a &'b u8> for L2 { type App = u8; }
trait Case1 {
type A: Iterator<Item: Debug>;
type B: Iterator<Item: 'static>;
type C: Clone + Iterator<Item:
Send + Iterator<Item:
for<'a> Lam<&'a u8, App:
Debug
>
> + Sync>;
// Let's be really annoying and introduce a `for<'a>` binder in an outer
// ATB which is then used in an inner ATB:
type D: Clone + Iterator<Item: // <- Outer ATB
Send + for<'a> Iterator<Item: // <- Inner ATB
for<'b> Lam<&'a &'b u8, App:
Debug
>
> + Sync>;
}
pub struct S1;
impl Case1 for S1 {
type A = Empty<String>;
type B = Range<u16>;
type C = Once<Once<L1>>;
type D = Once<Once<L2>>;
}
fn _assume_case1<T: Case1>() {
fn assert_a<_0, A>() where A: Iterator<Item = _0>, _0: Debug {}
assert_a::<_, T::A>();
fn assert_b<_0, B>() where B: Iterator<Item = _0>, _0: 'static {}
assert_b::<_, T::B>();
fn assert_c<_0, _1, _2, C>()
where
C: Clone + Iterator<Item = _2>,
_2: Send + Iterator<Item = _1>,
_1: for<'a> Lam<&'a u8, App = _0>,
_0: Debug,
{}
assert_c::<_, _, _, T::C>();
fn assert_d<_0, _1, _2, D>()
where
D: Clone + Iterator<Item = _2>,
_2: Send + for<'a> Iterator,
for<'a> <_2 as Iterator>::Item: for<'b> Lam<&'a &'b u8, App = _0>,
_0: Debug,
{}
assert_d::<_, _, _, T::D>();
}
// compile-fail
struct SI1<T: Iterator<Item: Copy, Item: Send>> { f: T }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
struct SI2<T: Iterator<Item: Copy, Item: Copy>> { f: T }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
struct SI3<T: Iterator<Item: 'static, Item: 'static>> { f: T }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
struct SW1<T> where T: Iterator<Item: Copy, Item: Send> { f: T }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
struct SW2<T> where T: Iterator<Item: Copy, Item: Copy> { f: T }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
struct SW3<T> where T: Iterator<Item: 'static, Item: 'static> { f: T }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
enum EI1<T: Iterator<Item: Copy, Item: Send>> { V(T) }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
enum EI2<T: Iterator<Item: Copy, Item: Copy>> { V(T) }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
enum EI3<T: Iterator<Item: 'static, Item: 'static>> { V(T) }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
enum EW1<T> where T: Iterator<Item: Copy, Item: Send> { V(T) }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
enum EW2<T> where T: Iterator<Item: Copy, Item: Copy> { V(T) }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
enum EW3<T> where T: Iterator<Item: 'static, Item: 'static> { V(T) }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
union UI1<T: Iterator<Item: Copy, Item: Send>> { f: T }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
union UI2<T: Iterator<Item: Copy, Item: Copy>> { f: T }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
union UI3<T: Iterator<Item: 'static, Item: 'static>> { f: T }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
union UW1<T> where T: Iterator<Item: Copy, Item: Send> { f: T }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
union UW2<T> where T: Iterator<Item: Copy, Item: Copy> { f: T }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
union UW3<T> where T: Iterator<Item: 'static, Item: 'static> { f: T }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
fn FI1<T: Iterator<Item: Copy, Item: Send>>() {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
fn FI2<T: Iterator<Item: Copy, Item: Copy>>() {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
fn FI3<T: Iterator<Item: 'static, Item: 'static>>() {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
fn FW1<T>() where T: Iterator<Item: Copy, Item: Send> {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
fn FW2<T>() where T: Iterator<Item: Copy, Item: Copy> {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
fn FW3<T>() where T: Iterator<Item: 'static, Item: 'static> {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
fn FRPIT1() -> impl Iterator<Item: Copy, Item: Send> {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
fn FRPIT2() -> impl Iterator<Item: Copy, Item: Copy> {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
fn FRPIT3() -> impl Iterator<Item: 'static, Item: 'static> {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
fn FAPIT1(_: impl Iterator<Item: Copy, Item: Send>) {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
fn FAPIT2(_: impl Iterator<Item: Copy, Item: Copy>) {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
fn FAPIT3(_: impl Iterator<Item: 'static, Item: 'static>) {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
const CIT1: impl Iterator<Item: Copy, Item: Send> = ();
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
const CIT2: impl Iterator<Item: Copy, Item: Copy> = ();
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
const CIT3: impl Iterator<Item: 'static, Item: 'static> = ();
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
static SIT1: impl Iterator<Item: Copy, Item: Send> = ();
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
static SIT2: impl Iterator<Item: Copy, Item: Copy> = ();
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
static SIT3: impl Iterator<Item: 'static, Item: 'static> = ();
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
fn lit1() { let _: impl Iterator<Item: Copy, Item: Send> = (); }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
fn lit2() { let _: impl Iterator<Item: Copy, Item: Copy> = (); }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
fn lit3() { let _: impl Iterator<Item: 'static, Item: 'static> = (); }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
type TAI1<T: Iterator<Item: Copy, Item: Send>> = T;
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
type TAI2<T: Iterator<Item: Copy, Item: Copy>> = T;
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
type TAI3<T: Iterator<Item: 'static, Item: 'static>> = T;
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
type TAW1<T> where T: Iterator<Item: Copy, Item: Send> = T;
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
type TAW2<T> where T: Iterator<Item: Copy, Item: Copy> = T;
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
type TAW3<T> where T: Iterator<Item: 'static, Item: 'static> = T;
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
existential type ETAI1<T: Iterator<Item: Copy, Item: Send>>: Copy;
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
existential type ETAI2<T: Iterator<Item: Copy, Item: Copy>>: Copy;
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
existential type ETAI3<T: Iterator<Item: 'static, Item: 'static>>: Copy;
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
existential type ETAI1: Iterator<Item: Copy, Item: Send>;
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
existential type ETAI2: Iterator<Item: Copy, Item: Copy>;
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
existential type ETAI3: Iterator<Item: 'static, Item: 'static>;
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
trait TRI1<T: Iterator<Item: Copy, Item: Send>> {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
trait TRS1: Iterator<Item: Copy, Item: Send> {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
trait TRS2: Iterator<Item: Copy, Item: Copy> {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
trait TRS3: Iterator<Item: 'static, Item: 'static> {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
trait TRW1<T> where T: Iterator<Item: Copy, Item: Send> {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
trait TRW2<T> where T: Iterator<Item: Copy, Item: Copy> {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
trait TRW3<T> where T: Iterator<Item: 'static, Item: 'static> {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
trait TRA3 { type A: Iterator<Item: 'static, Item: 'static>; }
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
struct SDyn1 { f: dyn Iterator<Item: Copy, Item: Send> };
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
struct SDyn2 { f: Box<dyn Iterator<Item: Copy, Item: Copy>> };
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
struct SDyn3 { f: dyn Iterator<Item: 'static, Item: 'static> };
// ~^ error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
// run-pass
#![feature(existential_type)]
trait Tr1 { type As1; fn mk(&self) -> Self::As1; }
trait Tr2<'a> { fn tr2(self) -> &'a Self; }
fn assert_copy<T: Copy>(x: T) { let _x = x; let _x = x; }
fn assert_static<T: 'static>(_: T) {}
fn assert_forall_tr2<T: for<'a> Tr2<'a>>(_: T) {}
struct S1;
#[derive(Copy, Clone)]
struct S2;
impl Tr1 for S1 { type As1 = S2; fn mk(&self) -> Self::As1 { S2 } }
type Et1 = Box<dyn Tr1<As1: Copy>>;
fn def_et1() -> Et1 { Box::new(S1) }
pub fn use_et1() { assert_copy(def_et1().mk()); }
type Et2 = Box<dyn Tr1<As1: 'static>>;
fn def_et2() -> Et2 { Box::new(S1) }
pub fn use_et2() { assert_static(def_et2().mk()); }
use core::ops::Add;
type Et3 = Box<dyn Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>>>;
fn def_et3() -> Et3 {
struct A;
impl Tr1 for A {
type As1 = core::ops::Range<u8>;
fn mk(&self) -> Self::As1 { 0..10 }
};
Box::new(A)
}
pub fn use_et3() {
let _0 = def_et3().mk().clone();
let mut s = 0u8;
for _1 in _0 {
let _2 = _1 + 1u8;
s += _2.into();
}
assert_eq!(s, (0..10).map(|x| x + 1).sum());
}
type Et4 = Box<dyn Tr1<As1: for<'a> Tr2<'a>>>;
fn def_et4() -> Et4 {
#[derive(Copy, Clone)]
struct A;
impl Tr1 for A {
type As1 = A;
fn mk(&self) -> A { A }
}
impl<'a> Tr2<'a> for A {
fn tr2(self) -> &'a Self { &A }
}
Box::new(A)
}
pub fn use_et4() { assert_forall_tr2(def_et4().mk()); }
fn main() {
let _ = use_et1();
let _ = use_et2();
let _ = use_et3();
let _ = use_et4();
}
// run-pass
#![feature(impl_trait_in_bindings)]
#![allow(non_upper_case_globals)]
trait Tr1 { type As1; fn mk(&self) -> Self::As1; }
trait Tr2<'a> { fn tr2(self) -> &'a Self; }
fn assert_copy<T: Copy>(x: T) { let _x = x; let _x = x; }
fn assert_static<T: 'static>(_: T) {}
fn assert_forall_tr2<T: for<'a> Tr2<'a>>(_: T) {}
#[derive(Copy, Clone)]
struct S1;
#[derive(Copy, Clone)]
struct S2;
impl Tr1 for S1 { type As1 = S2; fn mk(&self) -> Self::As1 { S2 } }
const cdef_et1: &dyn Tr1<As1: Copy> = &S1;
const sdef_et1: &dyn Tr1<As1: Copy> = &S1;
pub fn use_et1() { assert_copy(cdef_et1.mk()); assert_copy(sdef_et1.mk()); }
const cdef_et2: &(dyn Tr1<As1: 'static> + Sync) = &S1;
static sdef_et2: &(dyn Tr1<As1: 'static> + Sync) = &S1;
pub fn use_et2() { assert_static(cdef_et2.mk()); assert_static(sdef_et2.mk()); }
use core::ops::Add;
const cdef_et3: &dyn Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>> = {
struct A;
impl Tr1 for A {
type As1 = core::ops::Range<u8>;
fn mk(&self) -> Self::As1 { 0..10 }
};
&A
};
pub fn use_et3() {
let _0 = cdef_et3.mk().clone();
let mut s = 0u8;
for _1 in _0 {
let _2 = _1 + 1u8;
s += _2.into();
}
assert_eq!(s, (0..10).map(|x| x + 1).sum());
}
const cdef_et4: &(dyn Tr1<As1: for<'a> Tr2<'a>> + Sync) = {
#[derive(Copy, Clone)]
struct A;
impl Tr1 for A {
type As1 = A;
fn mk(&self) -> A { A }
}
impl<'a> Tr2<'a> for A {
fn tr2(self) -> &'a Self { &A }
}
&A
};
static sdef_et4: &(dyn Tr1<As1: for<'a> Tr2<'a>> + Sync) = cdef_et4;
pub fn use_et4() { assert_forall_tr2(cdef_et4.mk()); assert_forall_tr2(sdef_et4.mk()); }
fn main() {
let _ = use_et1();
let _ = use_et2();
let _ = use_et3();
let _ = use_et4();
}
// run-pass
trait Tr1 { type As1; fn mk(&self) -> Self::As1; }
trait Tr2<'a> { fn tr2(self) -> &'a Self; }
fn assert_copy<T: Copy>(x: T) { let _x = x; let _x = x; }
fn assert_static<T: 'static>(_: T) {}
fn assert_forall_tr2<T: for<'a> Tr2<'a>>(_: T) {}
struct S1;
#[derive(Copy, Clone)]
struct S2;
impl Tr1 for S1 { type As1 = S2; fn mk(&self) -> Self::As1 { S2 } }
fn def_et1() -> Box<dyn Tr1<As1: Copy>> {
let x: Box<dyn Tr1<As1: Copy>> = Box::new(S1);
x
}
pub fn use_et1() { assert_copy(def_et1().mk()); }
fn def_et2() -> Box<dyn Tr1<As1: Send + 'static>> {
let x: Box<dyn Tr1<As1: Send + 'static>> = Box::new(S1);
x
}
pub fn use_et2() { assert_static(def_et2().mk()); }
use core::ops::Add;
fn def_et3() -> Box<dyn Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>>> {
struct A;
impl Tr1 for A {
type As1 = core::ops::Range<u8>;
fn mk(&self) -> Self::As1 { 0..10 }
};
let x: Box<dyn Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>>> = Box::new(A);
x
}
pub fn use_et3() {
let _0 = def_et3().mk().clone();
let mut s = 0u8;
for _1 in _0 {
let _2 = _1 + 1u8;
s += _2.into();
}
assert_eq!(s, (0..10).map(|x| x + 1).sum());
}
fn def_et4() -> Box<dyn Tr1<As1: for<'a> Tr2<'a>>> {
#[derive(Copy, Clone)]
struct A;
impl Tr1 for A {
type As1 = A;
fn mk(&self) -> A { A }
}
impl<'a> Tr2<'a> for A {
fn tr2(self) -> &'a Self { &A }
}
let x: Box<dyn Tr1<As1: for<'a> Tr2<'a>>> = Box::new(A);
x
}
pub fn use_et4() { assert_forall_tr2(def_et4().mk()); }
fn main() {
let _ = use_et1();
let _ = use_et2();
let _ = use_et3();
let _ = use_et4();
}
// compile-pass
trait Tr1: Sized { type As1; }
trait Tr2<'a>: Sized { type As1; }
trait ObjTr1 { fn foo() -> Self where Self: Tr1<As1: Copy>; }
fn _assert_obj_safe_1(_: Box<dyn ObjTr1>) {}
trait ObjTr2 { fn foo() -> Self where Self: Tr1<As1: 'static>; }
fn _assert_obj_safe_2(_: Box<dyn ObjTr2>) {}
trait ObjTr3 { fn foo() -> Self where Self: Tr1<As1: Into<u8> + 'static + Copy>; }
fn _assert_obj_safe_3(_: Box<dyn ObjTr3>) {}
trait ObjTr4 { fn foo() -> Self where Self: Tr1<As1: for<'a> Tr2<'a>>; }
fn _assert_obj_safe_4(_: Box<dyn ObjTr4>) {}
trait ObjTr5 { fn foo() -> Self where for<'a> Self: Tr1<As1: Tr2<'a>>; }
fn _assert_obj_safe_5(_: Box<dyn ObjTr5>) {}
trait ObjTr6 { fn foo() -> Self where Self: for<'a> Tr1<As1: Tr2<'a, As2: for<'b> Tr2<'b>>>; }
fn _assert_obj_safe_6(_: Box<dyn ObjTr6>) {}
// run-pass
trait Tr1 { type As1; }
trait Tr2 { type As2; }
trait Tr3 { type As3; }
trait Tr4<'a> { type As4; }
trait Tr5 { type As5; }
impl Tr1 for &str { type As1 = bool; }
impl Tr2 for bool { type As2 = u8; }
impl Tr3 for u8 { type As3 = fn() -> u8; }
impl Tr1 for () { type As1 = (usize,); }
impl<'a> Tr4<'a> for (usize,) { type As4 = u8; }
impl Tr5 for bool { type As5 = u16; }
enum En1<T: Tr1<As1: Tr2>> {
Outest(T),
Outer(T::As1),
Inner(<T::As1 as Tr2>::As2),
}
fn wrap_en1_1<T>(x: T) -> En1<T> where T: Tr1, T::As1: Tr2 {
En1::Outest(x)
}
fn wrap_en1_2<T>(x: T::As1) -> En1<T> where T: Tr1, T::As1: Tr2 {
En1::Outer(x)
}
fn wrap_en1_3<T>(x: <T::As1 as Tr2>::As2) -> En1<T> where T: Tr1, T::As1: Tr2 {
En1::Inner(x)
}
enum En2<T: Tr1<As1: Tr2<As2: Tr3>>> {
V0(T),
V1(T::As1),
V2(<T::As1 as Tr2>::As2),
V3(<<T::As1 as Tr2>::As2 as Tr3>::As3),
}
enum En3<T: Tr1<As1: 'static>> {
V0(T),
V1(&'static T::As1),
}
enum En4<'x1, 'x2, T: Tr1<As1: for<'l> Tr4<'l>>> {
V0(&'x1 <T::As1 as Tr4<'x1>>::As4),
V1(&'x2 <T::As1 as Tr4<'x2>>::As4),
}
enum _En5<'x1, 'x2, T: Tr1<As1: for<'l> Tr4<'l, As4: Copy>>> {
_V0(&'x1 <T::As1 as Tr4<'x1>>::As4),
_V1(&'x2 <T::As1 as Tr4<'x2>>::As4),
}
enum En6<T>
where
T: Tr1<As1: Tr2 + 'static + Tr5>,
{
V0(T),
V1(<T::As1 as Tr2>::As2),
V2(&'static T::As1),
V3(<T::As1 as Tr5>::As5),
}
enum _En7<'a, 'b, T> // `<T::As1 as Tr2>::As2: 'a` is implied.
where
T: Tr1<As1: Tr2>,
{
V0(&'a T),
V1(&'b <T::As1 as Tr2>::As2),
}
fn _make_en7<'a, 'b, T>(x: _En7<'a, 'b, T>)
where
T: Tr1<As1: Tr2>,
{
match x {
_En7::V0(x) => {
let _: &'a T = &x;
},
_En7::V1(_) => {},
}
}
enum EnSelf<T> where Self: Tr1<As1: Tr2> {
V0(T),
V1(<Self as Tr1>::As1),
V2(<<Self as Tr1>::As1 as Tr2>::As2),
}
impl Tr1 for EnSelf<&'static str> { type As1 = bool; }
fn main() {
if let En1::Outest("foo") = wrap_en1_1::<_>("foo") {} else { panic!() };
if let En1::Outer(true) = wrap_en1_2::<&str>(true) {} else { panic!() };
if let En1::Inner(24u8) = wrap_en1_3::<&str>(24u8) {} else { panic!() };
let _ = En2::<_>::V0("151571");
let _ = En2::<&str>::V1(false);
let _ = En2::<&str>::V2(42u8);
let _ = En2::<&str>::V3(|| 12u8);
let _ = En3::<_>::V0("deadbeef");
let _ = En3::<&str>::V1(&true);
let f1 = (1,);
let f2 = (2,);
let _ = En4::<()>::V0(&f1.0);
let _ = En4::<()>::V1(&f2.0);
let _ = En6::<_>::V0("bar");
let _ = En6::<&str>::V1(24u8);
let _ = En6::<&str>::V2(&false);
let _ = En6::<&str>::V3(12u16);
let _ = EnSelf::<_>::V0("foo");
let _ = EnSelf::<&'static str>::V1(true);
let _ = EnSelf::<&'static str>::V2(24u8);
}
// run-pass
#![feature(existential_type)]
trait Tr1 { type As1; fn mk(self) -> Self::As1; }
trait Tr2<'a> { fn tr2(self) -> &'a Self; }
fn assert_copy<T: Copy>(x: T) { let _x = x; let _x = x; }
fn assert_static<T: 'static>(_: T) {}
fn assert_forall_tr2<T: for<'a> Tr2<'a>>(_: T) {}
struct S1;
#[derive(Copy, Clone)]
struct S2;
impl Tr1 for S1 { type As1 = S2; fn mk(self) -> Self::As1 { S2 } }
existential type Et1: Tr1<As1: Copy>;
fn def_et1() -> Et1 { S1 }
pub fn use_et1() { assert_copy(def_et1().mk()); }
existential type Et2: Tr1<As1: 'static>;
fn def_et2() -> Et2 { S1 }
pub fn use_et2() { assert_static(def_et2().mk()); }
use core::ops::Add;
existential type Et3: Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>>;
fn def_et3() -> Et3 {
struct A;
impl Tr1 for A {
type As1 = core::ops::Range<u8>;
fn mk(self) -> Self::As1 { 0..10 }
};
A
}
pub fn use_et3() {
let _0 = def_et3().mk().clone();
let mut s = 0u8;
for _1 in _0 {
let _2 = _1 + 1u8;
s += _2.into();
}
assert_eq!(s, (0..10).map(|x| x + 1).sum());
}
existential type Et4: Tr1<As1: for<'a> Tr2<'a>>;
fn def_et4() -> Et4 {
#[derive(Copy, Clone)]
struct A;
impl Tr1 for A {
type As1 = A;
fn mk(self) -> A { A }
}
impl<'a> Tr2<'a> for A {
fn tr2(self) -> &'a Self { &A }
}
A
}
pub fn use_et4() { assert_forall_tr2(def_et4().mk()); }
fn main() {
let _ = use_et1();
let _ = use_et2();
let _ = use_et3();
let _ = use_et4();
}
// run-pass
use fn_aux::*;
// ATB, APIT:
fn apit_bound(beta: impl Beta<Gamma: Alpha>) -> usize {
desugared_bound(beta)
}
fn apit_bound_region(beta: impl Beta<Gamma: 'static>) -> usize {
desugared_bound_region(beta)
}
fn apit_bound_multi(
beta: impl Copy + Beta<Gamma: Alpha + 'static + Delta>
) -> usize {
desugared_bound_multi(beta)
}
fn apit_bound_region_forall(
beta: impl Beta<Gamma: Copy + for<'a> Epsilon<'a>>
) -> usize {
desugared_bound_region_forall(beta)
}
fn apit_bound_region_forall2(
beta: impl Beta<Gamma: Copy + for<'a> Epsilon<'a, Zeta: Eta>>
) -> usize {
desugared_bound_region_forall2(beta)
}
fn apit_bound_nested(
beta: impl Beta<Gamma: Copy + Alpha + Beta<Gamma: Delta>>
) -> usize {
desugared_bound_nested(beta)
}
fn apit_bound_nested2(
beta: impl Beta<Gamma = impl Copy + Alpha + Beta<Gamma: Delta>>
) -> usize {
desugared_bound_nested(beta)
}
fn main() {
let beta = BetaType;
let gamma = beta.gamma();
assert_eq!(42, apit_bound(beta));
assert_eq!(24, apit_bound_region(beta));
assert_eq!(42 + 24 + 1337, apit_bound_multi(beta));
assert_eq!(7331 * 2, apit_bound_region_forall(beta));
assert_eq!(42 + 1337, apit_bound_nested(beta));
assert_eq!(42 + 1337, apit_bound_nested2(beta));
}
// run-pass
// Traits:
pub trait Alpha {
fn alpha(self) -> usize;
}
pub trait Beta {
type Gamma;
fn gamma(self) -> Self::Gamma;
}
pub trait Delta {
fn delta(self) -> usize;
}
pub trait Epsilon<'a> {
type Zeta;
fn zeta(&'a self) -> Self::Zeta;
fn epsilon(&'a self) -> usize;
}
pub trait Eta {
fn eta(self) -> usize;
}
// Assertions:
pub fn assert_alpha<T: Alpha>(x: T) -> usize { x.alpha() }
pub fn assert_static<T: 'static>(_: T) -> usize { 24 }
pub fn assert_delta<T: Delta>(x: T) -> usize { x.delta() }
pub fn assert_epsilon_specific<'a, T: 'a + Epsilon<'a>>(x: &'a T) -> usize { x.epsilon() }
pub fn assert_epsilon_forall<T: for<'a> Epsilon<'a>>() {}
pub fn assert_forall_epsilon_zeta_satisfies_eta<T>(x: T) -> usize
where
T: for<'a> Epsilon<'a>,
for<'a> <T as Epsilon<'a>>::Zeta: Eta,
{
x.epsilon() + x.zeta().eta()
}
// Implementations and types:
#[derive(Copy, Clone)]
pub struct BetaType;
#[derive(Copy, Clone)]
pub struct GammaType;
#[derive(Copy, Clone)]
pub struct ZetaType;
impl Beta for BetaType {
type Gamma = GammaType;
fn gamma(self) -> Self::Gamma { GammaType }
}
impl<'a> Beta for &'a BetaType {
type Gamma = GammaType;
fn gamma(self) -> Self::Gamma { GammaType }
}
impl Beta for GammaType {
type Gamma = Self;
fn gamma(self) -> Self::Gamma { self }
}
impl Alpha for GammaType {
fn alpha(self) -> usize { 42 }
}
impl Delta for GammaType {
fn delta(self) -> usize { 1337 }
}
impl<'a> Epsilon<'a> for GammaType {
type Zeta = ZetaType;
fn zeta(&'a self) -> Self::Zeta { ZetaType }
fn epsilon(&'a self) -> usize { 7331 }
}
impl Eta for ZetaType {
fn eta(self) -> usize { 7 }
}
// Desugared forms to check against:
pub fn desugared_bound<B>(beta: B) -> usize
where
B: Beta,
B::Gamma: Alpha
{
let gamma: B::Gamma = beta.gamma();
assert_alpha::<B::Gamma>(gamma)
}
pub fn desugared_bound_region<B>(beta: B) -> usize
where
B: Beta,
B::Gamma: 'static,
{
assert_static::<B::Gamma>(beta.gamma())
}
pub fn desugared_bound_multi<B>(beta: B) -> usize
where
B: Copy + Beta,
B::Gamma: Alpha + 'static + Delta,
{
assert_alpha::<B::Gamma>(beta.gamma()) +
assert_static::<B::Gamma>(beta.gamma()) +
assert_delta::<B::Gamma>(beta.gamma())
}
pub fn desugared_bound_region_specific<'a, B>(gamma: &'a B::Gamma) -> usize
where
B: Beta,
B::Gamma: 'a + Epsilon<'a>,
{
assert_epsilon_specific::<B::Gamma>(gamma)
}
pub fn desugared_bound_region_forall<B>(beta: B) -> usize
where
B: Beta,
B::Gamma: Copy + for<'a> Epsilon<'a>,
{
assert_epsilon_forall::<B::Gamma>();
let g1: B::Gamma = beta.gamma();
let g2: B::Gamma = g1;
assert_epsilon_specific::<B::Gamma>(&g1) +
assert_epsilon_specific::<B::Gamma>(&g2)
}
pub fn desugared_bound_region_forall2<B>(beta: B) -> usize
where
B: Beta,
B::Gamma: Copy + for<'a> Epsilon<'a>,
for<'a> <B::Gamma as Epsilon<'a>>::Zeta: Eta,
{
let gamma = beta.gamma();
assert_forall_epsilon_zeta_satisfies_eta::<B::Gamma>(gamma)
}
pub fn desugared_contraint_region_forall<B>(beta: B) -> usize
where
for<'a> &'a B: Beta,
for<'a> <&'a B as Beta>::Gamma: Alpha,
{
let g1 = beta.gamma();
let g2 = beta.gamma();
assert_alpha(g1) + assert_alpha(g2)
}
pub fn desugared_bound_nested<B>(beta: B) -> usize
where
B: Beta,
B::Gamma: Copy + Alpha + Beta,
<B::Gamma as Beta>::Gamma: Delta,
{
let go = beta.gamma();
let gi = go.gamma();
go.alpha() + gi.delta()
}
pub fn desugared() {
let beta = BetaType;
let gamma = beta.gamma();
assert_eq!(42, desugared_bound(beta));
assert_eq!(24, desugared_bound_region(beta));
assert_eq!(42 + 24 + 1337, desugared_bound_multi(beta));
assert_eq!(7331, desugared_bound_region_specific::<BetaType>(&gamma));
assert_eq!(7331 * 2, desugared_bound_region_forall(beta));
assert_eq!(42 + 1337, desugared_bound_nested(beta));
}
// Check dynamic semantics:
fn main() {
desugared();
}
// run-pass
use fn_aux::*;
// ATB, APIT (dyn trait):
fn dyn_apit_bound(beta: &dyn Beta<Gamma: Alpha>) -> usize {
desugared_bound(beta)
}
fn dyn_apit_bound_region(beta: &dyn Beta<Gamma: 'static>) -> usize {
desugared_bound_region(beta)
}
fn dyn_apit_bound_multi(
beta: &dyn Copy + Beta<Gamma: Alpha + 'static + Delta>
) -> usize {
desugared_bound_multi(beta)
}
fn dyn_apit_bound_region_forall(
beta: &dyn Beta<Gamma: Copy + for<'a> Epsilon<'a>>
) -> usize {
desugared_bound_region_forall(beta)
}
fn dyn_apit_bound_region_forall2(
beta: &dyn Beta<Gamma: Copy + for<'a> Epsilon<'a, Zeta: Eta>>
) -> usize {
desugared_bound_region_forall2(beta)
}
fn dyn_apit_bound_nested(
beta: &dyn Beta<Gamma: Copy + Alpha + Beta<Gamma: Delta>>
) -> usize {
desugared_bound_nested(beta)
}
fn dyn_apit_bound_nested2(
beta: &dyn Beta<Gamma = impl Copy + Alpha + Beta<Gamma: Delta>>
) -> usize {
desugared_bound_nested(beta)
}
fn main() {
let beta = BetaType;
let gamma = beta.gamma();
assert_eq!(42, dyn_apit_bound(&beta));
assert_eq!(24, dyn_apit_bound_region(&beta));
assert_eq!(42 + 24 + 1337, dyn_apit_bound_multi(&beta));
assert_eq!(7331 * 2, dyn_apit_bound_region_forall(&beta));
assert_eq!(42 + 1337, dyn_apit_bound_nested(&beta));
assert_eq!(42 + 1337, dyn_apit_bound_nested2(&beta));
}
// run-pass
use fn_aux::*;
// ATB, Type parameters, Inline bounds:
fn inline_bound<B: Beta<Gamma: Alpha>>(beta: B) -> usize {
desugared_bound(beta)
}
fn inline_bound_region<B: Beta<Gamma: 'static>>(beta: B) -> usize {
desugared_bound_region(beta)
}
fn inline_bound_multi<B: Copy + Beta<Gamma: Alpha + 'static + Delta>>(
beta: B
) -> usize {
desugared_bound_multi(beta)
}
fn inline_bound_region_specific<'a, B: Beta<Gamma: 'a + Epsilon<'a>>>(
gamma: &'a B::Gamma
) -> usize {
desugared_bound_region_specific(gamma)
}
fn inline_bound_region_forall<B: Beta<Gamma: Copy + for<'a> Epsilon<'a>>>(
beta: B
) -> usize {
desugared_bound_region_forall(beta)
}
fn inline_bound_region_forall2<B: Beta<Gamma: Copy + for<'a> Epsilon<'a, Zeta: Eta>>>(
beta: B
) -> usize {
desugared_bound_region_forall2(beta)
}
fn inline_bound_nested<B: Beta<Gamma: Copy + Alpha + Beta<Gamma: Delta>>>(
beta: B
) -> usize {
desugared_bound_nested(beta)
}
fn inline() {
let beta = BetaType;
let gamma = beta.gamma();
assert_eq!(42, inline_bound(beta));
assert_eq!(24, inline_bound_region(beta));
assert_eq!(42 + 24 + 1337, inline_bound_multi(beta));
assert_eq!(7331, inline_bound_region_specific::<BetaType>(&gamma));
assert_eq!(7331 * 2, inline_bound_region_forall::<BetaType>(beta));
assert_eq!(42 + 1337, inline_bound_nested::<BetaType>(beta));
}
// run-pass
use fn_aux::*;
// ATB, Type parameters, Where clauses:
fn where_bound<B>(beta: B) -> usize
where
B: Beta<Gamma: Alpha>
{
desugared_bound(beta)
}
fn where_bound_region<B>(beta: B) -> usize
where
B: Beta<Gamma: 'static>
{
desugared_bound_region(beta)
}
fn where_bound_multi<B>(beta: B) -> usize
where
B: Copy + Beta<Gamma: Alpha + 'static + Delta>,
{
desugared_bound_multi(beta)
}
fn where_bound_region_specific<'a, B>(gamma: &'a B::Gamma) -> usize
where
B: Beta<Gamma: 'a + Epsilon<'a>>,
{
desugared_bound_region_specific(gamma)
}
fn where_bound_region_forall<B>(beta: B) -> usize
where
B: Beta<Gamma: Copy + for<'a> Epsilon<'a>>,
{
desugared_bound_region_forall(beta)
}
fn where_bound_region_forall2<B>(beta: B) -> usize
where
B: Beta<Gamma: Copy + for<'a> Epsilon<'a, Zeta: Eta>>,
{
desugared_bound_region_forall2(beta)
}
fn where_contraint_region_forall<B>(beta: B) -> usize
where
for<'a> &'a B: Beta<Gamma: Alpha>,
{
desugared_contraint_region_forall(beta)
}
fn where_bound_nested<B>(beta: B) -> usize
where
B: Beta<Gamma: Copy + Alpha + Beta<Gamma: Delta>>,
{
desugared_bound_nested(beta)
}
fn main() {
let beta = BetaType;
let gamma = beta.gamma();
assert_eq!(42, where_bound(beta));
assert_eq!(24, where_bound_region(beta));
assert_eq!(42 + 24 + 1337, where_bound_multi(beta));
assert_eq!(7331, where_bound_region_specific::<BetaType>(&gamma));
assert_eq!(7331 * 2, where_bound_region_forall::<BetaType>(beta));
assert_eq!(42 + 1337, where_bound_nested::<BetaType>(beta));
}
// run-pass
use fn_aux::*;
// ATB, APIT + Wrap:
struct Wrap<T>(T);
fn wrap_apit_bound(beta: Wrap<impl Beta<Gamma: Alpha>>) -> usize {
desugared_bound(beta.0)
}
fn wrap_apit_bound_region(beta: Wrap<impl Beta<Gamma: 'static>>) -> usize {
desugared_bound_region(beta.0)
}
fn wrap_apit_bound_multi(
beta: Wrap<impl Copy + Beta<Gamma: Alpha + 'static + Delta>>
) -> usize {
desugared_bound_multi(beta.0)
}
fn wrap_apit_bound_region_forall(
beta: Wrap<impl Beta<Gamma: Copy + for<'a> Epsilon<'a>>>
) -> usize {
desugared_bound_region_forall(beta.0)
}
fn wrap_apit_bound_region_forall2(
beta: Wrap<impl Beta<Gamma: Copy + for<'a> Epsilon<'a, Zeta: Eta>>>
) -> usize {
desugared_bound_region_forall2(beta.0)
}
fn wrap_apit_bound_nested(
beta: Wrap<impl Beta<Gamma: Copy + Alpha + Beta<Gamma: Delta>>>
) -> usize {
desugared_bound_nested(beta.0)
}
fn wrap_apit_bound_nested2(
beta: Wrap<impl Beta<Gamma = impl Copy + Alpha + Beta<Gamma: Delta>>>
) -> usize {
desugared_bound_nested(beta.0)
}
fn main() {
let beta = BetaType;
let gamma = beta.gamma();
assert_eq!(42, wrap_apit_bound(beta));
assert_eq!(24, wrap_apit_bound_region(beta));
assert_eq!(42 + 24 + 1337, wrap_apit_bound_multi(beta));
assert_eq!(7331 * 2, wrap_apit_bound_region_forall(beta));
assert_eq!(42 + 1337, wrap_apit_bound_nested(beta));
assert_eq!(42 + 1337, wrap_apit_bound_nested2(beta));
}
// compile-fail
trait Tr1 { type As1; }
trait Tr2 { type As2; }
struct St<'a, 'b, T: Tr1<As1: Tr2>> { // `T: 'b` is *not* implied!
f0: &'a T, // `T: 'a` is implied.
f1: &'b <T::As1 as Tr2>::As2, // `<T::As1 as Tr2>::As2: 'a` is implied.
}
fn _bad_st<'a, 'b, T>(x: St<'a, 'b, T>)
where
T: Tr1,
T::As1: Tr2,
{
// This should fail because `T: 'b` is not implied from `WF(St<'a, 'b, T>)`.
let _failure_proves_not_implied_outlives_region_b: &'b T = &x.f0; // error[E0623]: lifetime mismatch
}
enum En7<'a, 'b, T> // `<T::As1 as Tr2>::As2: 'a` is implied.
where
T: Tr1,
T::As1: Tr2,
{
V0(&'a T),
V1(&'b <T::As1 as Tr2>::As2),
}
fn _bad_en7<'a, 'b, T>(x: En7<'a, 'b, T>)
where
T: Tr1,
T::As1: Tr2,
{
match x {
En7::V0(x) => {
// Also fails for the same reason as above:
let _failure_proves_not_implied_outlives_region_b: &'b T = &x; // error[E0623]: lifetime mismatch
},
En7::V1(_) => {},
}
}
// run-pass
#![feature(impl_trait_in_bindings)]
#![allow(non_upper_case_globals)]
trait Tr1 { type As1; fn mk(self) -> Self::As1; }
trait Tr2<'a> { fn tr2(self) -> &'a Self; }
fn assert_copy<T: Copy>(x: T) { let _x = x; let _x = x; }
fn assert_static<T: 'static>(_: T) {}
fn assert_forall_tr2<T: for<'a> Tr2<'a>>(_: T) {}
#[derive(Copy, Clone)]
struct S1;
#[derive(Copy, Clone)]
struct S2;
impl Tr1 for S1 { type As1 = S2; fn mk(self) -> Self::As1 { S2 } }
const cdef_et1: impl Copy + Tr1<As1: Copy> = {
let x: impl Copy + Tr1<As1: Copy> = S1;
x
};
static sdef_et1: impl Copy + Tr1<As1: Copy> = cdef_et1;
pub fn use_et1() { assert_copy(cdef_et1.mk()); assert_copy(sdef_et1.mk()); }
const cdef_et2: impl Tr1<As1: 'static> = {
let x: impl Tr1<As1: 'static> = S1;
x
};
static sdef_et2: impl Tr1<As1: 'static> = cdef_et2;
pub fn use_et2() { assert_static(cdef_et2.mk()); assert_static(sdef_et2.mk()); }
use core::ops::Add;
const cdef_et3: impl Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>> = {
struct A;
impl Tr1 for A {
type As1 = core::ops::Range<u8>;
fn mk(self) -> Self::As1 { 0..10 }
};
let x: impl Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>> = A;
x
};
pub fn use_et3() {
let _0 = cdef_et3.mk().clone();
let mut s = 0u8;
for _1 in _0 {
let _2 = _1 + 1u8;
s += _2.into();
}
assert_eq!(s, (0..10).map(|x| x + 1).sum());
}
const cdef_et4: impl Copy + Tr1<As1: for<'a> Tr2<'a>> = {
#[derive(Copy, Clone)]
struct A;
impl Tr1 for A {
type As1 = A;
fn mk(self) -> A { A }
}
impl<'a> Tr2<'a> for A {
fn tr2(self) -> &'a Self { &A }
}
let x: impl Copy + Tr1<As1: for<'a> Tr2<'a>> = A;
x
};
static sdef_et4: impl Copy + Tr1<As1: for<'a> Tr2<'a>> = cdef_et4;
pub fn use_et4() { assert_forall_tr2(cdef_et4.mk()); assert_forall_tr2(sdef_et4.mk()); }
fn main() {
let _ = use_et1();
let _ = use_et2();
let _ = use_et3();
let _ = use_et4();
}
// run-pass
trait Tr1 { type As1; fn mk(self) -> Self::As1; }
trait Tr2<'a> { fn tr2(self) -> &'a Self; }
fn assert_copy<T: Copy>(x: T) { let _x = x; let _x = x; }
fn assert_static<T: 'static>(_: T) {}
fn assert_forall_tr2<T: for<'a> Tr2<'a>>(_: T) {}
struct S1;
#[derive(Copy, Clone)]
struct S2;
impl Tr1 for S1 { type As1 = S2; fn mk(self) -> Self::As1 { S2 } }
fn def_et1() -> impl Tr1<As1: Copy> { S1 }
pub fn use_et1() { assert_copy(def_et1().mk()); }
fn def_et2() -> impl Tr1<As1: 'static> { S1 }
pub fn use_et2() { assert_static(def_et2().mk()); }
use core::ops::Add;
fn def_et3() -> impl Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>> {
struct A;
impl Tr1 for A {
type As1 = core::ops::Range<u8>;
fn mk(self) -> Self::As1 { 0..10 }
};
A
}
pub fn use_et3() {
let _0 = def_et3().mk().clone();
let mut s = 0u8;
for _1 in _0 {
let _2 = _1 + 1u8;
s += _2.into();
}
assert_eq!(s, (0..10).map(|x| x + 1).sum());
}
fn def_et4() -> impl Tr1<As1: for<'a> Tr2<'a>> {
#[derive(Copy, Clone)]
struct A;
impl Tr1 for A {
type As1 = A;
fn mk(self) -> A { A }
}
impl<'a> Tr2<'a> for A {
fn tr2(self) -> &'a Self { &A }
}
A
}
pub fn use_et4() { assert_forall_tr2(def_et4().mk()); }
fn main() {
let _ = use_et1();
let _ = use_et2();
let _ = use_et3();
let _ = use_et4();
}
// run-pass
trait Tr1 { type As1; }
trait Tr2 { type As2; }
trait Tr3 {}
trait Tr4<'a> { type As4; }
trait Tr5 { type As5; }
impl Tr1 for &str { type As1 = bool; }
impl Tr2 for bool { type As2 = u8; }
impl Tr3 for u8 {}
impl Tr1 for () { type As1 = (usize,); }
impl<'a> Tr4<'a> for (usize,) { type As4 = u8; }
impl Tr5 for bool { type As5 = u16; }
struct St1<T: Tr1<As1: Tr2>> {
outest: T,
outer: T::As1,
inner: <T::As1 as Tr2>::As2,
}
fn unwrap_1_st1<T: Tr1<As1: Tr2>>(x: St1<T>) -> (T, T::As1, <T::As1 as Tr2>::As2) {
(x.outest, x.outer, x.inner)
}
fn unwrap_2_st1<T>(x: St1<T>) -> (T, T::As1, <T::As1 as Tr2>::As2)
where
T: Tr1,
T::As1: Tr2,
{
unwrap_1_st1(x)
}
struct St2<T: Tr1<As1: Tr2<As2: Tr3>>> {
outest: T,
outer: T::As1,
inner: <T::As1 as Tr2>::As2,
}
struct St3<T: Tr1<As1: 'static>> {
outest: T,
outer: &'static T::As1,
}
struct St4<'x1, 'x2, T: Tr1<As1: for<'l> Tr4<'l>>> {
f1: &'x1 <T::As1 as Tr4<'x1>>::As4,
f2: &'x2 <T::As1 as Tr4<'x2>>::As4,
}
struct St5<'x1, 'x2, T: Tr1<As1: for<'l> Tr4<'l, As4: Copy>>> {
f1: &'x1 <T::As1 as Tr4<'x1>>::As4,
f2: &'x2 <T::As1 as Tr4<'x2>>::As4,
}
struct St6<T>
where
T: Tr1<As1: Tr2 + 'static + Tr5>,
{
f0: T,
f1: <T::As1 as Tr2>::As2,
f2: &'static T::As1,
f3: <T::As1 as Tr5>::As5,
}
struct St7<'a, 'b, T> // `<T::As1 as Tr2>::As2: 'a` is implied.
where
T: Tr1<As1: Tr2>,
{
f0: &'a T,
f1: &'b <T::As1 as Tr2>::As2,
}
fn _use_st7<'a, 'b, T>(x: St7<'a, 'b, T>)
where
T: Tr1,
T::As1: Tr2,
{
let _: &'a T = &x.f0;
}
struct StSelf<T> where Self: Tr1<As1: Tr2> {
f2: <<Self as Tr1>::As1 as Tr2>::As2,
}
impl Tr1 for StSelf<&'static str> { type As1 = bool; }
fn main() {
let st1 = St1 { outest: "foo", outer: true, inner: 42u8 };
assert_eq!(("foo", true, 42), unwrap_1_st1(st1));
let _ = St2 { outest: "foo", outer: true, inner: 42u8 };
let _ = St3 { outest: "foo", outer: &true };
let f1 = (1,);
let f2 = (2,);
let st4 = St4::<()> { f1: &f1.0, f2: &f2.0, };
assert_eq!((&1, &2), (st4.f1, st4.f2));
/*
// FIXME: This won't work due to lack of lazy norm:
let f1 = (1,);
let f2 = (2,);
let st5 = St5::<()> { f1: &f1.0, f2: &f2.0, };
assert_eq!((&1, &2), (st5.f1, st5.f2));
*/
let st6 = St6 { f0: "bar", f1: 24u8, f2: &true, f3: 12u16, };
assert_eq!(("bar", 24, &true, 12), (st6.f0, st6.f1, st6.f2, st6.f3));
let stself = StSelf::<&'static str> { f2: 42u8 };
assert_eq!(stself.f2, 42u8);
}
// compile-pass
pub trait Three { type A; type B; type C; }
pub fn assert_three<T: ?Sized + Three>() {}
pub fn assert_iterator<T: Iterator>() {}
pub fn assert_copy<T: Copy>() {}
pub fn assert_static<T: 'static>() {}
pub fn assert_send<T: Send>() {}
pub fn assert_forall_into<T: for<'a> Into<&'a u8>>() {}
use core::ops::Range;
use core::iter::Once;
struct A; struct B;
impl<'a> Into<&'a u8> for A { fn into(self) -> &'a u8 { &0 } }
impl Three for B { type A = Range<u8>; type B = Range<u8>; type C = Range<u8>; }
trait Case1<A, B, C, D, E>
where
A: Iterator<Item: Copy>,
B: Iterator<Item: 'static>,
C: Iterator<Item: 'static + Copy + Send>,
D: Iterator<Item: for<'a> Into<&'a u8>>,
E: Three<A: Iterator<Item: Copy>, B: Iterator<Item: Copy>, C: Iterator<Item: Copy>>,
Self: Three<A: 'static, B: Copy, C: Send>,
{
fn _a() {
assert_iterator::<A>();
assert_copy::<A::Item>();
}
fn _b() {
assert_iterator::<B>();
assert_static::<B::Item>();
}
fn _c() {
assert_iterator::<C>();
assert_copy::<C::Item>();
assert_static::<C::Item>();
assert_send::<C::Item>();
}
fn _d() {
assert_iterator::<D>();
assert_forall_into::<D::Item>();
}
fn _e() {
assert_three::<E>();
assert_iterator::<E::A>();
assert_iterator::<E::B>();
assert_iterator::<E::C>();
assert_copy::<<E::A as Iterator>::Item>();
assert_copy::<<E::B as Iterator>::Item>();
assert_copy::<<E::C as Iterator>::Item>();
}
fn _self() {
assert_three::<Self>();
assert_copy::<Self::B>();
assert_static::<Self::A>();
assert_send::<Self::C>();
}
}
struct DataCase1;
impl Three for DataCase1 { type A = u8; type B = u8; type C = u8; }
impl Case1<Range<u8>, Range<u8>, Range<u8>, Once<A>, B> for DataCase1 {}
trait Case2<
A: Iterator<Item: Copy>,
B: Iterator<Item: 'static>,
C: Iterator<Item: 'static + Copy + Send>,
D: Iterator<Item: for<'a> Into<&'a u8>>,
E: Three<A: Iterator<Item: Copy>, B: Iterator<Item: Copy>, C: Iterator<Item: Copy>>,
>:
Three<A: 'static, B: Copy, C: Send>
{
fn _a() {
assert_iterator::<A>();
assert_copy::<A::Item>();
}
fn _b() {
assert_iterator::<B>();
assert_static::<B::Item>();
}
fn _c() {
assert_iterator::<C>();
assert_copy::<C::Item>();
assert_static::<C::Item>();
assert_send::<C::Item>();
}
fn _d() {
assert_iterator::<D>();
assert_forall_into::<D::Item>();
}
fn _e() {
assert_three::<E>();
assert_iterator::<E::A>();
assert_iterator::<E::B>();
assert_iterator::<E::C>();
assert_copy::<<E::A as Iterator>::Item>();
assert_copy::<<E::B as Iterator>::Item>();
assert_copy::<<E::C as Iterator>::Item>();
}
fn _self() {
assert_three::<Self>();
assert_copy::<Self::B>();
assert_static::<Self::A>();
assert_send::<Self::C>();
}
}
struct DataCase2;
impl Three for DataCase2 { type A = u8; type B = u8; type C = u8; }
impl Case2<Range<u8>, Range<u8>, Range<u8>, Once<A>, B> for DataCase2 {}
// compile-pass
// These constraints have no effect:
type _TaWhere1<T> where T: Iterator<Item: Copy> = T;
// ~^ WARNING where clauses are not enforced in type aliases
type _TaWhere2<T> where T: Iterator<Item: 'static> = T;
// ~^ WARNING where clauses are not enforced in type aliases
type _TaWhere3<T> where T: Iterator<Item: 'static> = T;
// ~^ WARNING where clauses are not enforced in type aliases
type _TaWhere4<T> where T: Iterator<Item: 'static + Copy + S
// ~^ WARNING where clauses are not enforced in type aliasesend> = T;
type _TaWhere5<T> where T: Iterator<Item: for<'a> Into<&'a u8>> = T;
// ~^ WARNING where clauses are not enforced in type aliases
type _TaWhere6<T> where T: Iterator<Item: Iterator<Item: Copy>> = T;
// ~^ WARNING where clauses are not enforced in type aliases
type _TaInline1<T: Iterator<Item: Copy>> = T;
// ~^ WARNING bounds on generic parameters are not enforced in type aliases
type _TaInline2<T: Iterator<Item: 'static>> = T;
// ~^ WARNING bounds on generic parameters are not enforced in type aliases
type _TaInline3<T: Iterator<Item: 'static>> = T;
// ~^ WARNING bounds on generic parameters are not enforced in type aliases
type _TaInline4<T: Iterator<Item: 'static + Copy + Send>> = T;
// ~^ WARNING bounds on generic parameters are not enforced in type aliases
type _TaInline5<T: Iterator<Item: for<'a> Into<&'a u8>>> = T;
// ~^ WARNING bounds on generic parameters are not enforced in type aliases
type _TaInline6<T: Iterator<Item: Iterator<Item: Copy>>> = T;
// ~^ WARNING bounds on generic parameters are not enforced in type aliases
// run-pass
#![feature(untagged_unions)]
#![allow(unions_with_drop_fields, unused_assignments)]
trait Tr1 { type As1; }
trait Tr2 { type As2; }
trait Tr3 { type As3; }
trait Tr4<'a> { type As4; }
trait Tr5 { type As5; }
impl Tr1 for &str { type As1 = bool; }
impl Tr2 for bool { type As2 = u8; }
impl Tr3 for u8 { type As3 = fn() -> u8; }
impl Tr1 for () { type As1 = (usize,); }
impl<'a> Tr4<'a> for (usize,) { type As4 = u8; }
impl Tr5 for bool { type As5 = u16; }
union Un1<T: Tr1<As1: Tr2> {
outest: T,
outer: T::As1,
inner: <T::As1 as Tr2>::As2,
}
union Un2<T: Tr1<As1: Tr2<As2: Tr3>>> {
outest: T,
outer: T::As1,
inner: <T::As1 as Tr2>::As2,
}
union Un3<T: Tr1<As1: 'static>> {
outest: T,
outer: &'static T::As1,
}
union Un4<'x1, 'x2, T: Tr1<As1: for<'l> Tr4<'l>>> {
f1: &'x1 <T::As1 as Tr4<'x1>>::As4,
f2: &'x2 <T::As1 as Tr4<'x2>>::As4,
}
union _Un5<'x1, 'x2, T: Tr1<As1: for<'l> Tr4<'l, As4: Copy>>> {
f1: &'x1 <T::As1 as Tr4<'x1>>::As4,
f2: &'x2 <T::As1 as Tr4<'x2>>::As4,
}
union Un6<T>
where
T: Tr1<As1: Tr2 + 'static + Tr5>,
{
f0: T,
f1: <T::As1 as Tr2>::As2,
f2: &'static T::As1,
f3: <T::As1 as Tr5>::As5,
}
union _Un7<'a, 'b, T> // `<T::As1 as Tr2>::As2: 'a` is implied.
where
T: Tr1<As1: Tr2>,
{
f0: &'a T,
f1: &'b <T::As1 as Tr2>::As2,
}
unsafe fn _use_un7<'a, 'b, T>(x: _Un7<'a, 'b, T>)
where
T: Tr1,
T::As1: Tr2,
{
let _: &'a T = &x.f0;
}
union UnSelf<T> where Self: Tr1<As1: Tr2> {
f0: T,
f1: <Self as Tr1>::As1,
f2: <<Self as Tr1>::As1 as Tr2>::As2,
}
impl Tr1 for UnSelf<&'static str> { type As1 = bool; }
fn main() {
let mut un1 = Un1 { outest: "foo" };
un1 = Un1 { outer: true };
assert_eq!(unsafe { un1.outer }, true);
un1 = Un1 { inner: 42u8 };
assert_eq!(unsafe { un1.inner }, 42u8);
let mut un2 = Un2 { outest: "bar" };
assert_eq!(unsafe { un2.outest }, "bar");
un2 = Un2 { outer: true };
assert_eq!(unsafe { un2.outer }, true);
un2 = Un2 { inner: 42u8 };
assert_eq!(unsafe { un2.inner }, 42u8);
let mut un3 = Un3 { outest: "baz" };
assert_eq!(unsafe { un3.outest }, "baz");
un3 = Un3 { outer: &true };
assert_eq!(unsafe { *un3.outer }, true);
let f1 = (1,);
let f2 = (2,);
let mut un4 = Un4::<()> { f1: &f1.0 };
assert_eq!(1, unsafe { *un4.f1 });
un4 = Un4 { f2: &f2.0 };
assert_eq!(2, unsafe { *un4.f2 });
let mut un6 = Un6 { f0: "bar" };
assert_eq!(unsafe { un6.f0 }, "bar");
un6 = Un6 { f1: 24u8 };
assert_eq!(unsafe { un6.f1 }, 24u8);
un6 = Un6 { f2: &true };
assert_eq!(unsafe { un6.f2 }, &true);
un6 = Un6 { f3: 12u16 };
assert_eq!(unsafe { un6.f3 }, 12u16);
let mut unself = UnSelf::<_> { f0: "selfish" };
assert_eq!(unsafe { unself.f0 }, "selfish");
unself = UnSelf { f1: true };
assert_eq!(unsafe { unself.f1 }, true);
unself = UnSelf { f2: 24u8 };
assert_eq!(unsafe { unself.f2 }, 24u8);
}
@Centril
Copy link
Author

Centril commented Mar 4, 2019

  • Add a lot of compile-fail tests.
    • Failing when duplicate mentions of associated item.
  • Add tests for traits.
    • Inline quantification bounds
    • In where clauses
    • In supertrait bounds.
    • Add tests for bounds on associated types in traits.
  • Add tests for existential type.
  • Add tests for existential associated types
  • Add tests for type aliases.
  • Add tests for methods
    • Object safety.
  • Add tests for dyn Trait.
    • In fn
    • In let + static + const
    • In type (existential type)
    • In impl ... for ... { type Foo: Bar<dyn Baz<Quux: Wibble>>; }
    • In associated type defaults (should probably be deferred to work on ATDs)
    • In impl ... for dyn Foo<Bar: Baz> (run-pass or compile-fail? TBD...)
    • In static, enum, and union fields (run-pass or compile-fail? TBD...)
  • Add tests for RPIT.
  • Add tests for CIIT
  • Add tests for SIIT.
  • Add tests for LBIT.
  • Add tests for TypeAscriptionIT.
  • Add tests for AsIT.
  • Take a look at type grammar and where bounds may occur.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment