diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_typeck/src/check/cast.rs | 43 |
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)), } } |
