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); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
existential type
.dyn Trait
.fn
let
+static
+const
type
(existential type)impl ... for ... { type Foo: Bar<dyn Baz<Quux: Wibble>>; }
impl ... for dyn Foo<Bar: Baz>
(run-pass or compile-fail? TBD...)static
,enum
, andunion
fields (run-pass or compile-fail? TBD...)Add tests for TypeAscriptionIT.Add tests for AsIT.