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