]> git.lizzy.rs Git - rust.git/blob - src/libcore/kinds.rs
6489101f7b980d184ac187a88044f218b9138d1b
[rust.git] / src / libcore / kinds.rs
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 /*!
12 Primitive traits representing basic 'kinds' of types
13
14 Rust types can be classified in various useful ways according to
15 intrinsic properties of the type. These classifications, often called
16 'kinds', are represented as traits.
17
18 They cannot be implemented by user code, but are instead implemented
19 by the compiler automatically for the types to which they apply.
20
21 */
22
23 /// Types able to be transferred across task boundaries.
24 #[lang="send"]
25 pub trait Send for Sized? {
26     // empty.
27 }
28
29 /// Types with a constant size known at compile-time.
30 #[lang="sized"]
31 pub trait Sized for Sized? {
32     // Empty.
33 }
34
35 /// Types that can be copied by simply copying bits (i.e. `memcpy`).
36 #[lang="copy"]
37 pub trait Copy for Sized? {
38     // Empty.
39 }
40
41 /// Types that can be safely shared between tasks when aliased.
42 ///
43 /// The precise definition is: a type `T` is `Sync` if `&T` is
44 /// thread-safe. In other words, there is no possibility of data races
45 /// when passing `&T` references between tasks.
46 ///
47 /// As one would expect, primitive types like `u8` and `f64` are all
48 /// `Sync`, and so are simple aggregate types containing them (like
49 /// tuples, structs and enums). More instances of basic `Sync` types
50 /// include "immutable" types like `&T` and those with simple
51 /// inherited mutability, such as `Box<T>`, `Vec<T>` and most other
52 /// collection types. (Generic parameters need to be `Sync` for their
53 /// container to be `Sync`.)
54 ///
55 /// A somewhat surprising consequence of the definition is `&mut T` is
56 /// `Sync` (if `T` is `Sync`) even though it seems that it might
57 /// provide unsynchronised mutation. The trick is a mutable reference
58 /// stored in an aliasable reference (that is, `& &mut T`) becomes
59 /// read-only, as if it were a `& &T`, hence there is no risk of a data
60 /// race.
61 ///
62 /// Types that are not `Sync` are those that have "interior
63 /// mutability" in a non-thread-safe way, such as `Cell` and `RefCell`
64 /// in `std::cell`. These types allow for mutation of their contents
65 /// even when in an immutable, aliasable slot, e.g. the contents of
66 /// `&Cell<T>` can be `.set`, and do not ensure data races are
67 /// impossible, hence they cannot be `Sync`. A higher level example
68 /// of a non-`Sync` type is the reference counted pointer
69 /// `std::rc::Rc`, because any reference `&Rc<T>` can clone a new
70 /// reference, which modifies the reference counts in a non-atomic
71 /// way.
72 ///
73 /// For cases when one does need thread-safe interior mutability,
74 /// types like the atomics in `std::sync` and `Mutex` & `RWLock` in
75 /// the `sync` crate do ensure that any mutation cannot cause data
76 /// races.  Hence these types are `Sync`.
77 ///
78 /// Users writing their own types with interior mutability (or anything
79 /// else that is not thread-safe) should use the `NoSync` marker type
80 /// (from `std::kinds::marker`) to ensure that the compiler doesn't
81 /// consider the user-defined type to be `Sync`.  Any types with
82 /// interior mutability must also use the `std::cell::UnsafeCell` wrapper
83 /// around the value(s) which can be mutated when behind a `&`
84 /// reference; not doing this is undefined behaviour (for example,
85 /// `transmute`-ing from `&T` to `&mut T` is illegal).
86 #[lang="sync"]
87 pub trait Sync for Sized? {
88     // Empty
89 }
90
91 /// Marker types are special types that are used with unsafe code to
92 /// inform the compiler of special constraints. Marker types should
93 /// only be needed when you are creating an abstraction that is
94 /// implemented using unsafe code. In that case, you may want to embed
95 /// some of the marker types below into your type.
96 pub mod marker {
97     /// A marker type whose type parameter `T` is considered to be
98     /// covariant with respect to the type itself. This is (typically)
99     /// used to indicate that an instance of the type `T` is being stored
100     /// into memory and read from, even though that may not be apparent.
101     ///
102     /// For more information about variance, refer to this Wikipedia
103     /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
104     ///
105     /// *Note:* It is very unusual to have to add a covariant constraint.
106     /// If you are not sure, you probably want to use `InvariantType`.
107     ///
108     /// # Example
109     ///
110     /// Given a struct `S` that includes a type parameter `T`
111     /// but does not actually *reference* that type parameter:
112     ///
113     /// ```ignore
114     /// use std::mem;
115     ///
116     /// struct S<T> { x: *() }
117     /// fn get<T>(s: &S<T>) -> T {
118     ///    unsafe {
119     ///        let x: *T = mem::transmute(s.x);
120     ///        *x
121     ///    }
122     /// }
123     /// ```
124     ///
125     /// The type system would currently infer that the value of
126     /// the type parameter `T` is irrelevant, and hence a `S<int>` is
127     /// a subtype of `S<Box<int>>` (or, for that matter, `S<U>` for
128     /// any `U`). But this is incorrect because `get()` converts the
129     /// `*()` into a `*T` and reads from it. Therefore, we should include the
130     /// a marker field `CovariantType<T>` to inform the type checker that
131     /// `S<T>` is a subtype of `S<U>` if `T` is a subtype of `U`
132     /// (for example, `S<&'static int>` is a subtype of `S<&'a int>`
133     /// for some lifetime `'a`, but not the other way around).
134     #[lang="covariant_type"]
135     #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
136     pub struct CovariantType<T>;
137
138     /// A marker type whose type parameter `T` is considered to be
139     /// contravariant with respect to the type itself. This is (typically)
140     /// used to indicate that an instance of the type `T` will be consumed
141     /// (but not read from), even though that may not be apparent.
142     ///
143     /// For more information about variance, refer to this Wikipedia
144     /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
145     ///
146     /// *Note:* It is very unusual to have to add a contravariant constraint.
147     /// If you are not sure, you probably want to use `InvariantType`.
148     ///
149     /// # Example
150     ///
151     /// Given a struct `S` that includes a type parameter `T`
152     /// but does not actually *reference* that type parameter:
153     ///
154     /// ```
155     /// use std::mem;
156     ///
157     /// struct S<T> { x: *const () }
158     /// fn get<T>(s: &S<T>, v: T) {
159     ///    unsafe {
160     ///        let x: fn(T) = mem::transmute(s.x);
161     ///        x(v)
162     ///    }
163     /// }
164     /// ```
165     ///
166     /// The type system would currently infer that the value of
167     /// the type parameter `T` is irrelevant, and hence a `S<int>` is
168     /// a subtype of `S<Box<int>>` (or, for that matter, `S<U>` for
169     /// any `U`). But this is incorrect because `get()` converts the
170     /// `*()` into a `fn(T)` and then passes a value of type `T` to it.
171     ///
172     /// Supplying a `ContravariantType` marker would correct the
173     /// problem, because it would mark `S` so that `S<T>` is only a
174     /// subtype of `S<U>` if `U` is a subtype of `T`; given that the
175     /// function requires arguments of type `T`, it must also accept
176     /// arguments of type `U`, hence such a conversion is safe.
177     #[lang="contravariant_type"]
178     #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
179     pub struct ContravariantType<T>;
180
181     /// A marker type whose type parameter `T` is considered to be
182     /// invariant with respect to the type itself. This is (typically)
183     /// used to indicate that instances of the type `T` may be read or
184     /// written, even though that may not be apparent.
185     ///
186     /// For more information about variance, refer to this Wikipedia
187     /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
188     ///
189     /// # Example
190     ///
191     /// The Cell type is an example which uses unsafe code to achieve
192     /// "interior" mutability:
193     ///
194     /// ```
195     /// pub struct Cell<T> { value: T }
196     /// # fn main() {}
197     /// ```
198     ///
199     /// The type system would infer that `value` is only read here and
200     /// never written, but in fact `Cell` uses unsafe code to achieve
201     /// interior mutability.
202     #[lang="invariant_type"]
203     #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
204     pub struct InvariantType<T>;
205
206     /// As `CovariantType`, but for lifetime parameters. Using
207     /// `CovariantLifetime<'a>` indicates that it is ok to substitute
208     /// a *longer* lifetime for `'a` than the one you originally
209     /// started with (e.g., you could convert any lifetime `'foo` to
210     /// `'static`). You almost certainly want `ContravariantLifetime`
211     /// instead, or possibly `InvariantLifetime`. The only case where
212     /// it would be appropriate is that you have a (type-casted, and
213     /// hence hidden from the type system) function pointer with a
214     /// signature like `fn(&'a T)` (and no other uses of `'a`). In
215     /// this case, it is ok to substitute a larger lifetime for `'a`
216     /// (e.g., `fn(&'static T)`), because the function is only
217     /// becoming more selective in terms of what it accepts as
218     /// argument.
219     ///
220     /// For more information about variance, refer to this Wikipedia
221     /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
222     #[lang="covariant_lifetime"]
223     #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
224     pub struct CovariantLifetime<'a>;
225
226     /// As `ContravariantType`, but for lifetime parameters. Using
227     /// `ContravariantLifetime<'a>` indicates that it is ok to
228     /// substitute a *shorter* lifetime for `'a` than the one you
229     /// originally started with (e.g., you could convert `'static` to
230     /// any lifetime `'foo`). This is appropriate for cases where you
231     /// have an unsafe pointer that is actually a pointer into some
232     /// memory with lifetime `'a`, and thus you want to limit the
233     /// lifetime of your data structure to `'a`. An example of where
234     /// this is used is the iterator for vectors.
235     ///
236     /// For more information about variance, refer to this Wikipedia
237     /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
238     #[lang="contravariant_lifetime"]
239     #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
240     pub struct ContravariantLifetime<'a>;
241
242     /// As `InvariantType`, but for lifetime parameters. Using
243     /// `InvariantLifetime<'a>` indicates that it is not ok to
244     /// substitute any other lifetime for `'a` besides its original
245     /// value. This is appropriate for cases where you have an unsafe
246     /// pointer that is actually a pointer into memory with lifetime `'a`,
247     /// and this pointer is itself stored in an inherently mutable
248     /// location (such as a `Cell`).
249     #[lang="invariant_lifetime"]
250     #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
251     pub struct InvariantLifetime<'a>;
252
253     /// A type which is considered "not sendable", meaning that it cannot
254     /// be safely sent between tasks, even if it is owned. This is
255     /// typically embedded in other types, such as `Gc`, to ensure that
256     /// their instances remain thread-local.
257     #[lang="no_send_bound"]
258     #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
259     pub struct NoSend;
260
261     /// A type which is considered "not POD", meaning that it is not
262     /// implicitly copyable. This is typically embedded in other types to
263     /// ensure that they are never copied, even if they lack a destructor.
264     #[lang="no_copy_bound"]
265     #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
266     pub struct NoCopy;
267
268     /// A type which is considered "not sync", meaning that
269     /// its contents are not threadsafe, hence they cannot be
270     /// shared between tasks.
271     #[lang="no_sync_bound"]
272     #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
273     pub struct NoSync;
274
275     /// A type which is considered managed by the GC. This is typically
276     /// embedded in other types.
277     #[lang="managed_bound"]
278     #[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
279     pub struct Managed;
280 }