Skip to content

Commit 710f13f

Browse files
committed
Add Unsafe<T> type
1 parent b85d5f1 commit 710f13f

File tree

4 files changed

+88
-1
lines changed

4 files changed

+88
-1
lines changed

src/librustc/middle/lang_items.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,8 @@ lets_do_this! {
233233
ShrTraitLangItem, "shr", shr_trait;
234234
IndexTraitLangItem, "index", index_trait;
235235

236+
UnsafeTypeLangItem, "unsafe", unsafe_type;
237+
236238
DerefTraitLangItem, "deref", deref_trait;
237239
DerefMutTraitLangItem, "deref_mut", deref_mut_trait;
238240

src/librustc/middle/ty.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1878,7 +1878,8 @@ def_type_content_sets!(
18781878

18791879
// Things that are interior to the value (first nibble):
18801880
InteriorUnsized = 0b0000_0000__0000_0000__0001,
1881-
// InteriorAll = 0b0000_0000__0000_0000__1111,
1881+
InteriorUnsafe = 0b0000_0000__0000_0000__0010,
1882+
// InteriorAll = 0b00000000__00000000__1111,
18821883

18831884
// Things that are owned by the value (second and third nibbles):
18841885
OwnsOwned = 0b0000_0000__0000_0001__0000,
@@ -2297,6 +2298,8 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
22972298
tc | TC::OwnsAffine
22982299
} else if Some(did) == cx.lang_items.no_share_bound() {
22992300
tc | TC::ReachesNoShare
2301+
} else if Some(did) == cx.lang_items.unsafe_type() {
2302+
tc | TC::InteriorUnsafe
23002303
} else {
23012304
tc
23022305
}

src/libstd/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
#[cfg(test)] pub use kinds = realstd::kinds;
8484
#[cfg(test)] pub use ops = realstd::ops;
8585
#[cfg(test)] pub use cmp = realstd::cmp;
86+
#[cfg(test)] pub use ty = realstd::ty;
8687

8788
pub mod macros;
8889

@@ -138,6 +139,7 @@ pub mod gc;
138139
#[cfg(not(test))] pub mod kinds;
139140
#[cfg(not(test))] pub mod ops;
140141
#[cfg(not(test))] pub mod cmp;
142+
#[cfg(not(test))] pub mod ty;
141143

142144

143145
/* Common traits */
@@ -226,5 +228,6 @@ mod std {
226228
pub use rt;
227229
pub use str;
228230
pub use to_str;
231+
pub use ty;
229232
pub use unstable;
230233
}

src/libstd/ty.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright 2012-2013 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+
//! Types dealing with unsafe actions.
12+
13+
use cast;
14+
use kinds::marker;
15+
16+
/// Unsafe type that wraps a type T and indicates unsafe interior operations on the
17+
/// wrapped type. Types with an `Unsafe<T>` field are considered to have an *unsafe
18+
/// interior*. The Unsafe type is the only legal way to obtain aliasable data that is
19+
/// considered mutable. In general, transmuting an &T type into an &mut T is considered
20+
/// undefined behavior.
21+
///
22+
/// Although it is possible to put an Unsafe<T> into static item, it is not permitted to
23+
/// take the address of the static item if the item is not declared as mutable. This rule
24+
/// exists because immutable static items are stored in read-only memory, and thus any
25+
/// attempt to mutate their interior can cause segfaults. Immutable static items containing
26+
/// Unsafe<T> instances are still useful as read-only initializers, however, so we do not
27+
/// forbid them altogether.
28+
///
29+
/// Types like `Cell` and `RefCell` use this type to wrap their internal data.
30+
///
31+
/// Unsafe doesn't opt-out from any kind, instead, types with an `Unsafe` interior
32+
/// are expected to opt-out from kinds themselves.
33+
///
34+
/// # Example:
35+
///
36+
/// ```rust
37+
/// use std::ty::Unsafe;
38+
/// use std::kinds::marker;
39+
///
40+
/// struct NotThreadSafe<T> {
41+
/// value: Unsafe<T>,
42+
/// marker1: marker::NoShare
43+
/// }
44+
/// ```
45+
///
46+
/// **NOTE:** Unsafe<T> fields are public to allow static initializers. It is not recommended
47+
/// to access its fields directly, `get` should be used instead.
48+
#[cfg(not(stage0))]
49+
#[lang="unsafe"]
50+
pub struct Unsafe<T> {
51+
/// Wrapped value
52+
value: T,
53+
54+
/// Invariance marker
55+
marker1: marker::InvariantType<T>
56+
}
57+
58+
/// Unsafe type for stage0
59+
#[cfg(stage0)]
60+
pub struct Unsafe<T> {
61+
/// Wrapped value
62+
value: T,
63+
64+
/// Invariance marker
65+
marker1: marker::InvariantType<T>
66+
}
67+
68+
69+
impl<T> Unsafe<T> {
70+
71+
/// Static constructor
72+
pub fn new(value: T) -> Unsafe<T> {
73+
Unsafe{value: value, marker1: marker::InvariantType}
74+
}
75+
76+
/// Gets a mutable pointer to the wrapped value
77+
#[inline]
78+
pub unsafe fn get(&self) -> *mut T { cast::transmute(&self.value) }
79+
}

0 commit comments

Comments
 (0)