about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
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
-rw-r--r--src/test/ui/specialization/issue-51892.rs19
-rw-r--r--src/test/ui/specialization/issue-51892.stderr10
4 files changed, 91 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`.
diff --git a/src/test/ui/specialization/issue-51892.rs b/src/test/ui/specialization/issue-51892.rs
new file mode 100644
index 00000000000..3cd0711ae42
--- /dev/null
+++ b/src/test/ui/specialization/issue-51892.rs
@@ -0,0 +1,19 @@
+#![allow(incomplete_features)]
+#![feature(const_generics)]
+#![feature(const_evaluatable_checked)]
+#![feature(specialization)]
+
+pub trait Trait {
+    type Type;
+}
+
+impl<T: ?Sized> Trait for T {
+    default type Type = [u8; 1];
+}
+
+impl<T: Trait> Trait for *const T {
+    type Type = [u8; std::mem::size_of::<<T as Trait>::Type>()];
+    //~^ ERROR: unconstrained generic constant
+}
+
+fn main() {}
diff --git a/src/test/ui/specialization/issue-51892.stderr b/src/test/ui/specialization/issue-51892.stderr
new file mode 100644
index 00000000000..2d30164380a
--- /dev/null
+++ b/src/test/ui/specialization/issue-51892.stderr
@@ -0,0 +1,10 @@
+error: unconstrained generic constant
+  --> $DIR/issue-51892.rs:15:5
+   |
+LL |     type Type = [u8; std::mem::size_of::<<T as Trait>::Type>()];
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); std::mem::size_of::<<T as Trait>::Type>()]:`
+
+error: aborting due to previous error
+