unsize.rs - source
Description: Source of the Rust file `library/core/src/ops/unsize.rs`.

#
core/ops/
unsize.rs

    1use crate::marker::{PointeeSized, Unsize};
    2
    3/// Trait that indicates that this is a pointer or a wrapper for one,
    4/// where unsizing can be performed on the pointee.
    5///
    6/// See the [DST coercion RFC][dst-coerce] and [the nomicon entry on coercion][nomicon-coerce]
    7/// for more details.
    8///
    9/// For builtin pointer types, pointers to `T` will coerce to pointers to `U` if `T: Unsize<U>`
    10/// by converting from a thin pointer to a fat pointer.
    11///
    12/// For custom types, the coercion here works by coercing `Foo<T>` to `Foo<U>`
    13/// provided an impl of `CoerceUnsized<Foo<U>> for Foo<T>` exists.
    14/// Such an impl can only be written if `Foo<T>` has only a single non-phantomdata
    15/// field involving `T`. If the type of that field is `Bar<T>`, an implementation
    16/// of `CoerceUnsized<Bar<U>> for Bar<T>` must exist. The coercion will work by
    17/// coercing the `Bar<T>` field into `Bar<U>` and filling in the rest of the fields
    18/// from `Foo<T>` to create a `Foo<U>`. This will effectively drill down to a pointer
    19/// field and coerce that.
    20///
    21/// Generally, for smart pointers you will implement
    22/// `CoerceUnsized<Ptr<U>> for Ptr<T> where T: Unsize<U>, U: ?Sized`, with an
    23/// optional `?Sized` bound on `T` itself. For wrapper types that directly embed `T`
    24/// like `Cell<T>` and `RefCell<T>`, you
    25/// can directly implement `CoerceUnsized<Wrap<U>> for Wrap<T> where T: CoerceUnsized<U>`.
    26/// This will let coercions of types like `Cell<Box<T>>` work.
    27///
    28/// [`Unsize`][unsize] is used to mark types which can be coerced to DSTs if behind
    29/// pointers. It is implemented automatically by the compiler.
    30///
    31/// [dst-coerce]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md
    32/// [unsize]: crate::marker::Unsize
    33/// [nomicon-coerce]: ../../nomicon/coercions.html
    34#[unstable(feature = "coerce_unsized", issue = "18598")]
    35#[lang = "coerce_unsized"]
    36pub trait CoerceUnsized<T: PointeeSized> {
    37    // Empty.
    38}
    39
    40// &mut T -> &mut U
    41#[unstable(feature = "coerce_unsized", issue = "18598")]
    42impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<&'a mut U> for &'a mut T {}
    43// &mut T -> &U
    44#[unstable(feature = "coerce_unsized", issue = "18598")]
    45impl<'a, 'b: 'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<&'a U> for &'b mut T {}
    46// &mut T -> *mut U
    47#[unstable(feature = "coerce_unsized", issue = "18598")]
    48impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*mut U> for &'a mut T {}
    49// &mut T -> *const U
    50#[unstable(feature = "coerce_unsized", issue = "18598")]
    51impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*const U> for &'a mut T {}
    52
    53// &T -> &U
    54#[unstable(feature = "coerce_unsized", issue = "18598")]
    55impl<'a, 'b: 'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<&'a U> for &'b T {}
    56// &T -> *const U
    57#[unstable(feature = "coerce_unsized", issue = "18598")]
    58impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*const U> for &'a T {}
    59
    60// *mut T -> *mut U
    61#[unstable(feature = "coerce_unsized", issue = "18598")]
    62impl<T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*mut U> for *mut T {}
    63// *mut T -> *const U
    64#[unstable(feature = "coerce_unsized", issue = "18598")]
    65impl<T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*const U> for *mut T {}
    66
    67// *const T -> *const U
    68#[unstable(feature = "coerce_unsized", issue = "18598")]
    69impl<T: PointeeSized + Unsize<U>, U: PointeeSized> CoerceUnsized<*const U> for *const T {}
    70
    71/// `DispatchFromDyn` is used in the implementation of dyn-compatibility[^1] checks (specifically
    72/// allowing arbitrary self types), to guarantee that a method's receiver type can be dispatched on.
    73///
    74/// Note: `DispatchFromDyn` was briefly named `CoerceSized` (and had a slightly different
    75/// interpretation).
    76///
    77/// Imagine we have a trait object `t` with type `&dyn Tr`, where `Tr` is some trait with a method
    78/// `m` defined as `fn m(&self);`. When calling `t.m()`, the receiver `t` is a wide pointer, but an
    79/// implementation of `m` will expect a narrow pointer as `&self` (a reference to the concrete
    80/// type). The compiler must generate an implicit conversion from the trait object/wide pointer to
    81/// the concrete reference/narrow pointer. Implementing `DispatchFromDyn` indicates that that
    82/// conversion is allowed and thus that the type implementing `DispatchFromDyn` is safe to use as
    83/// the self type in an dyn-compatible method. (in the above example, the compiler will require
    84/// `DispatchFromDyn` is implemented for `&'a U`).
    85///
    86/// `DispatchFromDyn` does not specify the conversion from wide pointer to narrow pointer; the
    87/// conversion is hard-wired into the compiler. For the conversion to work, the following
    88/// properties must hold (i.e., it is only safe to implement `DispatchFromDyn` for types which have
    89/// these properties, these are also checked by the compiler):
    90///
    91/// * EITHER `Self` and `T` are either both references or both raw pointers; in either case, with
    92///   the same mutability.
    93/// * OR, all of the following hold
    94///   - `Self` and `T` must have the same type constructor, and only vary in a single type parameter
    95///     formal (the *coerced type*, e.g., `impl DispatchFromDyn<Rc<T>> for Rc<U>` is ok and the
    96///     single type parameter (instantiated with `T` or `U`) is the coerced type,
    97///     `impl DispatchFromDyn<Arc<T>> for Rc<U>` is not ok).
    98///   - The definition for `Self` must be a struct.
    99///   - The definition for `Self` must not be `#[repr(packed)]` or `#[repr(C)]`.
    100///   - Other than one-aligned, zero-sized fields, the definition for `Self` must have exactly one
    101///     field and that field's type must be the coerced type. Furthermore, `Self`'s field type must
    102///     implement `DispatchFromDyn<F>` where `F` is the type of `T`'s field type.
    103///
    104/// An example implementation of the trait:
    105///
    106/// ```
    107/// # #![feature(dispatch_from_dyn, unsize)]
    108/// # use std::{ops::DispatchFromDyn, marker::Unsize};
    109/// # struct Rc<T: ?Sized>(std::rc::Rc<T>);
    110/// impl<T: ?Sized, U: ?Sized> DispatchFromDyn<Rc<U>> for Rc<T>
    111/// where
    112///     T: Unsize<U>,
    113/// {}
    114/// ```
    115///
    116/// [^1]: Formerly known as *object safety*.
    117#[unstable(feature = "dispatch_from_dyn", issue = "none")]
    118#[lang = "dispatch_from_dyn"]
    119pub trait DispatchFromDyn<T> {
    120    // Empty.
    121}
    122
    123// &T -> &U
    124#[unstable(feature = "dispatch_from_dyn", issue = "none")]
    125impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<&'a U> for &'a T {}
    126// &mut T -> &mut U
    127#[unstable(feature = "dispatch_from_dyn", issue = "none")]
    128impl<'a, T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<&'a mut U> for &'a mut T {}
    129// *const T -> *const U
    130#[unstable(feature = "dispatch_from_dyn", issue = "none")]
    131impl<T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<*const U> for *const T {}
    132// *mut T -> *mut U
    133#[unstable(feature = "dispatch_from_dyn", issue = "none")]
    134impl<T: PointeeSized + Unsize<U>, U: PointeeSized> DispatchFromDyn<*mut U> for *mut T {}