Auto merge of #31710 - eddyb:reify, r=nikomatsakis
Distinguish fn item types to allow reification from nothing to fn pointers. The first commit is a rebase of #26284, except for files that have moved since. This is a [breaking-change], due to: * each FFI function has a distinct type, like all other functions currently do * all generic parameters on functions are recorded in their item types, e.g.: `size_of::<u8>` & `size_of::<i8>`'s types differ despite their identical signature. * function items are zero-sized, which will stop transmutes from working on them The first two cases are handled in most cases with the new coerce-unify logic, which will combine incompatible function item types into function pointers, at the outer-most level of if-else chains, match arms and array literals. The last case is specially handled during type-checking such that transmutes from a function item type to a pointer or integer type will continue to work for another release cycle, but are being linted against. To get rid of warnings and ensure your code will continue to compile, cast to a pointer before transmuting.
This commit is contained in:
commit
bcda58f491
109 changed files with 2044 additions and 2230 deletions
|
|
@ -14,26 +14,26 @@ pub mod testtypes {
|
|||
use std::any::TypeId;
|
||||
|
||||
pub fn type_ids() -> Vec<TypeId> {
|
||||
let mut ids = vec!();
|
||||
ids.push(TypeId::of::<FooNil>());
|
||||
ids.push(TypeId::of::<FooBool>());
|
||||
ids.push(TypeId::of::<FooInt>());
|
||||
ids.push(TypeId::of::<FooUint>());
|
||||
ids.push(TypeId::of::<FooFloat>());
|
||||
ids.push(TypeId::of::<FooEnum>());
|
||||
ids.push(TypeId::of::<FooUniq>());
|
||||
ids.push(TypeId::of::<FooPtr>());
|
||||
ids.push(TypeId::of::<&'static FooTrait>());
|
||||
ids.push(TypeId::of::<FooStruct>());
|
||||
ids.push(TypeId::of::<FooTuple>());
|
||||
ids
|
||||
vec![
|
||||
TypeId::of::<FooBool>(),
|
||||
TypeId::of::<FooInt>(),
|
||||
TypeId::of::<FooUint>(),
|
||||
TypeId::of::<FooFloat>(),
|
||||
TypeId::of::<FooStr>(),
|
||||
TypeId::of::<FooArray>(),
|
||||
TypeId::of::<FooSlice>(),
|
||||
TypeId::of::<FooBox>(),
|
||||
TypeId::of::<FooPtr>(),
|
||||
TypeId::of::<FooRef>(),
|
||||
TypeId::of::<FooFnPtr>(),
|
||||
TypeId::of::<FooNil>(),
|
||||
TypeId::of::<FooTuple>(),
|
||||
TypeId::of::<FooTrait>(),
|
||||
TypeId::of::<FooStruct>(),
|
||||
TypeId::of::<FooEnum>()
|
||||
]
|
||||
}
|
||||
|
||||
// Tests ty_nil
|
||||
pub type FooNil = ();
|
||||
|
||||
// Skipping ty_bot
|
||||
|
||||
// Tests TyBool
|
||||
pub type FooBool = bool;
|
||||
|
||||
|
|
@ -49,25 +49,26 @@ pub mod testtypes {
|
|||
// Tests TyFloat (does not test all variants of FloatTy)
|
||||
pub type FooFloat = f64;
|
||||
|
||||
// For TyStr, what kind of string should I use? &'static str? String? Raw str?
|
||||
// Tests TyStr
|
||||
pub type FooStr = str;
|
||||
|
||||
// Tests TyEnum
|
||||
pub enum FooEnum {
|
||||
VarA(usize),
|
||||
VarB(usize, usize)
|
||||
}
|
||||
// Tests TyArray
|
||||
pub type FooArray = [u8; 1];
|
||||
|
||||
// Tests TySlice
|
||||
pub type FooSlice = [u8];
|
||||
|
||||
// Tests TyBox (of u8)
|
||||
pub type FooUniq = Box<u8>;
|
||||
|
||||
// As with TyStr, what type should be used for TyArray?
|
||||
pub type FooBox = Box<u8>;
|
||||
|
||||
// Tests TyRawPtr
|
||||
pub type FooPtr = *const u8;
|
||||
|
||||
// Skipping TyRef
|
||||
// Tests TyRef
|
||||
pub type FooRef = &'static u8;
|
||||
|
||||
// Skipping TyBareFn (how do you get a bare function type, rather than proc or closure?)
|
||||
// Tests TyFnPtr
|
||||
pub type FooFnPtr = fn(u8) -> bool;
|
||||
|
||||
// Tests TyTrait
|
||||
pub trait FooTrait {
|
||||
|
|
@ -80,14 +81,17 @@ pub mod testtypes {
|
|||
foo_field: usize
|
||||
}
|
||||
|
||||
// Tests TyEnum
|
||||
pub enum FooEnum {
|
||||
VarA(usize),
|
||||
VarB(usize, usize)
|
||||
}
|
||||
|
||||
// Tests TyTuple
|
||||
pub type FooNil = ();
|
||||
pub type FooTuple = (u8, i8, bool);
|
||||
|
||||
// Skipping ty_param
|
||||
|
||||
// Skipping ty_self
|
||||
|
||||
// Skipping ty_self
|
||||
// Skipping TyParam
|
||||
|
||||
// Skipping TyInfer
|
||||
|
||||
|
|
|
|||
|
|
@ -11,23 +11,37 @@
|
|||
// Test that the types of distinct fn items are not compatible by
|
||||
// default. See also `run-pass/fn-item-type-*.rs`.
|
||||
|
||||
fn foo(x: isize) -> isize { x * 2 }
|
||||
fn bar(x: isize) -> isize { x * 4 }
|
||||
fn foo<T>(x: isize) -> isize { x * 2 }
|
||||
fn bar<T>(x: isize) -> isize { x * 4 }
|
||||
|
||||
fn eq<T>(x: T, y: T) { }
|
||||
|
||||
fn main() {
|
||||
let f = if true { foo } else { bar };
|
||||
//~^ ERROR if and else have incompatible types
|
||||
//~| expected `fn(isize) -> isize {foo}`
|
||||
//~| found `fn(isize) -> isize {bar}`
|
||||
//~| expected fn item,
|
||||
//~| found a different fn item
|
||||
trait Foo { fn foo() { /* this is a default fn */ } }
|
||||
impl<T> Foo for T { /* `foo` is still default here */ }
|
||||
|
||||
eq(foo, bar);
|
||||
fn main() {
|
||||
eq(foo::<u8>, bar::<u8>);
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected `fn(isize) -> isize {foo}`
|
||||
//~| found `fn(isize) -> isize {bar}`
|
||||
//~| expected `fn(isize) -> isize {foo::<u8>}`
|
||||
//~| found `fn(isize) -> isize {bar::<u8>}`
|
||||
//~| expected fn item
|
||||
//~| found a different fn item
|
||||
|
||||
eq(foo::<u8>, foo::<i8>);
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected `fn(isize) -> isize {foo::<u8>}`
|
||||
//~| found `fn(isize) -> isize {foo::<i8>}`
|
||||
|
||||
eq(bar::<String>, bar::<Vec<u8>>);
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected `fn(isize) -> isize {bar::<collections::string::String>}`
|
||||
//~| found `fn(isize) -> isize {bar::<collections::vec::Vec<u8>>}`
|
||||
//~| expected struct `collections::string::String`
|
||||
//~| found struct `collections::vec::Vec`
|
||||
|
||||
// Make sure we distinguish between trait methods correctly.
|
||||
eq(<u8 as Foo>::foo, <u16 as Foo>::foo);
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected `fn() {Foo::foo}`
|
||||
//~| found `fn() {Foo::foo}`
|
||||
}
|
||||
|
|
|
|||
16
src/test/compile-fail/invalid-intrinsic.rs
Normal file
16
src/test/compile-fail/invalid-intrinsic.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2015 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.
|
||||
|
||||
#![feature(intrinsics)]
|
||||
extern "rust-intrinsic" {
|
||||
pub static breakpoint : unsafe extern "rust-intrinsic" fn();
|
||||
//~^ ERROR intrinsic has wrong type
|
||||
}
|
||||
fn main() { unsafe { breakpoint(); } }
|
||||
|
|
@ -17,7 +17,7 @@ fn main() {
|
|||
let y = match x {
|
||||
[] => None,
|
||||
//~^ ERROR mismatched types
|
||||
//~| expected `[_#0i; 2]`
|
||||
//~| expected `[_#1i; 2]`
|
||||
//~| found `[_#7t; 0]`
|
||||
//~| expected an array with a fixed size of 2 elements
|
||||
//~| found one with 0 elements
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ impl Debug for Player {
|
|||
}
|
||||
|
||||
fn str_to_direction(to_parse: &str) -> RoomDirection {
|
||||
match to_parse {
|
||||
match to_parse { //~ ERROR match arms have incompatible types
|
||||
"w" | "west" => RoomDirection::West,
|
||||
"e" | "east" => RoomDirection::East,
|
||||
"n" | "north" => RoomDirection::North,
|
||||
|
|
@ -116,7 +116,7 @@ fn str_to_direction(to_parse: &str) -> RoomDirection {
|
|||
"out" => RoomDirection::Out,
|
||||
"up" => RoomDirection::Up,
|
||||
"down" => RoomDirection::Down,
|
||||
_ => None //~ ERROR mismatched types
|
||||
_ => None //~ NOTE match arm with an incompatible type
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,5 +21,5 @@ impl<A> vec_monad<A> for Vec<A> {
|
|||
}
|
||||
fn main() {
|
||||
["hi"].bind(|x| [x] );
|
||||
//~^ ERROR no method named `bind` found for type `[&str; 1]` in the current scope
|
||||
//~^ ERROR no method named `bind` found for type `[&'static str; 1]` in the current scope
|
||||
}
|
||||
|
|
|
|||
51
src/test/compile-fail/transmute-from-fn-item-types-lint.rs
Normal file
51
src/test/compile-fail/transmute-from-fn-item-types-lint.rs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
// 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.
|
||||
|
||||
use std::mem;
|
||||
|
||||
unsafe fn foo() -> (isize, *const (), Option<fn()>) {
|
||||
let i = mem::transmute(bar);
|
||||
//~^ WARN is now zero-sized and has to be cast to a pointer before transmuting
|
||||
//~^^ WARN was previously accepted
|
||||
|
||||
let p = mem::transmute(foo);
|
||||
//~^ WARN is now zero-sized and has to be cast to a pointer before transmuting
|
||||
//~^^ WARN was previously accepted
|
||||
|
||||
let of = mem::transmute(main);
|
||||
//~^ WARN is now zero-sized and has to be cast to a pointer before transmuting
|
||||
//~^^ WARN was previously accepted
|
||||
|
||||
(i, p, of)
|
||||
}
|
||||
|
||||
unsafe fn bar() {
|
||||
mem::transmute::<_, *mut ()>(foo);
|
||||
//~^ WARN is now zero-sized and has to be cast to a pointer before transmuting
|
||||
//~^^ WARN was previously accepted
|
||||
|
||||
mem::transmute::<_, fn()>(bar);
|
||||
//~^ WARN is now zero-sized and has to be cast to a pointer before transmuting
|
||||
//~^^ WARN was previously accepted
|
||||
|
||||
// No error if a coercion would otherwise occur.
|
||||
mem::transmute::<fn(), usize>(main);
|
||||
|
||||
// Error, still, if the resulting type is not pointer-sized.
|
||||
mem::transmute::<_, u8>(main);
|
||||
//~^ ERROR transmute called with differently sized types
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
foo();
|
||||
bar();
|
||||
}
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ fn main() {
|
|||
let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
|
||||
//~^ ERROR: mismatched types
|
||||
//~| expected `unsafe extern "C" fn(isize, u8)`
|
||||
//~| found `unsafe extern "C" fn(isize, u8, ...)`
|
||||
//~| found `unsafe extern "C" fn(isize, u8, ...) {foo}`
|
||||
//~| expected non-variadic fn
|
||||
//~| found variadic function
|
||||
|
||||
|
|
|
|||
|
|
@ -86,8 +86,10 @@ pub fn id<T>(x: T) -> T { (x as T) }
|
|||
pub fn use_id() {
|
||||
let _ =
|
||||
((id::<[i32; (3 as usize)]> as
|
||||
fn([i32; 3]) -> [i32; 3] {id})(([(1 as i32), (2 as i32),
|
||||
(3 as i32)] as [i32; 3])) as
|
||||
fn([i32; 3]) -> [i32; 3] {id::<[i32; 3]>})(([(1 as i32),
|
||||
(2 as i32),
|
||||
(3 as i32)] as
|
||||
[i32; 3])) as
|
||||
[i32; 3]);
|
||||
}
|
||||
fn main() { }
|
||||
|
|
|
|||
77
src/test/run-pass/coerce-unify.rs
Normal file
77
src/test/run-pass/coerce-unify.rs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
// 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.
|
||||
|
||||
// Check that coercions can unify if-else, match arms and array elements.
|
||||
|
||||
// Try to construct if-else chains, matches and arrays out of given expressions.
|
||||
macro_rules! check {
|
||||
($last:expr $(, $rest:expr)+) => {
|
||||
// Last expression comes first because of whacky ifs and matches.
|
||||
let _ = $(if false { $rest })else+ else { $last };
|
||||
|
||||
let _ = match 0 { $(_ if false => $rest,)+ _ => $last };
|
||||
|
||||
let _ = [$($rest,)+ $last];
|
||||
}
|
||||
}
|
||||
|
||||
// Check all non-uniform cases of 2 and 3 expressions of 2 types.
|
||||
macro_rules! check2 {
|
||||
($a:expr, $b:expr) => {
|
||||
check!($a, $b);
|
||||
check!($b, $a);
|
||||
|
||||
check!($a, $a, $b);
|
||||
check!($a, $b, $a);
|
||||
check!($a, $b, $b);
|
||||
|
||||
check!($b, $a, $a);
|
||||
check!($b, $a, $b);
|
||||
check!($b, $b, $a);
|
||||
}
|
||||
}
|
||||
|
||||
// Check all non-uniform cases of 2 and 3 expressions of 3 types.
|
||||
macro_rules! check3 {
|
||||
($a:expr, $b:expr, $c:expr) => {
|
||||
// Delegate to check2 for cases where a type repeats.
|
||||
check2!($a, $b);
|
||||
check2!($b, $c);
|
||||
check2!($a, $c);
|
||||
|
||||
// Check the remaining cases, i.e. permutations of ($a, $b, $c).
|
||||
check!($a, $b, $c);
|
||||
check!($a, $c, $b);
|
||||
check!($b, $a, $c);
|
||||
check!($b, $c, $a);
|
||||
check!($c, $a, $b);
|
||||
check!($c, $b, $a);
|
||||
}
|
||||
}
|
||||
|
||||
use std::mem::size_of;
|
||||
|
||||
fn foo() {}
|
||||
fn bar() {}
|
||||
|
||||
pub fn main() {
|
||||
check3!(foo, bar, foo as fn());
|
||||
check3!(size_of::<u8>, size_of::<u16>, size_of::<usize> as fn() -> usize);
|
||||
|
||||
let s = String::from("bar");
|
||||
check2!("foo", &s);
|
||||
|
||||
let a = [1, 2, 3];
|
||||
let v = vec![1, 2, 3];
|
||||
check2!(&a[..], &v);
|
||||
|
||||
// Make sure in-array coercion still works.
|
||||
let _ = [("a", Default::default()), (Default::default(), "b"), (&s, &s)];
|
||||
}
|
||||
|
|
@ -25,16 +25,17 @@
|
|||
|
||||
#[repr(u32)]
|
||||
enum Foo {
|
||||
A = 0,
|
||||
B = 23
|
||||
A = 0,
|
||||
B = 23
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
extern "C" fn foo(_x: usize) -> Foo { Foo::B }
|
||||
|
||||
pub fn main() {
|
||||
unsafe {
|
||||
let f: extern "C" fn(usize) -> u32 = ::std::mem::transmute(foo);
|
||||
assert_eq!(f(0xDEADBEEF), Foo::B as u32);
|
||||
}
|
||||
unsafe {
|
||||
let f: extern "C" fn(usize) -> u32 =
|
||||
::std::mem::transmute(foo as extern "C" fn(usize) -> Foo);
|
||||
assert_eq!(f(0xDEADBEEF), Foo::B as u32);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
22
src/test/run-pass/fn-item-type-zero-sized.rs
Normal file
22
src/test/run-pass/fn-item-type-zero-sized.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// 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 fn item types are zero-sized.
|
||||
|
||||
use std::mem::{size_of, size_of_val};
|
||||
|
||||
fn main() {
|
||||
assert_eq!(size_of_val(&main), 0);
|
||||
|
||||
let (a, b) = (size_of::<u8>, size_of::<u16>);
|
||||
assert_eq!(size_of_val(&a), 0);
|
||||
assert_eq!(size_of_val(&b), 0);
|
||||
assert_eq!((a(), b()), (1, 2));
|
||||
}
|
||||
|
|
@ -19,23 +19,29 @@ use issue13507::testtypes;
|
|||
use std::any::TypeId;
|
||||
|
||||
pub fn type_ids() -> Vec<TypeId> {
|
||||
let mut ids = vec!();
|
||||
ids.push(TypeId::of::<testtypes::FooNil>());
|
||||
ids.push(TypeId::of::<testtypes::FooBool>());
|
||||
ids.push(TypeId::of::<testtypes::FooInt>());
|
||||
ids.push(TypeId::of::<testtypes::FooUint>());
|
||||
ids.push(TypeId::of::<testtypes::FooFloat>());
|
||||
ids.push(TypeId::of::<testtypes::FooEnum>());
|
||||
ids.push(TypeId::of::<testtypes::FooUniq>());
|
||||
ids.push(TypeId::of::<testtypes::FooPtr>());
|
||||
ids.push(TypeId::of::<&'static testtypes::FooTrait>());
|
||||
ids.push(TypeId::of::<testtypes::FooStruct>());
|
||||
ids.push(TypeId::of::<testtypes::FooTuple>());
|
||||
ids
|
||||
use issue13507::testtypes::*;
|
||||
vec![
|
||||
TypeId::of::<FooBool>(),
|
||||
TypeId::of::<FooInt>(),
|
||||
TypeId::of::<FooUint>(),
|
||||
TypeId::of::<FooFloat>(),
|
||||
TypeId::of::<FooStr>(),
|
||||
TypeId::of::<FooArray>(),
|
||||
TypeId::of::<FooSlice>(),
|
||||
TypeId::of::<FooBox>(),
|
||||
TypeId::of::<FooPtr>(),
|
||||
TypeId::of::<FooRef>(),
|
||||
TypeId::of::<FooFnPtr>(),
|
||||
TypeId::of::<FooNil>(),
|
||||
TypeId::of::<FooTuple>(),
|
||||
TypeId::of::<FooTrait>(),
|
||||
TypeId::of::<FooStruct>(),
|
||||
TypeId::of::<FooEnum>()
|
||||
]
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let othercrate = testtypes::type_ids();
|
||||
let othercrate = issue13507::testtypes::type_ids();
|
||||
let thiscrate = type_ids();
|
||||
assert_eq!(thiscrate, othercrate);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -204,48 +204,41 @@ fn t24() -> fn(u8) -> S {
|
|||
C4
|
||||
}
|
||||
|
||||
fn main(){
|
||||
unsafe {
|
||||
assert_eq!(t1()(), regular());
|
||||
fn main() {
|
||||
assert_eq!(t1()(), regular());
|
||||
|
||||
assert!(::std::mem::transmute::<_, *mut ()>(t2()) ==
|
||||
::std::mem::transmute::<_, *mut ()>(E::U));
|
||||
assert!(::std::mem::transmute::<_, *mut ()>(t3()) ==
|
||||
::std::mem::transmute::<_, *mut ()>(S));
|
||||
assert_eq!(t2() as *mut (), E::U as *mut ());
|
||||
assert_eq!(t3() as *mut (), S as *mut ());
|
||||
|
||||
assert_eq!(t4()(), S::hey());
|
||||
let s = S(42);
|
||||
assert_eq!(t5()(&s), <S as X>::hoy(&s));
|
||||
assert_eq!(t4()(), S::hey());
|
||||
let s = S(42);
|
||||
assert_eq!(t5()(&s), <S as X>::hoy(&s));
|
||||
|
||||
|
||||
assert_eq!(t6()(), ext::regular_fn());
|
||||
assert!(::std::mem::transmute::<_, *mut ()>(t7()) ==
|
||||
::std::mem::transmute::<_, *mut ()>(ext::E::U));
|
||||
assert!(::std::mem::transmute::<_, *mut ()>(t8()) ==
|
||||
::std::mem::transmute::<_, *mut ()>(ext::S));
|
||||
assert_eq!(t6()(), ext::regular_fn());
|
||||
assert_eq!(t7() as *mut (), ext::E::U as *mut ());
|
||||
assert_eq!(t8() as *mut (), ext::S as *mut ());
|
||||
|
||||
assert_eq!(t9()(), ext::S::hey());
|
||||
let sext = ext::S(6);
|
||||
assert_eq!(t10()(&sext), <ext::S as ext::X>::hoy(&sext));
|
||||
assert_eq!(t9()(), ext::S::hey());
|
||||
let sext = ext::S(6);
|
||||
assert_eq!(t10()(&sext), <ext::S as ext::X>::hoy(&sext));
|
||||
|
||||
let p = parametric::<u8>;
|
||||
assert!(::std::mem::transmute::<_, *mut ()>(t11()) ==
|
||||
::std::mem::transmute::<_, *mut ()>(p));
|
||||
let p = parametric::<u8>;
|
||||
assert_eq!(t11() as *mut (), p as *mut ());
|
||||
|
||||
assert_eq!(t12(), C);
|
||||
assert_eq!(t13(), C2);
|
||||
assert_eq!(t13_2(), C3);
|
||||
assert_eq!(t12(), C);
|
||||
assert_eq!(t13(), C2);
|
||||
assert_eq!(t13_2(), C3);
|
||||
|
||||
assert_eq!(t14()(), <S as X>::hoy2());
|
||||
assert_eq!(t15()(&s), S::hey2(&s));
|
||||
assert_eq!(t16()(10u32, 20u32), F::f(10u32, 20u32));
|
||||
assert_eq!(t17()(30u32, 10u64), F::f(30u32, 10u64));
|
||||
assert_eq!(t18()(50u64, 5u64), F::f(50u64, 5u64));
|
||||
assert_eq!(t19()(322u64, 2u32), F::f(322u64, 2u32));
|
||||
assert_eq!(t20()(123u64, 38u32), <u32 as T<_, _>>::staticmeth(123, 38));
|
||||
assert_eq!(t21(), Unit);
|
||||
assert_eq!(t22(), None);
|
||||
assert_eq!(t23(), (CEnum::A, CEnum::B));
|
||||
assert_eq!(t24(), C4);
|
||||
}
|
||||
assert_eq!(t14()(), <S as X>::hoy2());
|
||||
assert_eq!(t15()(&s), S::hey2(&s));
|
||||
assert_eq!(t16()(10u32, 20u32), F::f(10u32, 20u32));
|
||||
assert_eq!(t17()(30u32, 10u64), F::f(30u32, 10u64));
|
||||
assert_eq!(t18()(50u64, 5u64), F::f(50u64, 5u64));
|
||||
assert_eq!(t19()(322u64, 2u32), F::f(322u64, 2u32));
|
||||
assert_eq!(t20()(123u64, 38u32), <u32 as T<_, _>>::staticmeth(123, 38));
|
||||
assert_eq!(t21(), Unit);
|
||||
assert_eq!(t22(), None);
|
||||
assert_eq!(t23(), (CEnum::A, CEnum::B));
|
||||
assert_eq!(t24(), C4);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,13 +24,14 @@
|
|||
use std::mem;
|
||||
|
||||
#[inline(never)]
|
||||
extern "C" fn foo<'a>(x: &'a isize) -> Option<&'a isize> { Some(x) }
|
||||
extern "C" fn foo(x: &isize) -> Option<&isize> { Some(x) }
|
||||
|
||||
static FOO: isize = 0xDEADBEE;
|
||||
|
||||
pub fn main() {
|
||||
unsafe {
|
||||
let f: for<'a> extern "C" fn(&'a isize) -> &'a isize = mem::transmute(foo);
|
||||
let f: extern "C" fn(&isize) -> &isize =
|
||||
mem::transmute(foo as extern "C" fn(&isize) -> Option<&isize>);
|
||||
assert_eq!(*f(&FOO), FOO);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@
|
|||
#![allow(unknown_features)]
|
||||
#![feature(box_syntax)]
|
||||
|
||||
use std::{option, mem};
|
||||
|
||||
// Iota-reduction is a rule in the Calculus of (Co-)Inductive Constructions,
|
||||
// which "says that a destructor applied to an object built from a constructor
|
||||
// behaves as expected". -- http://coq.inria.fr/doc/Reference-Manual006.html
|
||||
|
|
@ -43,9 +41,9 @@ macro_rules! check_option {
|
|||
check_option!($e, $T, |ptr| assert_eq!(*ptr, $e));
|
||||
}};
|
||||
($e:expr, $T:ty, |$v:ident| $chk:expr) => {{
|
||||
assert!(option::Option::None::<$T>.is_none());
|
||||
assert!(None::<$T>.is_none());
|
||||
let e = $e;
|
||||
let s_ = option::Option::Some::<$T>(e);
|
||||
let s_ = Some::<$T>(e);
|
||||
let $v = s_.as_ref().unwrap();
|
||||
$chk
|
||||
}}
|
||||
|
|
@ -78,9 +76,8 @@ pub fn main() {
|
|||
check_type!(&17, &isize);
|
||||
check_type!(box 18, Box<isize>);
|
||||
check_type!("foo".to_string(), String);
|
||||
check_type!(vec!(20, 22), Vec<isize> );
|
||||
let mint: usize = unsafe { mem::transmute(main) };
|
||||
check_type!(vec!(20, 22), Vec<isize>);
|
||||
check_type!(main, fn(), |pthing| {
|
||||
assert_eq!(mint, unsafe { mem::transmute(*pthing) })
|
||||
assert_eq!(main as fn(), *pthing as fn())
|
||||
});
|
||||
}
|
||||
|
|
|
|||
27
src/test/run-pass/transmute-from-fn-item-types.rs
Normal file
27
src/test/run-pass/transmute-from-fn-item-types.rs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// 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.
|
||||
|
||||
#![allow(transmute_from_fn_item_types)]
|
||||
|
||||
use std::mem;
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let u = mem::transmute(main);
|
||||
let p = mem::transmute(main);
|
||||
let f = mem::transmute(main);
|
||||
let tuple: (usize, *mut (), fn()) = (u, p, f);
|
||||
assert_eq!(mem::transmute::<_, [usize; 3]>(tuple), [main as usize; 3]);
|
||||
|
||||
mem::transmute::<_, usize>(main);
|
||||
mem::transmute::<_, *mut ()>(main);
|
||||
mem::transmute::<_, fn()>(main);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue