]>
Commit | Line | Data |
---|---|---|
c34b1796 AL |
1 | // Copyright 2014 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 | //! Traits for conversions between types. | |
12 | //! | |
62682a34 SL |
13 | //! The traits in this module provide a general way to talk about conversions |
14 | //! from one type to another. They follow the standard Rust conventions of | |
15 | //! `as`/`into`/`from`. | |
9346a6ac | 16 | //! |
62682a34 SL |
17 | //! Like many traits, these are often used as bounds for generic functions, to |
18 | //! support arguments of multiple types. | |
9346a6ac | 19 | //! |
7453a54e SL |
20 | //! - Impl the `As*` traits for reference-to-reference conversions |
21 | //! - Impl the `Into` trait when you want to consume the value in the conversion | |
54a0048b | 22 | //! - The `From` trait is the most flexible, useful for value _and_ reference conversions |
a7813a04 XL |
23 | //! - The `TryFrom` and `TryInto` traits behave like `From` and `Into`, but allow for the |
24 | //! conversion to fail | |
7453a54e | 25 | //! |
a7813a04 XL |
26 | //! As a library author, you should prefer implementing `From<T>` or `TryFrom<T>` rather than |
27 | //! `Into<U>` or `TryInto<U>`, as `From` and `TryFrom` provide greater flexibility and offer | |
28 | //! equivalent `Into` or `TryInto` implementations for free, thanks to a blanket implementation | |
29 | //! in the standard library. | |
7453a54e SL |
30 | //! |
31 | //! # Generic impl | |
32 | //! | |
33 | //! - `AsRef` and `AsMut` auto-dereference if the inner type is a reference | |
34 | //! - `From<U> for T` implies `Into<T> for U` | |
a7813a04 | 35 | //! - `TryFrom<U> for T` implies `TryInto<T> for U` |
7453a54e SL |
36 | //! - `From` and `Into` are reflexive, which means that all types can `into()` |
37 | //! themselves and `from()` themselves | |
38 | //! | |
9346a6ac | 39 | //! See each trait for usage examples. |
c34b1796 AL |
40 | |
41 | #![stable(feature = "rust1", since = "1.0.0")] | |
42 | ||
c34b1796 | 43 | /// A cheap, reference-to-reference conversion. |
9346a6ac | 44 | /// |
9e0c209e | 45 | /// `AsRef` is very similar to, but different than, [`Borrow`]. See |
d9579d0f AL |
46 | /// [the book][book] for more. |
47 | /// | |
48 | /// [book]: ../../book/borrow-and-asref.html | |
9e0c209e | 49 | /// [`Borrow`]: ../../std/borrow/trait.Borrow.html |
d9579d0f | 50 | /// |
7453a54e | 51 | /// **Note: this trait must not fail**. If the conversion can fail, use a dedicated method which |
9e0c209e SL |
52 | /// returns an [`Option<T>`] or a [`Result<T, E>`]. |
53 | /// | |
54 | /// [`Option<T>`]: ../../std/option/enum.Option.html | |
55 | /// [`Result<T, E>`]: ../../std/result/enum.Result.html | |
7453a54e | 56 | /// |
9346a6ac AL |
57 | /// # Examples |
58 | /// | |
9e0c209e SL |
59 | /// Both [`String`] and `&str` implement `AsRef<str>`: |
60 | /// | |
61 | /// [`String`]: ../../std/string/struct.String.html | |
9346a6ac AL |
62 | /// |
63 | /// ``` | |
64 | /// fn is_hello<T: AsRef<str>>(s: T) { | |
65 | /// assert_eq!("hello", s.as_ref()); | |
66 | /// } | |
67 | /// | |
68 | /// let s = "hello"; | |
69 | /// is_hello(s); | |
70 | /// | |
71 | /// let s = "hello".to_string(); | |
72 | /// is_hello(s); | |
73 | /// ``` | |
7453a54e SL |
74 | /// |
75 | /// # Generic Impls | |
76 | /// | |
5bcae85e SL |
77 | /// - `AsRef` auto-dereferences if the inner type is a reference or a mutable |
78 | /// reference (e.g.: `foo.as_ref()` will work the same if `foo` has type `&mut Foo` or `&&mut Foo`) | |
7453a54e | 79 | /// |
c34b1796 AL |
80 | #[stable(feature = "rust1", since = "1.0.0")] |
81 | pub trait AsRef<T: ?Sized> { | |
9346a6ac | 82 | /// Performs the conversion. |
c34b1796 AL |
83 | #[stable(feature = "rust1", since = "1.0.0")] |
84 | fn as_ref(&self) -> &T; | |
85 | } | |
86 | ||
87 | /// A cheap, mutable reference-to-mutable reference conversion. | |
7453a54e SL |
88 | /// |
89 | /// **Note: this trait must not fail**. If the conversion can fail, use a dedicated method which | |
9e0c209e SL |
90 | /// returns an [`Option<T>`] or a [`Result<T, E>`]. |
91 | /// | |
92 | /// [`Option<T>`]: ../../std/option/enum.Option.html | |
93 | /// [`Result<T, E>`]: ../../std/result/enum.Result.html | |
94 | /// | |
95 | /// # Examples | |
96 | /// | |
97 | /// [`Box<T>`] implements `AsMut<T>`: | |
98 | /// | |
99 | /// [`Box<T>`]: ../../std/boxed/struct.Box.html | |
100 | /// | |
101 | /// ``` | |
102 | /// fn add_one<T: AsMut<u64>>(num: &mut T) { | |
103 | /// *num.as_mut() += 1; | |
104 | /// } | |
105 | /// | |
106 | /// let mut boxed_num = Box::new(0); | |
107 | /// add_one(&mut boxed_num); | |
108 | /// assert_eq!(*boxed_num, 1); | |
109 | /// ``` | |
7453a54e SL |
110 | /// |
111 | /// # Generic Impls | |
112 | /// | |
5bcae85e SL |
113 | /// - `AsMut` auto-dereferences if the inner type is a reference or a mutable |
114 | /// reference (e.g.: `foo.as_ref()` will work the same if `foo` has type `&mut Foo` or `&&mut Foo`) | |
7453a54e | 115 | /// |
c34b1796 AL |
116 | #[stable(feature = "rust1", since = "1.0.0")] |
117 | pub trait AsMut<T: ?Sized> { | |
9346a6ac | 118 | /// Performs the conversion. |
c34b1796 AL |
119 | #[stable(feature = "rust1", since = "1.0.0")] |
120 | fn as_mut(&mut self) -> &mut T; | |
121 | } | |
122 | ||
9346a6ac AL |
123 | /// A conversion that consumes `self`, which may or may not be expensive. |
124 | /// | |
9e0c209e SL |
125 | /// **Note: this trait must not fail**. If the conversion can fail, use [`TryInto`] or a dedicated |
126 | /// method which returns an [`Option<T>`] or a [`Result<T, E>`]. | |
7453a54e | 127 | /// |
54a0048b | 128 | /// Library authors should not directly implement this trait, but should prefer implementing |
9e0c209e | 129 | /// the [`From`][From] trait, which offers greater flexibility and provides an equivalent `Into` |
7453a54e SL |
130 | /// implementation for free, thanks to a blanket implementation in the standard library. |
131 | /// | |
9346a6ac AL |
132 | /// # Examples |
133 | /// | |
9e0c209e | 134 | /// [`String`] implements `Into<Vec<u8>>`: |
9346a6ac AL |
135 | /// |
136 | /// ``` | |
137 | /// fn is_hello<T: Into<Vec<u8>>>(s: T) { | |
138 | /// let bytes = b"hello".to_vec(); | |
139 | /// assert_eq!(bytes, s.into()); | |
140 | /// } | |
141 | /// | |
142 | /// let s = "hello".to_string(); | |
143 | /// is_hello(s); | |
144 | /// ``` | |
7453a54e SL |
145 | /// |
146 | /// # Generic Impls | |
147 | /// | |
9e0c209e SL |
148 | /// - `[From<T>][From] for U` implies `Into<U> for T` |
149 | /// - [`into()`] is reflexive, which means that `Into<T> for T` is implemented | |
7453a54e | 150 | /// |
9e0c209e SL |
151 | /// [`TryInto`]: trait.TryInto.html |
152 | /// [`Option<T>`]: ../../std/option/enum.Option.html | |
153 | /// [`Result<T, E>`]: ../../std/result/enum.Result.html | |
154 | /// [`String`]: ../../std/string/struct.String.html | |
155 | /// [From]: trait.From.html | |
156 | /// [`into()`]: trait.Into.html#tymethod.into | |
c34b1796 AL |
157 | #[stable(feature = "rust1", since = "1.0.0")] |
158 | pub trait Into<T>: Sized { | |
9346a6ac | 159 | /// Performs the conversion. |
c34b1796 AL |
160 | #[stable(feature = "rust1", since = "1.0.0")] |
161 | fn into(self) -> T; | |
162 | } | |
163 | ||
164 | /// Construct `Self` via a conversion. | |
9346a6ac | 165 | /// |
9e0c209e SL |
166 | /// **Note: this trait must not fail**. If the conversion can fail, use [`TryFrom`] or a dedicated |
167 | /// method which returns an [`Option<T>`] or a [`Result<T, E>`]. | |
7453a54e | 168 | /// |
9346a6ac AL |
169 | /// # Examples |
170 | /// | |
9e0c209e | 171 | /// [`String`] implements `From<&str>`: |
9346a6ac AL |
172 | /// |
173 | /// ``` | |
9346a6ac | 174 | /// let string = "hello".to_string(); |
bd371182 | 175 | /// let other_string = String::from("hello"); |
9346a6ac AL |
176 | /// |
177 | /// assert_eq!(string, other_string); | |
178 | /// ``` | |
7453a54e SL |
179 | /// # Generic impls |
180 | /// | |
9e0c209e SL |
181 | /// - `From<T> for U` implies `[Into<U>] for T` |
182 | /// - [`from()`] is reflexive, which means that `From<T> for T` is implemented | |
7453a54e | 183 | /// |
9e0c209e SL |
184 | /// [`TryFrom`]: trait.TryFrom.html |
185 | /// [`Option<T>`]: ../../std/option/enum.Option.html | |
186 | /// [`Result<T, E>`]: ../../std/result/enum.Result.html | |
187 | /// [`String`]: ../../std/string/struct.String.html | |
188 | /// [Into<U>]: trait.Into.html | |
189 | /// [`from()`]: trait.From.html#tymethod.from | |
c34b1796 | 190 | #[stable(feature = "rust1", since = "1.0.0")] |
b039eaaf | 191 | pub trait From<T>: Sized { |
9346a6ac | 192 | /// Performs the conversion. |
c34b1796 AL |
193 | #[stable(feature = "rust1", since = "1.0.0")] |
194 | fn from(T) -> Self; | |
195 | } | |
196 | ||
a7813a04 XL |
197 | /// An attempted conversion that consumes `self`, which may or may not be expensive. |
198 | /// | |
199 | /// Library authors should not directly implement this trait, but should prefer implementing | |
9e0c209e | 200 | /// the [`TryFrom`] trait, which offers greater flexibility and provides an equivalent `TryInto` |
a7813a04 | 201 | /// implementation for free, thanks to a blanket implementation in the standard library. |
9e0c209e SL |
202 | /// |
203 | /// [`TryFrom`]: trait.TryFrom.html | |
a7813a04 XL |
204 | #[unstable(feature = "try_from", issue = "33417")] |
205 | pub trait TryInto<T>: Sized { | |
206 | /// The type returned in the event of a conversion error. | |
207 | type Err; | |
208 | ||
209 | /// Performs the conversion. | |
210 | fn try_into(self) -> Result<T, Self::Err>; | |
211 | } | |
212 | ||
213 | /// Attempt to construct `Self` via a conversion. | |
214 | #[unstable(feature = "try_from", issue = "33417")] | |
215 | pub trait TryFrom<T>: Sized { | |
216 | /// The type returned in the event of a conversion error. | |
217 | type Err; | |
218 | ||
219 | /// Performs the conversion. | |
220 | fn try_from(T) -> Result<Self, Self::Err>; | |
221 | } | |
222 | ||
c34b1796 AL |
223 | //////////////////////////////////////////////////////////////////////////////// |
224 | // GENERIC IMPLS | |
225 | //////////////////////////////////////////////////////////////////////////////// | |
226 | ||
227 | // As lifts over & | |
228 | #[stable(feature = "rust1", since = "1.0.0")] | |
229 | impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a T where T: AsRef<U> { | |
230 | fn as_ref(&self) -> &U { | |
231 | <T as AsRef<U>>::as_ref(*self) | |
232 | } | |
233 | } | |
234 | ||
235 | // As lifts over &mut | |
236 | #[stable(feature = "rust1", since = "1.0.0")] | |
237 | impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a mut T where T: AsRef<U> { | |
238 | fn as_ref(&self) -> &U { | |
239 | <T as AsRef<U>>::as_ref(*self) | |
240 | } | |
241 | } | |
242 | ||
243 | // FIXME (#23442): replace the above impls for &/&mut with the following more general one: | |
244 | // // As lifts over Deref | |
245 | // impl<D: ?Sized + Deref, U: ?Sized> AsRef<U> for D where D::Target: AsRef<U> { | |
246 | // fn as_ref(&self) -> &U { | |
247 | // self.deref().as_ref() | |
248 | // } | |
249 | // } | |
250 | ||
251 | // AsMut lifts over &mut | |
252 | #[stable(feature = "rust1", since = "1.0.0")] | |
253 | impl<'a, T: ?Sized, U: ?Sized> AsMut<U> for &'a mut T where T: AsMut<U> { | |
254 | fn as_mut(&mut self) -> &mut U { | |
255 | (*self).as_mut() | |
256 | } | |
257 | } | |
258 | ||
259 | // FIXME (#23442): replace the above impl for &mut with the following more general one: | |
260 | // // AsMut lifts over DerefMut | |
261 | // impl<D: ?Sized + Deref, U: ?Sized> AsMut<U> for D where D::Target: AsMut<U> { | |
262 | // fn as_mut(&mut self) -> &mut U { | |
263 | // self.deref_mut().as_mut() | |
264 | // } | |
265 | // } | |
266 | ||
267 | // From implies Into | |
268 | #[stable(feature = "rust1", since = "1.0.0")] | |
269 | impl<T, U> Into<U> for T where U: From<T> { | |
270 | fn into(self) -> U { | |
271 | U::from(self) | |
272 | } | |
273 | } | |
274 | ||
275 | // From (and thus Into) is reflexive | |
276 | #[stable(feature = "rust1", since = "1.0.0")] | |
277 | impl<T> From<T> for T { | |
278 | fn from(t: T) -> T { t } | |
279 | } | |
280 | ||
a7813a04 XL |
281 | |
282 | // TryFrom implies TryInto | |
283 | #[unstable(feature = "try_from", issue = "33417")] | |
284 | impl<T, U> TryInto<U> for T where U: TryFrom<T> { | |
285 | type Err = U::Err; | |
286 | ||
287 | fn try_into(self) -> Result<U, U::Err> { | |
288 | U::try_from(self) | |
289 | } | |
290 | } | |
291 | ||
c34b1796 AL |
292 | //////////////////////////////////////////////////////////////////////////////// |
293 | // CONCRETE IMPLS | |
294 | //////////////////////////////////////////////////////////////////////////////// | |
295 | ||
296 | #[stable(feature = "rust1", since = "1.0.0")] | |
297 | impl<T> AsRef<[T]> for [T] { | |
298 | fn as_ref(&self) -> &[T] { | |
299 | self | |
300 | } | |
301 | } | |
302 | ||
303 | #[stable(feature = "rust1", since = "1.0.0")] | |
304 | impl<T> AsMut<[T]> for [T] { | |
305 | fn as_mut(&mut self) -> &mut [T] { | |
306 | self | |
307 | } | |
308 | } | |
309 | ||
310 | #[stable(feature = "rust1", since = "1.0.0")] | |
311 | impl AsRef<str> for str { | |
d9579d0f | 312 | #[inline] |
c34b1796 AL |
313 | fn as_ref(&self) -> &str { |
314 | self | |
315 | } | |
316 | } |