// Test to ensure that trait bounds are properly // checked on specializable associated types #![allow(incomplete_features)] #![feature(specialization)] trait UncheckedCopy: Sized { type Output: From + Copy + Into; } impl UncheckedCopy for T { default type Output = Self; //~^ ERROR: the trait bound `T: Copy` is not satisfied } fn unchecked_copy(other: &T::Output) -> T { (*other).into() } fn bug(origin: String) { // Turn the String into it's Output type... // Which we can just do by `.into()`, the assoc type states `From`. let origin_output = origin.into(); // Make a copy of String::Output, which is a String... let mut copy: String = unchecked_copy::(&origin_output); // Turn the Output type into a String again, // Which we can just do by `.into()`, the assoc type states `Into`. let mut origin: String = origin_output.into(); // assert both Strings use the same buffer. assert_eq!(copy.as_ptr(), origin.as_ptr()); // Any use of the copy we made becomes invalid, drop(origin); // OH NO! UB UB UB UB! copy.push_str(" world!"); println!("{}", copy); } fn main() { bug(String::from("hello")); }