]> git.lizzy.rs Git - rust.git/blob - src/test/ui/associated-types/defaults-unsound-62211-1.rs
Separate bounds and predicates for associated/opaque types
[rust.git] / src / test / ui / associated-types / defaults-unsound-62211-1.rs
1 //! Regression test for https://github.com/rust-lang/rust/issues/62211
2 //!
3 //! The old implementation of defaults did not check whether the provided
4 //! default actually fulfills all bounds on the assoc. type, leading to
5 //! unsoundness, demonstrated here as a use-after-free.
6 //!
7 //! Note that the underlying cause of this is still not yet fixed.
8 //! See: https://github.com/rust-lang/rust/issues/33017
9
10 #![feature(associated_type_defaults)]
11
12 use std::{
13     fmt::Display,
14     ops::{AddAssign, Deref},
15 };
16
17 trait UncheckedCopy: Sized {
18     // This Output is said to be Copy. Yet we default to Self
19     // and it's accepted, not knowing if Self ineed is Copy
20     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
21
22     // We said the Output type was Copy, so we can Copy it freely!
23     fn unchecked_copy(other: &Self::Output) -> Self::Output {
24         (*other)
25     }
26
27     fn make_origin(s: Self) -> Self::Output {
28         s.into()
29     }
30 }
31
32 impl<T> UncheckedCopy for T {}
33
34 fn bug<T: UncheckedCopy>(origin: T) {
35     let origin = T::make_origin(origin);
36     let mut copy = T::unchecked_copy(&origin);
37
38     // assert we indeed have 2 strings pointing to the same buffer.
39     assert_eq!(origin.as_ptr(), copy.as_ptr());
40
41     // Drop the origin. Any use of `copy` is UB.
42     drop(origin);
43
44     copy += "This is invalid!";
45     println!("{}", copy);
46 }
47
48 fn main() {
49     bug(String::from("hello!"));
50 }