// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#![cfg_attr(test, feature(negative_impls))]

//! # Object-Oriented Programming Support (OOPS).
//!
//! ## Upcasting
//!
//! To cast a reference to its base class type, use `my_reference.upcast()`.
//! For example:
//!
//! ```ignore
//! let x : &mut Derived = ...;
//! let y : Pin<&mut Base> = x.upcast();
//! ```
//!
//! Because base classes are always `!Unpin`, mutable references to base must
//! take the form of `Pin<&mut Base>`. See
//! docs/unpin.md
//!
//! To implement upcasting, implement the `Inherits` trait.
//!
//! ## Downcasting
//!
//! TODO(b/216195042): dynamic downcasting
//! TODO(b/216195042): static downcasting

use std::pin::Pin;

/// Upcast a reference or smart pointer. This operation cannot fail at runtime.
///
/// If `Derived` has a (public, unambiguous) base class `Base`, then:
///
/// ```ignore
/// &Derived : Upcast<&Base>
/// Pin<&mut Derived> : Upcast<Pin<&mut Base>>
/// ```
///
/// In addition, if `Derived : Unpin`, then `&mut Derived : Upcast<Pin<&mut
/// Base>>`.
///
/// (And, while it is not possible in Crubit bindings, if `Base` is also
/// `Unpin`, then  `&mut Derived : Upcast<&mut Base>`.)
///
/// For the purpose of `Upcast`, any type `T` is its own ("improper") base
/// class.
pub trait Upcast<Target> {
    fn upcast(self) -> Target;
}

/// Upcast `&` -> `&`.
impl<'a, Derived, Base> Upcast<&'a Base> for &'a Derived
where
    Derived: Inherits<Base>,
{
    fn upcast(self: &'a Derived) -> &'a Base {
        unsafe { &*Derived::upcast_ptr(self as *const Derived) }
    }
}

/// Upcast `Pin<&mut>` -> `Pin<&mut>.
impl<'a, Derived, Base> Upcast<Pin<&'a mut Base>> for Pin<&'a mut Derived>
where
    Derived: Inherits<Base>,
{
    fn upcast(self: Pin<&'a mut Derived>) -> Pin<&'a mut Base> {
        unsafe {
            let inner = Pin::into_inner_unchecked(self) as *mut Derived;
            Pin::new_unchecked(&mut *Derived::upcast_ptr_mut(inner))
        }
    }
}

/// Upcast `&mut` -> `Pin<&mut>.
///
/// Since all C++ base classes are `!Unpin`, this is the normal shape of a
/// mutable reference upcast for an `Unpin` derived class.
impl<'a, Derived, Base> Upcast<Pin<&'a mut Base>> for &'a mut Derived
where
    Pin<&'a mut Derived>: Upcast<Pin<&'a mut Base>>,
    Derived: Unpin,
{
    fn upcast(self: &'a mut Derived) -> Pin<&'a mut Base> {
        Pin::new(self).upcast()
    }
}

/// Upcast `&mut` -> `&mut`.
///
/// This impl is never applicable to C++ types (a C++ base class is `!Unpin`),
/// but could work for inheritance implemented in pure Rust.
impl<'a, Derived, Base> Upcast<&'a mut Base> for &'a mut Derived
where
    Pin<&'a mut Derived>: Upcast<Pin<&'a mut Base>>,
    Derived: Unpin,
    Base: Unpin,
{
    fn upcast(self: &'a mut Derived) -> &'a mut Base {
        Pin::into_inner(Pin::new(self).upcast())
    }
}

/// Unsafely upcast a raw pointer. `Derived : Inherits<Base>` means that
/// `Derived` can be upcast to `Base`.
///
/// To upcast in safe code, use the `Upcast` trait. `Inherits` is used for
/// unsafe pointer upcasts, and to implement upcasting.
///
/// (Note that unlike `Upcast`, `Inherits` is not implemented on the pointers
/// themselves -- this is solely for trait coherence reasons, as owning `T` does
/// not currently grant ownership over `*const T` or `*mut T`.)
///
/// ## Safety
///
/// Implementations must uphold the safety contract of the unsafe functions in
/// this trait.
///
/// TODO(jeanpierreda): Should this be split into two traits?
/// We could have `Inherits` (with safe functions) and `InheritsVirtual` (with
/// unsafe functions). For now, these are all merged into one trait, as it is
/// not an immediately obvious benefit to make raw pointer upcasts a safe
/// operation.
pub unsafe trait Inherits<Base> {
    /// Upcast a `const` pointer.
    ///
    /// ## Safety
    ///
    /// Casting follows the same safety and dereferencability rules as C++:
    ///
    /// If `derived` is a dereferencable pointer, then the upcasted pointer is a
    /// dereferencable pointer with the same lifetime.
    ///
    /// If `derived` is null, this returns null.
    ///
    /// If `derived` is non-dereferencable, and `Base` is a non-virtual base
    /// class, then the return value is non-dereferencable.
    ///
    /// Otherwise, if `derived` is non-dereferencable and `Base` is a virtual
    /// base class, the behavior is undefined.
    unsafe fn upcast_ptr(derived: *const Self) -> *const Base;

    /// Upcast a `mut` pointer.
    ///
    /// ## Safety
    ///
    /// Casting follows the same safety and dereferencability rules as C++:
    ///
    /// If `derived` is a dereferencable pointer, then the upcasted pointer is a
    /// dereferencable pointer with the same lifetime.
    ///
    /// If `derived` is null, this returns null.
    ///
    /// If `derived` is non-dereferencable, and `Base` is a non-virtual base
    /// class, then the return value is non-dereferencable.
    ///
    /// Otherwise, if `derived` is non-dereferencable and `Base` is a virtual
    /// base class, the behavior is undefined.
    unsafe fn upcast_ptr_mut(derived: *mut Self) -> *mut Base {
        Self::upcast_ptr(derived) as *mut _
    }
}

/// All classes are their own improper base.
unsafe impl<T> Inherits<T> for T {
    unsafe fn upcast_ptr(derived: *const Self) -> *const Self {
        derived
    }
}

#[cfg(test)]
mod test {
    use super::*;

    fn ptr_location<T: std::ops::Deref>(x: T) -> usize {
        &*x as *const _ as *const u8 as usize
    }

    #[test]
    fn test_unpin_upcast() {
        #[derive(Default)]
        struct Base(i32);

        #[derive(Default)]
        struct Derived {
            _other_field: u32,
            base: Base,
        }

        unsafe impl Inherits<Base> for Derived {
            unsafe fn upcast_ptr(derived: *const Self) -> *const Base {
                &(*derived).base
            }
        }
        let mut derived = Derived::default();
        assert_eq!(ptr_location(&derived.base), ptr_location::<&Base>((&derived).upcast()));

        let _: *const Base = unsafe { Derived::upcast_ptr(&derived) };
        let _: *mut Base = unsafe { Derived::upcast_ptr_mut(&mut derived) };
        let _: &mut Base = (&mut derived).upcast();
        let _: Pin<&mut Base> = (&mut derived).upcast();
        let _: Pin<&mut Base> = Pin::new(&mut derived).upcast();

        // This write must not be UB:
        {
            let base: &mut Base = (&mut derived).upcast();
            base.0 = 42;
        }
        assert_eq!(derived.base.0, 42);
    }

    #[test]
    fn test_nonunpin_upcast() {
        #[derive(Default)]
        struct Base(i32);
        impl !Unpin for Base {}

        #[derive(Default)]
        struct Derived {
            _other_field: u32,
            base: Base,
        }
        impl Unpin for Derived {}

        unsafe impl Inherits<Base> for Derived {
            unsafe fn upcast_ptr(derived: *const Self) -> *const Base {
                &(*derived).base
            }
        }
        let mut derived = Derived::default();
        assert_eq!(ptr_location(&derived.base), ptr_location::<&Base>((&derived).upcast()));

        let _: *const Base = unsafe { Derived::upcast_ptr(&derived) };
        let _: *mut Base = unsafe { Derived::upcast_ptr_mut(&mut derived) };
        // let _: &mut Base = (&mut derived).upcast(); // does not compile
        let _: Pin<&mut Base> = (&mut derived).upcast();
        let _: Pin<&mut Base> = Pin::new(&mut derived).upcast();

        // This write must not be UB:
        unsafe {
            let base: *mut Base = Derived::upcast_ptr_mut(&mut derived);

            (&mut *base).0 = 42;
        }
        assert_eq!(derived.base.0, 42);
    }
}
