better suggestion for int to wide ptr cast
This commit is contained in:
parent
458262b131
commit
814c18a6dc
@ -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 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError) {
|
||||
.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 @@ fn check_addr_ptr_cast(
|
||||
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)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,15 @@ fn main() {
|
||||
q as *const [i32]; //~ ERROR cannot cast
|
||||
|
||||
// #21397
|
||||
let t: *mut (dyn Trait + 'static) = 0 as *mut _; //~ ERROR casting
|
||||
let mut fail: *const str = 0 as *const str; //~ ERROR casting
|
||||
let t: *mut (dyn Trait + 'static) = 0 as *mut _;
|
||||
//~^ ERROR cannot cast `usize` to a pointer that is wide
|
||||
let mut fail: *const str = 0 as *const str;
|
||||
//~^ ERROR cannot cast `usize` to a pointer that is wide
|
||||
let mut fail2: *const str = 0isize as *const str;
|
||||
//~^ ERROR cannot cast `isize` to a pointer that is wide
|
||||
}
|
||||
|
||||
fn foo<T: ?Sized>() {
|
||||
let s = 0 as *const T;
|
||||
//~^ ERROR cannot cast `usize` to a pointer that may be wide
|
||||
}
|
||||
|
@ -50,19 +50,39 @@ error[E0607]: cannot cast thin pointer `*const i32` to fat pointer `*const [i32]
|
||||
LL | q as *const [i32];
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0606]: casting `usize` as `*mut (dyn Trait + 'static)` is invalid
|
||||
--> $DIR/fat-ptr-cast.rs:22:41
|
||||
error[E0606]: cannot cast `usize` to a pointer that is wide
|
||||
--> $DIR/fat-ptr-cast.rs:22:46
|
||||
|
|
||||
LL | let t: *mut (dyn Trait + 'static) = 0 as *mut _;
|
||||
| ^^^^^^^^^^^
|
||||
| - ^^^^^^ creating a `*mut (dyn Trait + 'static)` requires both an address and a vtable
|
||||
| |
|
||||
| consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts`
|
||||
|
||||
error[E0606]: casting `usize` as `*const str` is invalid
|
||||
--> $DIR/fat-ptr-cast.rs:23:32
|
||||
error[E0606]: cannot cast `usize` to a pointer that is wide
|
||||
--> $DIR/fat-ptr-cast.rs:24:37
|
||||
|
|
||||
LL | let mut fail: *const str = 0 as *const str;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
| - ^^^^^^^^^^ creating a `*const str` requires both an address and a length
|
||||
| |
|
||||
| consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts`
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
error[E0606]: cannot cast `isize` to a pointer that is wide
|
||||
--> $DIR/fat-ptr-cast.rs:26:43
|
||||
|
|
||||
LL | let mut fail2: *const str = 0isize as *const str;
|
||||
| ------ ^^^^^^^^^^ creating a `*const str` requires both an address and a length
|
||||
| |
|
||||
| consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts`
|
||||
|
||||
error[E0606]: cannot cast `usize` to a pointer that may be wide
|
||||
--> $DIR/fat-ptr-cast.rs:31:18
|
||||
|
|
||||
LL | let s = 0 as *const T;
|
||||
| - ^^^^^^^^ creating a `*const T` requires both an address and type-specific metadata
|
||||
| |
|
||||
| consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts`
|
||||
|
||||
error: aborting due to 11 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0605, E0606, E0607.
|
||||
For more information about an error, try `rustc --explain E0605`.
|
||||
|
@ -48,7 +48,7 @@ fn main()
|
||||
let _ = E::A as *const u8; //~ ERROR is invalid
|
||||
let _ = 'a' as *const u8; //~ ERROR is invalid
|
||||
|
||||
let _ = 42usize as *const [u8]; //~ ERROR is invalid
|
||||
let _ = 42usize as *const [u8]; //~ ERROR cannot cast `usize` to a pointer that is wide
|
||||
let _ = v as *const [u8]; //~ ERROR cannot cast
|
||||
let _ = fat_v as *const dyn Foo; //~ ERROR the size for values of type
|
||||
let _ = foo as *const str; //~ ERROR is invalid
|
||||
|
@ -148,11 +148,13 @@ error[E0606]: casting `char` as `*const u8` is invalid
|
||||
LL | let _ = 'a' as *const u8;
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0606]: casting `usize` as `*const [u8]` is invalid
|
||||
--> $DIR/cast-rfc0401.rs:51:13
|
||||
error[E0606]: cannot cast `usize` to a pointer that is wide
|
||||
--> $DIR/cast-rfc0401.rs:51:24
|
||||
|
|
||||
LL | let _ = 42usize as *const [u8];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
| ------- ^^^^^^^^^^^ creating a `*const [u8]` requires both an address and a length
|
||||
| |
|
||||
| consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts`
|
||||
|
||||
error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
|
||||
--> $DIR/cast-rfc0401.rs:52:13
|
||||
|
Loading…
Reference in New Issue
Block a user