Rollup merge of #92150 - compiler-errors:better_usize_to_wide_ptr_cast, r=petrochenkov
Improve suggestion when casting usize to (possibly) wide pointer I thought #92125 was a wonderful idea, so I went ahead and took a stab at it. Not sure if my approach is the best going forward, but I'm happy with the improvement in the error message. Iwill definitely address any changes if people are more opinionated with the wordings or want more features. Also, do I need to add a new error code? (Fixes #92125)
This commit is contained in:
commit
7473750b13
5 changed files with 86 additions and 14 deletions
|
@ -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)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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…
Add table
Reference in a new issue