// run-pass // Test that type IDs correctly account for higher-rank lifetimes // Also acts as a regression test for an ICE (issue #19791) use std::any::{Any, TypeId}; struct Struct<'a>(#[allow(unused_tuple_struct_fields)] &'a ()); trait Trait<'a> {} fn main() { // Bare fns { let a = TypeId::of::(); let b = TypeId::of:: fn(&'static isize, &'a isize)>(); let c = TypeId::of:: fn(&'a isize, &'b isize)>(); let d = TypeId::of:: fn(&'b isize, &'a isize)>(); assert!(a != b); assert!(a != c); assert!(a != d); assert!(b != c); assert!(b != d); assert_eq!(c, d); // Make sure De Bruijn indices are handled correctly let e = TypeId::of:: fn(fn(&'a isize) -> &'a isize)>(); let f = TypeId::of:: fn(&'a isize) -> &'a isize)>(); assert!(e != f); // Make sure lifetime parameters of items are not ignored. let g = TypeId::of:: fn(&'a dyn Trait<'a>) -> Struct<'a>>(); let h = TypeId::of:: fn(&'a dyn Trait<'a>) -> Struct<'static>>(); let i = TypeId::of:: fn(&'a dyn Trait<'b>) -> Struct<'b>>(); assert!(g != h); assert!(g != i); assert!(h != i); // Make sure lifetime anonymization handles nesting correctly let j = TypeId::of:: fn(&'a isize) -> &'a usize)>(); let k = TypeId::of:: fn(&'b isize) -> &'b usize)>(); assert_eq!(j, k); } // Boxed unboxed closures { let a = TypeId::of::>(); let b = TypeId::of:: Fn(&'static isize, &'a isize)>>(); let c = TypeId::of:: Fn(&'a isize, &'b isize)>>(); let d = TypeId::of:: Fn(&'b isize, &'a isize)>>(); assert!(a != b); assert!(a != c); assert!(a != d); assert!(b != c); assert!(b != d); assert_eq!(c, d); // Make sure De Bruijn indices are handled correctly let e = TypeId::of:: Fn(Box &'a isize>)>>(); let f = TypeId::of:: Fn(&'a isize) -> &'a isize>)>>(); assert!(e != f); } // Raw unboxed closures // Note that every unboxed closure has its own anonymous type, // so no two IDs should equal each other, even when compatible { let a = id(|_: &isize, _: &isize| {}); let b = id(|_: &isize, _: &isize| {}); assert!(a != b); } fn id(_: T) -> TypeId { TypeId::of::() } }