Auto merge of #35267 - eddyb:ty-hash, r=nikomatsakis
Rewrite TypeId computation to not miss anything and work cross-crate. Fixes #33703 and also some soundness holes in `Any` due to `TypeId` ignoring most lifetimes.
This commit is contained in:
commit
ecdd51b7bb
7 changed files with 248 additions and 191 deletions
|
|
@ -21,14 +21,16 @@ pub struct E(Result<&'static str, isize>);
|
|||
pub type F = Option<isize>;
|
||||
pub type G = usize;
|
||||
pub type H = &'static str;
|
||||
pub type I = Box<Fn()>;
|
||||
|
||||
pub unsafe fn id_A() -> TypeId { TypeId::of::<A>() }
|
||||
pub unsafe fn id_B() -> TypeId { TypeId::of::<B>() }
|
||||
pub unsafe fn id_C() -> TypeId { TypeId::of::<C>() }
|
||||
pub unsafe fn id_D() -> TypeId { TypeId::of::<D>() }
|
||||
pub unsafe fn id_E() -> TypeId { TypeId::of::<E>() }
|
||||
pub unsafe fn id_F() -> TypeId { TypeId::of::<F>() }
|
||||
pub unsafe fn id_G() -> TypeId { TypeId::of::<G>() }
|
||||
pub unsafe fn id_H() -> TypeId { TypeId::of::<H>() }
|
||||
pub fn id_A() -> TypeId { TypeId::of::<A>() }
|
||||
pub fn id_B() -> TypeId { TypeId::of::<B>() }
|
||||
pub fn id_C() -> TypeId { TypeId::of::<C>() }
|
||||
pub fn id_D() -> TypeId { TypeId::of::<D>() }
|
||||
pub fn id_E() -> TypeId { TypeId::of::<E>() }
|
||||
pub fn id_F() -> TypeId { TypeId::of::<F>() }
|
||||
pub fn id_G() -> TypeId { TypeId::of::<G>() }
|
||||
pub fn id_H() -> TypeId { TypeId::of::<H>() }
|
||||
pub fn id_I() -> TypeId { TypeId::of::<I>() }
|
||||
|
||||
pub unsafe fn foo<T: Any>() -> TypeId { TypeId::of::<T>() }
|
||||
pub fn foo<T: Any>() -> TypeId { TypeId::of::<T>() }
|
||||
|
|
|
|||
|
|
@ -21,14 +21,16 @@ pub struct E(Result<&'static str, isize>);
|
|||
pub type F = Option<isize>;
|
||||
pub type G = usize;
|
||||
pub type H = &'static str;
|
||||
pub type I = Box<Fn()>;
|
||||
|
||||
pub unsafe fn id_A() -> TypeId { TypeId::of::<A>() }
|
||||
pub unsafe fn id_B() -> TypeId { TypeId::of::<B>() }
|
||||
pub unsafe fn id_C() -> TypeId { TypeId::of::<C>() }
|
||||
pub unsafe fn id_D() -> TypeId { TypeId::of::<D>() }
|
||||
pub unsafe fn id_E() -> TypeId { TypeId::of::<E>() }
|
||||
pub unsafe fn id_F() -> TypeId { TypeId::of::<F>() }
|
||||
pub unsafe fn id_G() -> TypeId { TypeId::of::<G>() }
|
||||
pub unsafe fn id_H() -> TypeId { TypeId::of::<H>() }
|
||||
pub fn id_A() -> TypeId { TypeId::of::<A>() }
|
||||
pub fn id_B() -> TypeId { TypeId::of::<B>() }
|
||||
pub fn id_C() -> TypeId { TypeId::of::<C>() }
|
||||
pub fn id_D() -> TypeId { TypeId::of::<D>() }
|
||||
pub fn id_E() -> TypeId { TypeId::of::<E>() }
|
||||
pub fn id_F() -> TypeId { TypeId::of::<F>() }
|
||||
pub fn id_G() -> TypeId { TypeId::of::<G>() }
|
||||
pub fn id_H() -> TypeId { TypeId::of::<H>() }
|
||||
pub fn id_I() -> TypeId { TypeId::of::<I>() }
|
||||
|
||||
pub unsafe fn foo<T:Any>() -> TypeId { TypeId::of::<T>() }
|
||||
pub fn foo<T: Any>() -> TypeId { TypeId::of::<T>() }
|
||||
|
|
|
|||
40
src/test/run-pass/type-id-higher-rank-2.rs
Normal file
40
src/test/run-pass/type-id-higher-rank-2.rs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Test that we can't ignore lifetimes by going through Any.
|
||||
|
||||
use std::any::Any;
|
||||
|
||||
struct Foo<'a>(&'a str);
|
||||
|
||||
fn good(s: &String) -> Foo { Foo(s) }
|
||||
|
||||
fn bad1(s: String) -> Option<&'static str> {
|
||||
let a: Box<Any> = Box::new(good as fn(&String) -> Foo);
|
||||
a.downcast_ref::<fn(&String) -> Foo<'static>>().map(|f| f(&s).0)
|
||||
}
|
||||
|
||||
trait AsStr<'a, 'b> {
|
||||
fn get(&'a self) -> &'b str;
|
||||
}
|
||||
|
||||
impl<'a> AsStr<'a, 'a> for String {
|
||||
fn get(&'a self) -> &'a str { self }
|
||||
}
|
||||
|
||||
fn bad2(s: String) -> Option<&'static str> {
|
||||
let a: Box<Any> = Box::new(Box::new(s) as Box<for<'a> AsStr<'a, 'a>>);
|
||||
a.downcast_ref::<Box<for<'a> AsStr<'a, 'static>>>().map(|x| x.get())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(bad1(String::from("foo")), None);
|
||||
assert_eq!(bad2(String::from("bar")), None);
|
||||
}
|
||||
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
use std::any::{Any, TypeId};
|
||||
|
||||
struct Struct<'a>(&'a ());
|
||||
trait Trait<'a> {}
|
||||
|
||||
fn main() {
|
||||
// Bare fns
|
||||
{
|
||||
|
|
@ -34,6 +37,14 @@ fn main() {
|
|||
let e = TypeId::of::<for<'a> fn(fn(&'a isize) -> &'a isize)>();
|
||||
let f = TypeId::of::<fn(for<'a> fn(&'a isize) -> &'a isize)>();
|
||||
assert!(e != f);
|
||||
|
||||
// Make sure lifetime parameters of items are not ignored.
|
||||
let g = TypeId::of::<for<'a> fn(&'a Trait<'a>) -> Struct<'a>>();
|
||||
let h = TypeId::of::<for<'a> fn(&'a Trait<'a>) -> Struct<'static>>();
|
||||
let i = TypeId::of::<for<'a, 'b> fn(&'a Trait<'b>) -> Struct<'b>>();
|
||||
assert!(g != h);
|
||||
assert!(g != i);
|
||||
assert!(h != i);
|
||||
}
|
||||
// Boxed unboxed closures
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,36 +23,37 @@ struct A;
|
|||
struct Test;
|
||||
|
||||
pub fn main() {
|
||||
unsafe {
|
||||
assert_eq!(TypeId::of::<other1::A>(), other1::id_A());
|
||||
assert_eq!(TypeId::of::<other1::B>(), other1::id_B());
|
||||
assert_eq!(TypeId::of::<other1::C>(), other1::id_C());
|
||||
assert_eq!(TypeId::of::<other1::D>(), other1::id_D());
|
||||
assert_eq!(TypeId::of::<other1::E>(), other1::id_E());
|
||||
assert_eq!(TypeId::of::<other1::F>(), other1::id_F());
|
||||
assert_eq!(TypeId::of::<other1::G>(), other1::id_G());
|
||||
assert_eq!(TypeId::of::<other1::H>(), other1::id_H());
|
||||
assert_eq!(TypeId::of::<other1::A>(), other1::id_A());
|
||||
assert_eq!(TypeId::of::<other1::B>(), other1::id_B());
|
||||
assert_eq!(TypeId::of::<other1::C>(), other1::id_C());
|
||||
assert_eq!(TypeId::of::<other1::D>(), other1::id_D());
|
||||
assert_eq!(TypeId::of::<other1::E>(), other1::id_E());
|
||||
assert_eq!(TypeId::of::<other1::F>(), other1::id_F());
|
||||
assert_eq!(TypeId::of::<other1::G>(), other1::id_G());
|
||||
assert_eq!(TypeId::of::<other1::H>(), other1::id_H());
|
||||
assert_eq!(TypeId::of::<other1::I>(), other1::id_I());
|
||||
|
||||
assert_eq!(TypeId::of::<other2::A>(), other2::id_A());
|
||||
assert_eq!(TypeId::of::<other2::B>(), other2::id_B());
|
||||
assert_eq!(TypeId::of::<other2::C>(), other2::id_C());
|
||||
assert_eq!(TypeId::of::<other2::D>(), other2::id_D());
|
||||
assert_eq!(TypeId::of::<other2::E>(), other2::id_E());
|
||||
assert_eq!(TypeId::of::<other2::F>(), other2::id_F());
|
||||
assert_eq!(TypeId::of::<other2::G>(), other2::id_G());
|
||||
assert_eq!(TypeId::of::<other2::H>(), other2::id_H());
|
||||
assert_eq!(TypeId::of::<other2::A>(), other2::id_A());
|
||||
assert_eq!(TypeId::of::<other2::B>(), other2::id_B());
|
||||
assert_eq!(TypeId::of::<other2::C>(), other2::id_C());
|
||||
assert_eq!(TypeId::of::<other2::D>(), other2::id_D());
|
||||
assert_eq!(TypeId::of::<other2::E>(), other2::id_E());
|
||||
assert_eq!(TypeId::of::<other2::F>(), other2::id_F());
|
||||
assert_eq!(TypeId::of::<other2::G>(), other2::id_G());
|
||||
assert_eq!(TypeId::of::<other2::H>(), other2::id_H());
|
||||
assert_eq!(TypeId::of::<other1::I>(), other2::id_I());
|
||||
|
||||
assert_eq!(other1::id_F(), other2::id_F());
|
||||
assert_eq!(other1::id_G(), other2::id_G());
|
||||
assert_eq!(other1::id_H(), other2::id_H());
|
||||
assert_eq!(other1::id_F(), other2::id_F());
|
||||
assert_eq!(other1::id_G(), other2::id_G());
|
||||
assert_eq!(other1::id_H(), other2::id_H());
|
||||
assert_eq!(other1::id_I(), other2::id_I());
|
||||
|
||||
assert_eq!(TypeId::of::<isize>(), other2::foo::<isize>());
|
||||
assert_eq!(TypeId::of::<isize>(), other1::foo::<isize>());
|
||||
assert_eq!(other2::foo::<isize>(), other1::foo::<isize>());
|
||||
assert_eq!(TypeId::of::<A>(), other2::foo::<A>());
|
||||
assert_eq!(TypeId::of::<A>(), other1::foo::<A>());
|
||||
assert_eq!(other2::foo::<A>(), other1::foo::<A>());
|
||||
}
|
||||
assert_eq!(TypeId::of::<isize>(), other2::foo::<isize>());
|
||||
assert_eq!(TypeId::of::<isize>(), other1::foo::<isize>());
|
||||
assert_eq!(other2::foo::<isize>(), other1::foo::<isize>());
|
||||
assert_eq!(TypeId::of::<A>(), other2::foo::<A>());
|
||||
assert_eq!(TypeId::of::<A>(), other1::foo::<A>());
|
||||
assert_eq!(other2::foo::<A>(), other1::foo::<A>());
|
||||
|
||||
// sanity test of TypeId
|
||||
let (a, b, c) = (TypeId::of::<usize>(), TypeId::of::<&'static str>(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue