@@ -479,6 +479,46 @@ pub trait Into<T>: Sized {
479
479
/// - `From<T> for U` implies [`Into`]`<U> for T`
480
480
/// - `From` is reflexive, which means that `From<T> for T` is implemented
481
481
///
482
+ /// # When to implement `From`
483
+ ///
484
+ /// While there's no technical restrictions on which conversions can be done using
485
+ /// a `From` implementation, the general expectation is that the conversions
486
+ /// should typically be restricted as follows:
487
+ ///
488
+ /// * The conversion is *infallible*: if the conversion can fail, use [`TryFrom`]
489
+ /// instead; don't provide a `From` impl that panics.
490
+ ///
491
+ /// * The conversion is *lossless*: semantically, it should not lose or discard
492
+ /// information. For example, `i32: From<u16>` exists, where the original
493
+ /// value can be recovered using `u16: TryFrom<i32>`. And `String: From<&str>`
494
+ /// exists, where you can get something equivalent to the original value via
495
+ /// `Deref`. But `From` cannot be used to convert from `u32` to `u16`, since
496
+ /// that cannot succeed in a lossless way. (There's some wiggle room here for
497
+ /// information not considered semantically relevant. For example,
498
+ /// `Box<[T]>: From<Vec<T>>` exists even though it might not preserve capacity,
499
+ /// like how two vectors can be equal despite differing capacities.)
500
+ ///
501
+ /// * The conversion is *value-preserving*: the conceptual kind and meaning of
502
+ /// the resulting value is the same, even though the Rust type and technical
503
+ /// representation might be different. For example `-1_i8 as u8` is *lossless*,
504
+ /// since `as` casting back can recover the original value, but that conversion
505
+ /// is *not* available via `From` because `-1` and `255` are different conceptual
506
+ /// values (despite being identical bit patterns technically). But
507
+ /// `f32: From<i16>` *is* available because `1_i16` and `1.0_f32` are conceptually
508
+ /// the same real number (despite having very different bit patterns technically).
509
+ /// `String: From<char>` is available because they're both *text*, but
510
+ /// `String: From<u32>` is *not* available, since `1` (a number) and `"1"`
511
+ /// (text) are too different. (Converting values to text is instead covered
512
+ /// by the [`Display`](crate::fmt::Display) trait.)
513
+ ///
514
+ /// * The conversion is *obvious*: it's the only reasonable conversion between
515
+ /// the two types. Otherwise it's better to have it be a named method or
516
+ /// constructor, like how [`str::as_bytes`] is a method and how integers have
517
+ /// methods like [`u32::from_ne_bytes`], [`u32::from_le_bytes`], and
518
+ /// [`u32::from_be_bytes`], none of which are `From` implementations. Whereas
519
+ /// there's only one reasonable way to wrap an [`Ipv6Addr`](crate::net::Ipv6Addr)
520
+ /// into an [`IpAddr`](crate::net::IpAddr), thus `IpAddr: From<Ipv6Addr>` exists.
521
+ ///
482
522
/// # Examples
483
523
///
484
524
/// [`String`] implements `From<&str>`:
0 commit comments