about summary refs log tree commit diff
path: root/tests/ui
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ui')
-rw-r--r--tests/ui/c-variadic/not-dyn-compatible.rs35
-rw-r--r--tests/ui/c-variadic/not-dyn-compatible.stderr21
-rw-r--r--tests/ui/c-variadic/trait-method.rs67
-rw-r--r--tests/ui/c-variadic/trait-method.stderr14
-rw-r--r--tests/ui/feature-gates/feature-gate-c_variadic.rs1
-rw-r--r--tests/ui/feature-gates/feature-gate-c_variadic.stderr8
-rw-r--r--tests/ui/parser/variadic-ffi-semantic-restrictions.rs8
-rw-r--r--tests/ui/parser/variadic-ffi-semantic-restrictions.stderr16
8 files changed, 123 insertions, 47 deletions
diff --git a/tests/ui/c-variadic/not-dyn-compatible.rs b/tests/ui/c-variadic/not-dyn-compatible.rs
new file mode 100644
index 00000000000..b40a13e5847
--- /dev/null
+++ b/tests/ui/c-variadic/not-dyn-compatible.rs
@@ -0,0 +1,35 @@
+// Traits where a method is c-variadic are not dyn compatible.
+//
+// Creating a function pointer from a method on an `&dyn T` value creates a ReifyShim.
+// This shim cannot reliably forward C-variadic arguments. Thus the trait as a whole
+// is dyn-incompatible to prevent invalid shims from being created.
+#![feature(c_variadic)]
+
+#[repr(transparent)]
+struct Struct(u64);
+
+trait Trait {
+    fn get(&self) -> u64;
+
+    unsafe extern "C" fn dyn_method_ref(&self, mut ap: ...) -> u64 {
+        self.get() + unsafe { ap.arg::<u64>() }
+    }
+}
+
+impl Trait for Struct {
+    fn get(&self) -> u64 {
+        self.0
+    }
+}
+
+fn main() {
+    unsafe {
+        let dyn_object: &dyn Trait = &Struct(64);
+        //~^ ERROR the trait `Trait` is not dyn compatible
+        assert_eq!(dyn_object.dyn_method_ref(100), 164);
+        assert_eq!(
+            (Trait::dyn_method_ref as unsafe extern "C" fn(_, ...) -> u64)(dyn_object, 100),
+            164
+        );
+    }
+}
diff --git a/tests/ui/c-variadic/not-dyn-compatible.stderr b/tests/ui/c-variadic/not-dyn-compatible.stderr
new file mode 100644
index 00000000000..76630600c51
--- /dev/null
+++ b/tests/ui/c-variadic/not-dyn-compatible.stderr
@@ -0,0 +1,21 @@
+error[E0038]: the trait `Trait` is not dyn compatible
+  --> $DIR/not-dyn-compatible.rs:27:30
+   |
+LL |         let dyn_object: &dyn Trait = &Struct(64);
+   |                              ^^^^^ `Trait` is not dyn compatible
+   |
+note: for a trait to be dyn compatible it needs to allow building a vtable
+      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
+  --> $DIR/not-dyn-compatible.rs:14:26
+   |
+LL | trait Trait {
+   |       ----- this trait is not dyn compatible...
+...
+LL |     unsafe extern "C" fn dyn_method_ref(&self, mut ap: ...) -> u64 {
+   |                          ^^^^^^^^^^^^^^ ...because method `dyn_method_ref` is C-variadic
+   = help: consider moving `dyn_method_ref` to another trait
+   = help: only type `Struct` implements `Trait`; consider using it directly instead.
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/c-variadic/trait-method.rs b/tests/ui/c-variadic/trait-method.rs
index 4c468c1907b..97da0706a3a 100644
--- a/tests/ui/c-variadic/trait-method.rs
+++ b/tests/ui/c-variadic/trait-method.rs
@@ -1,40 +1,73 @@
-// For now C-variadic arguments in trait methods are rejected, though we aim to lift this
-// restriction in the future. In particular we need to think about the interaction with
-// `dyn Trait` and the `ReifyShim`s that it may generate for methods.
+//@ run-pass
 #![feature(c_variadic)]
-#![crate_type = "lib"]
-struct S;
 
-impl S {
+#[repr(transparent)]
+struct Struct(i32);
+
+impl Struct {
     unsafe extern "C" fn associated_function(mut ap: ...) -> i32 {
         unsafe { ap.arg() }
     }
 
     unsafe extern "C" fn method(&self, mut ap: ...) -> i32 {
-        unsafe { ap.arg() }
+        self.0 + unsafe { ap.arg::<i32>() }
     }
 }
 
-trait T {
+trait Trait: Sized {
+    fn get(&self) -> i32;
+
     unsafe extern "C" fn trait_associated_function(mut ap: ...) -> i32 {
-        //~^ ERROR: associated functions cannot have a C variable argument list
         unsafe { ap.arg() }
     }
 
-    unsafe extern "C" fn trait_method(&self, mut ap: ...) -> i32 {
-        //~^ ERROR: associated functions cannot have a C variable argument list
-        unsafe { ap.arg() }
+    unsafe extern "C" fn trait_method_owned(self, mut ap: ...) -> i32 {
+        self.get() + unsafe { ap.arg::<i32>() }
+    }
+
+    unsafe extern "C" fn trait_method_ref(&self, mut ap: ...) -> i32 {
+        self.get() + unsafe { ap.arg::<i32>() }
+    }
+
+    unsafe extern "C" fn trait_method_mut(&mut self, mut ap: ...) -> i32 {
+        self.get() + unsafe { ap.arg::<i32>() }
+    }
+
+    unsafe extern "C" fn trait_fat_pointer(self: Box<Self>, mut ap: ...) -> i32 {
+        self.get() + unsafe { ap.arg::<i32>() }
     }
 }
 
-impl T for S {}
+impl Trait for Struct {
+    fn get(&self) -> i32 {
+        self.0
+    }
+}
 
 fn main() {
     unsafe {
-        assert_eq!(S::associated_function(32), 32);
-        assert_eq!(S.method(32), 32);
+        assert_eq!(Struct::associated_function(32), 32);
+        assert_eq!(Struct(100).method(32), 132);
+
+        assert_eq!(Struct::trait_associated_function(32), 32);
+        assert_eq!(Struct(100).trait_method_owned(32), 132);
+        assert_eq!(Struct(100).trait_method_ref(32), 132);
+        assert_eq!(Struct(100).trait_method_mut(32), 132);
+        assert_eq!(Struct::trait_fat_pointer(Box::new(Struct(100)), 32), 132);
+
+        assert_eq!(<Struct as Trait>::trait_associated_function(32), 32);
+        assert_eq!(Trait::trait_method_owned(Struct(100), 32), 132);
+        assert_eq!(Trait::trait_method_ref(&Struct(100), 32), 132);
+        assert_eq!(Trait::trait_method_mut(&mut Struct(100), 32), 132);
+        assert_eq!(Trait::trait_fat_pointer(Box::new(Struct(100)), 32), 132);
+
+        type Associated = unsafe extern "C" fn(...) -> i32;
+        type Method<T> = unsafe extern "C" fn(T, ...) -> i32;
 
-        assert_eq!(S::trait_associated_function(32), 32);
-        assert_eq!(S.trait_method(32), 32);
+        assert_eq!((Struct::trait_associated_function as Associated)(32), 32);
+        assert_eq!((Struct::trait_method_owned as Method<_>)(Struct(100), 32), 132);
+        assert_eq!((Struct::trait_method_ref as Method<_>)(&Struct(100), 32), 132);
+        assert_eq!((Struct::trait_method_mut as Method<_>)(&mut Struct(100), 32), 132);
+        assert_eq!((Struct::trait_fat_pointer as Method<_>)(Box::new(Struct(100)), 32), 132);
     }
 }
diff --git a/tests/ui/c-variadic/trait-method.stderr b/tests/ui/c-variadic/trait-method.stderr
deleted file mode 100644
index 35f6e24ef71..00000000000
--- a/tests/ui/c-variadic/trait-method.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error: associated functions cannot have a C variable argument list
-  --> $DIR/trait-method.rs:19:52
-   |
-LL |     unsafe extern "C" fn trait_associated_function(mut ap: ...) -> i32 {
-   |                                                    ^^^^^^^^^^^
-
-error: associated functions cannot have a C variable argument list
-  --> $DIR/trait-method.rs:24:46
-   |
-LL |     unsafe extern "C" fn trait_method(&self, mut ap: ...) -> i32 {
-   |                                              ^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
diff --git a/tests/ui/feature-gates/feature-gate-c_variadic.rs b/tests/ui/feature-gates/feature-gate-c_variadic.rs
index 88d91dbd081..649816b48d7 100644
--- a/tests/ui/feature-gates/feature-gate-c_variadic.rs
+++ b/tests/ui/feature-gates/feature-gate-c_variadic.rs
@@ -6,5 +6,4 @@ pub unsafe extern "C" fn test(_: i32, ap: ...) {}
 trait Trait {
     unsafe extern "C" fn trait_test(_: i32, ap: ...) {}
     //~^ ERROR C-variadic functions are unstable
-    //~| ERROR associated functions cannot have a C variable argument list
 }
diff --git a/tests/ui/feature-gates/feature-gate-c_variadic.stderr b/tests/ui/feature-gates/feature-gate-c_variadic.stderr
index 808aa20948d..ae880093b98 100644
--- a/tests/ui/feature-gates/feature-gate-c_variadic.stderr
+++ b/tests/ui/feature-gates/feature-gate-c_variadic.stderr
@@ -1,9 +1,3 @@
-error: associated functions cannot have a C variable argument list
-  --> $DIR/feature-gate-c_variadic.rs:7:45
-   |
-LL |     unsafe extern "C" fn trait_test(_: i32, ap: ...) {}
-   |                                             ^^^^^^^
-
 error[E0658]: C-variadic functions are unstable
   --> $DIR/feature-gate-c_variadic.rs:3:1
    |
@@ -24,6 +18,6 @@ LL |     unsafe extern "C" fn trait_test(_: i32, ap: ...) {}
    = help: add `#![feature(c_variadic)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs
index 566c4d30245..415472176d9 100644
--- a/tests/ui/parser/variadic-ffi-semantic-restrictions.rs
+++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.rs
@@ -70,13 +70,13 @@ impl X {
 
 trait T {
     fn t_f1(x: isize, ...) {}
-    //~^ ERROR associated functions cannot have a C variable argument list
+    //~^ ERROR `...` is not supported for non-extern functions
     fn t_f2(x: isize, ...);
-    //~^ ERROR associated functions cannot have a C variable argument list
+    //~^ ERROR `...` is not supported for non-extern functions
     fn t_f3(...) {}
-    //~^ ERROR associated functions cannot have a C variable argument list
+    //~^ ERROR `...` is not supported for non-extern functions
     fn t_f4(...);
-    //~^ ERROR associated functions cannot have a C variable argument list
+    //~^ ERROR `...` is not supported for non-extern functions
     fn t_f5(..., x: isize) {}
     //~^ ERROR `...` must be the last argument of a C-variadic function
     fn t_f6(..., x: isize);
diff --git a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr
index c18d857d14e..da9c9b0f760 100644
--- a/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr
+++ b/tests/ui/parser/variadic-ffi-semantic-restrictions.stderr
@@ -192,29 +192,37 @@ LL |     const fn i_f5(x: isize, ...) {}
    |
    = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
 
-error: associated functions cannot have a C variable argument list
+error: `...` is not supported for non-extern functions
   --> $DIR/variadic-ffi-semantic-restrictions.rs:72:23
    |
 LL |     fn t_f1(x: isize, ...) {}
    |                       ^^^
+   |
+   = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
 
-error: associated functions cannot have a C variable argument list
+error: `...` is not supported for non-extern functions
   --> $DIR/variadic-ffi-semantic-restrictions.rs:74:23
    |
 LL |     fn t_f2(x: isize, ...);
    |                       ^^^
+   |
+   = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
 
-error: associated functions cannot have a C variable argument list
+error: `...` is not supported for non-extern functions
   --> $DIR/variadic-ffi-semantic-restrictions.rs:76:13
    |
 LL |     fn t_f3(...) {}
    |             ^^^
+   |
+   = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
 
-error: associated functions cannot have a C variable argument list
+error: `...` is not supported for non-extern functions
   --> $DIR/variadic-ffi-semantic-restrictions.rs:78:13
    |
 LL |     fn t_f4(...);
    |             ^^^
+   |
+   = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list
 
 error: `...` must be the last argument of a C-variadic function
   --> $DIR/variadic-ffi-semantic-restrictions.rs:80:13