]> git.proxmox.com Git - rustc.git/blame - src/libcore/cast.rs
Imported Upstream version 0.6
[rustc.git] / src / libcore / cast.rs
CommitLineData
223e47cc
LB
1// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11//! Unsafe casting functions
12
13pub mod rusti {
14 #[abi = "rust-intrinsic"]
15 #[link_name = "rusti"]
16 pub extern "rust-intrinsic" {
17 fn forget<T>(+x: T);
18 fn reinterpret_cast<T, U>(&&e: T) -> U;
19 }
20}
21
22/// Casts the value at `src` to U. The two types must have the same length.
23#[inline(always)]
24pub unsafe fn reinterpret_cast<T, U>(src: &T) -> U {
25 rusti::reinterpret_cast(*src)
26}
27
28/**
29 * Move a thing into the void
30 *
31 * The forget function will take ownership of the provided value but neglect
32 * to run any required cleanup or memory-management operations on it. This
33 * can be used for various acts of magick, particularly when using
34 * reinterpret_cast on pointer types.
35 */
36#[inline(always)]
37pub unsafe fn forget<T>(thing: T) { rusti::forget(thing); }
38
39/**
40 * Force-increment the reference count on a shared box. If used
41 * carelessly, this can leak the box. Use this in conjunction with transmute
42 * and/or reinterpret_cast when such calls would otherwise scramble a box's
43 * reference count
44 */
45pub unsafe fn bump_box_refcount<T>(t: @T) { forget(t); }
46
47/**
48 * Transform a value of one type into a value of another type.
49 * Both types must have the same size and alignment.
50 *
51 * # Example
52 *
53 * assert!(transmute("L") == ~[76u8, 0u8]);
54 */
55#[inline(always)]
56pub unsafe fn transmute<L, G>(thing: L) -> G {
57 let newthing: G = reinterpret_cast(&thing);
58 forget(thing);
59 newthing
60}
61
62/// Coerce an immutable reference to be mutable.
63#[inline(always)]
64pub unsafe fn transmute_mut<'a,T>(ptr: &'a T) -> &'a mut T { transmute(ptr) }
65
66/// Coerce a mutable reference to be immutable.
67#[inline(always)]
68pub unsafe fn transmute_immut<'a,T>(ptr: &'a mut T) -> &'a T {
69 transmute(ptr)
70}
71
72/// Coerce a borrowed pointer to have an arbitrary associated region.
73#[inline(always)]
74pub unsafe fn transmute_region<'a,'b,T>(ptr: &'a T) -> &'b T {
75 transmute(ptr)
76}
77
78/// Coerce an immutable reference to be mutable.
79#[inline(always)]
80pub unsafe fn transmute_mut_unsafe<T>(ptr: *const T) -> *mut T {
81 transmute(ptr)
82}
83
84/// Coerce an immutable reference to be mutable.
85#[inline(always)]
86pub unsafe fn transmute_immut_unsafe<T>(ptr: *const T) -> *T {
87 transmute(ptr)
88}
89
90/// Coerce a borrowed mutable pointer to have an arbitrary associated region.
91#[inline(always)]
92pub unsafe fn transmute_mut_region<'a,'b,T>(ptr: &'a mut T) -> &'b mut T {
93 transmute(ptr)
94}
95
96/// Transforms lifetime of the second pointer to match the first.
97#[inline(always)]
98pub unsafe fn copy_lifetime<'a,S,T>(_ptr: &'a S, ptr: &T) -> &'a T {
99 transmute_region(ptr)
100}
101
102/// Transforms lifetime of the second pointer to match the first.
103#[inline(always)]
104pub unsafe fn copy_lifetime_vec<'a,S,T>(_ptr: &'a [S], ptr: &T) -> &'a T {
105 transmute_region(ptr)
106}
107
108
109/****************************************************************************
110 * Tests
111 ****************************************************************************/
112
113#[cfg(test)]
114pub mod tests {
115 use cast::{bump_box_refcount, reinterpret_cast, transmute};
116
117 #[test]
118 pub fn test_reinterpret_cast() {
119 assert!(1u == unsafe { reinterpret_cast(&1) });
120 }
121
122 #[test]
123 pub fn test_bump_box_refcount() {
124 unsafe {
125 let box = @~"box box box"; // refcount 1
126 bump_box_refcount(box); // refcount 2
127 let ptr: *int = transmute(box); // refcount 2
128 let _box1: @~str = reinterpret_cast(&ptr);
129 let _box2: @~str = reinterpret_cast(&ptr);
130 assert!(*_box1 == ~"box box box");
131 assert!(*_box2 == ~"box box box");
132 // Will destroy _box1 and _box2. Without the bump, this would
133 // use-after-free. With too many bumps, it would leak.
134 }
135 }
136
137 #[test]
138 pub fn test_transmute() {
139 use managed::raw::BoxRepr;
140 unsafe {
141 let x = @100u8;
142 let x: *BoxRepr = transmute(x);
143 assert!((*x).data == 100);
144 let _x: @int = transmute(x);
145 }
146 }
147
148 #[test]
149 pub fn test_transmute2() {
150 unsafe {
151 assert!(~[76u8, 0u8] == transmute(~"L"));
152 }
153 }
154}