about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
authormarmeladema <xademax@gmail.com>2021-04-23 23:09:26 +0100
committermarmeladema <xademax@gmail.com>2021-04-23 23:09:26 +0100
commita657e17a7f4348bf95cbda8475cd2cc2507aea8e (patch)
treeb900d20ac82586b8b8edf74adf2ad8a674b5812f /src/test
parent9a352326112e4fd993e339cbd4eabae06d4979b9 (diff)
downloadrust-a657e17a7f4348bf95cbda8475cd2cc2507aea8e.tar.gz
rust-a657e17a7f4348bf95cbda8475cd2cc2507aea8e.zip
Add test for issue #33017
Diffstat (limited to 'src/test')
-rw-r--r--src/test/ui/specialization/issue-33017.rs45
-rw-r--r--src/test/ui/specialization/issue-33017.stderr17
2 files changed, 62 insertions, 0 deletions
diff --git a/src/test/ui/specialization/issue-33017.rs b/src/test/ui/specialization/issue-33017.rs
new file mode 100644
index 00000000000..4d19230df6b
--- /dev/null
+++ b/src/test/ui/specialization/issue-33017.rs
@@ -0,0 +1,45 @@
+// Test to ensure that trait bounds are propertly
+// checked on specializable associated types
+
+#![allow(incomplete_features)]
+#![feature(specialization)]
+
+trait UncheckedCopy: Sized {
+    type Output: From<Self> + Copy + Into<Self>;
+}
+
+impl<T> UncheckedCopy for T {
+    default type Output = Self;
+    //~^ ERROR: the trait bound `T: Copy` is not satisfied
+}
+
+fn unchecked_copy<T: UncheckedCopy>(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<Self>`.
+    let origin_output = origin.into();
+
+    // Make a copy of String::Output, which is a String...
+    let mut copy: String = unchecked_copy::<String>(&origin_output);
+
+    // Turn the Output type into a String again,
+    // Which we can just do by `.into()`, the assoc type states `Into<Self>`.
+    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"));
+}
diff --git a/src/test/ui/specialization/issue-33017.stderr b/src/test/ui/specialization/issue-33017.stderr
new file mode 100644
index 00000000000..bff4618d0be
--- /dev/null
+++ b/src/test/ui/specialization/issue-33017.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `T: Copy` is not satisfied
+  --> $DIR/issue-33017.rs:12:5
+   |
+LL |     type Output: From<Self> + Copy + Into<Self>;
+   |                               ---- required by this bound in `UncheckedCopy::Output`
+...
+LL |     default type Output = Self;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
+   |
+help: consider restricting type parameter `T`
+   |
+LL | impl<T: std::marker::Copy> UncheckedCopy for T {
+   |       ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.