about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_typeck/src/check/cast.rs43
1 files changed, 42 insertions, 1 deletions
diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs
index 3d0f76f7a93..d3e9820834a 100644
--- a/compiler/rustc_typeck/src/check/cast.rs
+++ b/compiler/rustc_typeck/src/check/cast.rs
@@ -165,6 +165,12 @@ pub enum CastError {
     NonScalar,
     UnknownExprPtrKind,
     UnknownCastPtrKind,
+    /// Cast of int to (possibly) fat raw pointer.
+    ///
+    /// Argument is the specific name of the metadata in plain words, such as "a vtable"
+    /// or "a length". If this argument is None, then the metadata is unknown, for example,
+    /// when we're typechecking a type parameter with a ?Sized bound.
+    IntToFatCast(Option<&'static str>),
 }
 
 impl From<ErrorGuaranteed> for CastError {
@@ -522,6 +528,35 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                 .diagnostic()
                 .emit();
             }
+            CastError::IntToFatCast(known_metadata) => {
+                let mut err = struct_span_err!(
+                    fcx.tcx.sess,
+                    self.cast_span,
+                    E0606,
+                    "cannot cast `{}` to a pointer that {} wide",
+                    fcx.ty_to_string(self.expr_ty),
+                    if known_metadata.is_some() { "is" } else { "may be" }
+                );
+
+                err.span_label(
+                    self.cast_span,
+                    format!(
+                        "creating a `{}` requires both an address and {}",
+                        self.cast_ty,
+                        known_metadata.unwrap_or("type-specific metadata"),
+                    ),
+                );
+
+                if fcx.tcx.sess.is_nightly_build() {
+                    err.span_label(
+                        self.expr.span,
+                        "consider casting this expression to `*const ()`, \
+                        then using `core::ptr::from_raw_parts`",
+                    );
+                }
+
+                err.emit();
+            }
             CastError::UnknownCastPtrKind | CastError::UnknownExprPtrKind => {
                 let unknown_cast_to = match e {
                     CastError::UnknownCastPtrKind => true,
@@ -900,7 +935,13 @@ impl<'a, 'tcx> CastCheck<'tcx> {
         match fcx.pointer_kind(m_cast.ty, self.span)? {
             None => Err(CastError::UnknownCastPtrKind),
             Some(PointerKind::Thin) => Ok(CastKind::AddrPtrCast),
-            _ => Err(CastError::IllegalCast),
+            Some(PointerKind::Vtable(_)) => Err(CastError::IntToFatCast(Some("a vtable"))),
+            Some(PointerKind::Length) => Err(CastError::IntToFatCast(Some("a length"))),
+            Some(
+                PointerKind::OfProjection(_)
+                | PointerKind::OfOpaque(_, _)
+                | PointerKind::OfParam(_),
+            ) => Err(CastError::IntToFatCast(None)),
         }
     }