--- /dev/null
+//! 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.
+
+// compile-fail
+
+#![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!"));
+}
--- /dev/null
+error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied
+ --> $DIR/defaults-unsound-62211-1.rs:20:18
+ |
+LL | type Output: Copy
+ | ^^^^ the trait `std::marker::Copy` is not implemented for `Self`
+ |
+ = help: consider adding a `where Self: std::marker::Copy` bound
+note: required by `UncheckedCopy`
+ --> $DIR/defaults-unsound-62211-1.rs:17:1
+ |
+LL | trait UncheckedCopy: Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: cannot add-assign `&'static str` to `Self`
+ --> $DIR/defaults-unsound-62211-1.rs:24:7
+ |
+LL | + AddAssign<&'static str>
+ | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str`
+ |
+ = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self`
+ = help: consider adding a `where Self: std::ops::AddAssign<&'static str>` bound
+note: required by `UncheckedCopy`
+ --> $DIR/defaults-unsound-62211-1.rs:17:1
+ |
+LL | trait UncheckedCopy: Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied
+ --> $DIR/defaults-unsound-62211-1.rs:22:7
+ |
+LL | + Deref<Target = str>
+ | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self`
+ |
+ = help: consider adding a `where Self: std::ops::Deref` bound
+note: required by `UncheckedCopy`
+ --> $DIR/defaults-unsound-62211-1.rs:17:1
+ |
+LL | trait UncheckedCopy: Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `Self` doesn't implement `std::fmt::Display`
+ --> $DIR/defaults-unsound-62211-1.rs:27:7
+ |
+LL | + Display = Self;
+ | ^^^^^^^ `Self` cannot be formatted with the default formatter
+ |
+ = help: the trait `std::fmt::Display` is not implemented for `Self`
+ = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+ = help: consider adding a `where Self: std::fmt::Display` bound
+note: required by `UncheckedCopy`
+ --> $DIR/defaults-unsound-62211-1.rs:17:1
+ |
+LL | trait UncheckedCopy: Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `T` doesn't implement `std::fmt::Display`
+ --> $DIR/defaults-unsound-62211-1.rs:40:9
+ |
+LL | impl<T> UncheckedCopy for T {}
+ | ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter
+ |
+ = help: the trait `std::fmt::Display` is not implemented for `T`
+ = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+ = help: consider adding a `where T: std::fmt::Display` bound
+
+error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied
+ --> $DIR/defaults-unsound-62211-1.rs:40:9
+ |
+LL | impl<T> UncheckedCopy for T {}
+ | ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T`
+ |
+ = help: consider adding a `where T: std::ops::Deref` bound
+
+error[E0277]: cannot add-assign `&'static str` to `T`
+ --> $DIR/defaults-unsound-62211-1.rs:40:9
+ |
+LL | impl<T> UncheckedCopy for T {}
+ | ^^^^^^^^^^^^^ no implementation for `T += &'static str`
+ |
+ = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `T`
+ = help: consider adding a `where T: std::ops::AddAssign<&'static str>` bound
+
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+ --> $DIR/defaults-unsound-62211-1.rs:40:9
+ |
+LL | impl<T> UncheckedCopy for T {}
+ | ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
+ |
+ = help: consider adding a `where T: std::marker::Copy` bound
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
--- /dev/null
+//! 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 and ICEs, the latter being demonstrated here.
+
+// compile-fail
+
+#![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(());
+}
--- /dev/null
+error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied
+ --> $DIR/defaults-unsound-62211-2.rs:20:18
+ |
+LL | type Output: Copy
+ | ^^^^ the trait `std::marker::Copy` is not implemented for `Self`
+ |
+ = help: consider adding a `where Self: std::marker::Copy` bound
+note: required by `UncheckedCopy`
+ --> $DIR/defaults-unsound-62211-2.rs:17:1
+ |
+LL | trait UncheckedCopy: Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: cannot add-assign `&'static str` to `Self`
+ --> $DIR/defaults-unsound-62211-2.rs:24:7
+ |
+LL | + AddAssign<&'static str>
+ | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str`
+ |
+ = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self`
+ = help: consider adding a `where Self: std::ops::AddAssign<&'static str>` bound
+note: required by `UncheckedCopy`
+ --> $DIR/defaults-unsound-62211-2.rs:17:1
+ |
+LL | trait UncheckedCopy: Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied
+ --> $DIR/defaults-unsound-62211-2.rs:22:7
+ |
+LL | + Deref<Target = str>
+ | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self`
+ |
+ = help: consider adding a `where Self: std::ops::Deref` bound
+note: required by `UncheckedCopy`
+ --> $DIR/defaults-unsound-62211-2.rs:17:1
+ |
+LL | trait UncheckedCopy: Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `Self` doesn't implement `std::fmt::Display`
+ --> $DIR/defaults-unsound-62211-2.rs:27:7
+ |
+LL | + Display = Self;
+ | ^^^^^^^ `Self` cannot be formatted with the default formatter
+ |
+ = help: the trait `std::fmt::Display` is not implemented for `Self`
+ = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+ = help: consider adding a `where Self: std::fmt::Display` bound
+note: required by `UncheckedCopy`
+ --> $DIR/defaults-unsound-62211-2.rs:17:1
+ |
+LL | trait UncheckedCopy: Sized {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `T` doesn't implement `std::fmt::Display`
+ --> $DIR/defaults-unsound-62211-2.rs:40:9
+ |
+LL | impl<T> UncheckedCopy for T {}
+ | ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter
+ |
+ = help: the trait `std::fmt::Display` is not implemented for `T`
+ = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+ = help: consider adding a `where T: std::fmt::Display` bound
+
+error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied
+ --> $DIR/defaults-unsound-62211-2.rs:40:9
+ |
+LL | impl<T> UncheckedCopy for T {}
+ | ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T`
+ |
+ = help: consider adding a `where T: std::ops::Deref` bound
+
+error[E0277]: cannot add-assign `&'static str` to `T`
+ --> $DIR/defaults-unsound-62211-2.rs:40:9
+ |
+LL | impl<T> UncheckedCopy for T {}
+ | ^^^^^^^^^^^^^ no implementation for `T += &'static str`
+ |
+ = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `T`
+ = help: consider adding a `where T: std::ops::AddAssign<&'static str>` bound
+
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+ --> $DIR/defaults-unsound-62211-2.rs:40:9
+ |
+LL | impl<T> UncheckedCopy for T {}
+ | ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
+ |
+ = help: consider adding a `where T: std::marker::Copy` bound
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0277`.