about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs8
-rw-r--r--library/std/src/thread/mod.rs2
-rw-r--r--tests/ui/unsized-locals/rust-call.rs12
-rw-r--r--tests/ui/unsized-locals/rust-call.stderr13
6 files changed, 41 insertions, 3 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index a269a7a1d8b..4554d167080 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1449,7 +1449,7 @@ fn check_fn_or_method<'tcx>(
         let span = tcx.def_span(def_id);
         let has_implicit_self = hir_decl.implicit_self != hir::ImplicitSelfKind::None;
         let mut inputs = sig.inputs().iter().skip(if has_implicit_self { 1 } else { 0 });
-        // Check that the argument is a tuple
+        // Check that the argument is a tuple and is sized
         if let Some(ty) = inputs.next() {
             wfcx.register_bound(
                 ObligationCause::new(span, wfcx.body_def_id, ObligationCauseCode::RustCall),
@@ -1457,6 +1457,12 @@ fn check_fn_or_method<'tcx>(
                 *ty,
                 tcx.require_lang_item(hir::LangItem::Tuple, Some(span)),
             );
+            wfcx.register_bound(
+                ObligationCause::new(span, wfcx.body_def_id, ObligationCauseCode::RustCall),
+                wfcx.param_env,
+                *ty,
+                tcx.require_lang_item(hir::LangItem::Sized, Some(span)),
+            );
         } else {
             tcx.sess.span_err(
                 hir_decl.inputs.last().map_or(span, |input| input.span),
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 4389ad6ef26..9da72aae776 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -470,6 +470,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     self.tcx.require_lang_item(hir::LangItem::Tuple, Some(sp)),
                     traits::ObligationCause::new(sp, self.body_id, traits::RustCall),
                 );
+                self.require_type_is_sized(ty, sp, traits::RustCall);
             } else {
                 self.tcx.sess.span_err(
                         sp,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index e73d917a8ae..5783383e93e 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -2663,9 +2663,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             | ObligationCauseCode::LetElse
             | ObligationCauseCode::BinOp { .. }
             | ObligationCauseCode::AscribeUserTypeProvePredicate(..)
-            | ObligationCauseCode::RustCall
             | ObligationCauseCode::DropImpl
             | ObligationCauseCode::ConstParam(_) => {}
+            ObligationCauseCode::RustCall => {
+                if let Some(pred) = predicate.to_opt_poly_trait_pred()
+                    && Some(pred.def_id()) == self.tcx.lang_items().sized_trait()
+                {
+                    err.note("argument required to be sized due to `extern \"rust-call\"` ABI");
+                }
+            }
             ObligationCauseCode::SliceOrArrayElem => {
                 err.note("slice and array elements must have `Sized` type");
             }
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index d9973185bc4..1230bb5deed 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -195,7 +195,7 @@ mod local;
 
 cfg_if::cfg_if! {
     if #[cfg(test)] {
-        // Avoid duplicating the global state assoicated with thread-locals between this crate and
+        // Avoid duplicating the global state associated with thread-locals between this crate and
         // realstd. Miri relies on this.
         pub use realstd::thread::{local_impl, AccessError, LocalKey};
     } else {
diff --git a/tests/ui/unsized-locals/rust-call.rs b/tests/ui/unsized-locals/rust-call.rs
new file mode 100644
index 00000000000..ff4075aa4c0
--- /dev/null
+++ b/tests/ui/unsized-locals/rust-call.rs
@@ -0,0 +1,12 @@
+#![feature(unsized_tuple_coercion)]
+#![feature(unboxed_closures)]
+#![feature(unsized_fn_params)]
+
+fn bad() -> extern "rust-call" fn(([u8],)) { todo!() }
+
+fn main() {
+    let f = bad();
+    let slice: Box<([u8],)> = Box::new(([1; 8],));
+    f(*slice);
+    //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
+}
diff --git a/tests/ui/unsized-locals/rust-call.stderr b/tests/ui/unsized-locals/rust-call.stderr
new file mode 100644
index 00000000000..fff7ef75b33
--- /dev/null
+++ b/tests/ui/unsized-locals/rust-call.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/rust-call.rs:10:7
+   |
+LL |     f(*slice);
+   |       ^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `([u8],)`, the trait `Sized` is not implemented for `[u8]`
+   = note: required because it appears within the type `([u8],)`
+   = note: argument required to be sized due to `extern "rust-call"` ABI
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.