| //! Regression test for https://github.com/rust-lang/rust/issues/62211 |
| //! |
| //! The old implementation of defaults did not check whether the provided |
| //! default actually fulfills all bounds on the assoc. type, leading to |
| //! unsoundness, demonstrated here as a use-after-free. |
| //! |
| //! Note that the underlying cause of this is still not yet fixed. |
| //! See: https://github.com/rust-lang/rust/issues/33017 |
| |
| #![feature(associated_type_defaults)] |
| |
| use std::{ |
| fmt::Display, |
| ops::{AddAssign, Deref} |
| }; |
| |
| |
| trait UncheckedCopy: Sized { |
| // This Output is said to be Copy. Yet we default to Self |
| // and it's accepted, not knowing if Self ineed is Copy |
| type Output: Copy |
| //~^ ERROR the trait bound `Self: std::marker::Copy` is not satisfied |
| + Deref<Target = str> |
| //~^ ERROR the trait bound `Self: std::ops::Deref` is not satisfied |
| + AddAssign<&'static str> |
| //~^ ERROR cannot add-assign `&'static str` to `Self` |
| + From<Self> |
| + Display = Self; |
| //~^ ERROR `Self` doesn't implement `std::fmt::Display` |
| |
| // We said the Output type was Copy, so we can Copy it freely! |
| fn unchecked_copy(other: &Self::Output) -> Self::Output { |
| (*other) |
| } |
| |
| fn make_origin(s: Self) -> Self::Output { |
| s.into() |
| } |
| } |
| |
| impl<T> UncheckedCopy for T {} |
| //~^ ERROR `T` doesn't implement `std::fmt::Display` |
| //~| ERROR the trait bound `T: std::ops::Deref` is not satisfied |
| //~| ERROR cannot add-assign `&'static str` to `T` |
| //~| ERROR the trait bound `T: std::marker::Copy` is not satisfied |
| |
| fn bug<T: UncheckedCopy>(origin: T) { |
| let origin = T::make_origin(origin); |
| let mut copy = T::unchecked_copy(&origin); |
| |
| // assert we indeed have 2 strings pointing to the same buffer. |
| assert_eq!(origin.as_ptr(), copy.as_ptr()); |
| |
| // Drop the origin. Any use of `copy` is UB. |
| drop(origin); |
| |
| copy += "This is invalid!"; |
| println!("{}", copy); |
| } |
| |
| fn main() { |
| bug(String::from("hello!")); |
| } |