Improve reference cast help message

This commit is contained in:
Guillaume Gomez 2016-10-24 14:52:14 +02:00
parent c11e2bda39
commit 37903bfcf6
6 changed files with 39 additions and 32 deletions

View File

@ -105,7 +105,6 @@ enum CastError {
NeedViaPtr, NeedViaPtr,
NeedViaThinPtr, NeedViaThinPtr,
NeedViaInt, NeedViaInt,
NeedViaUsize,
NonScalar, NonScalar,
} }
@ -139,26 +138,39 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) { fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
match e { match e {
CastError::NeedViaPtr |
CastError::NeedViaThinPtr | CastError::NeedViaThinPtr |
CastError::NeedViaInt | CastError::NeedViaPtr => {
CastError::NeedViaUsize => { let mut err = fcx.type_error_struct(self.span,
|actual| {
format!("casting `{}` as `{}` is invalid",
actual,
fcx.ty_to_string(self.cast_ty))
},
self.expr_ty);
if self.cast_ty.is_uint() {
err.help(&format!("cast through {} first",
match e {
CastError::NeedViaPtr => "a raw pointer",
CastError::NeedViaThinPtr => "a thin pointer",
_ => bug!(),
}));
}
err.emit();
}
CastError::NeedViaInt => {
fcx.type_error_struct(self.span, fcx.type_error_struct(self.span,
|actual| { |actual| {
format!("casting `{}` as `{}` is invalid", format!("casting `{}` as `{}` is invalid",
actual, actual,
fcx.ty_to_string(self.cast_ty)) fcx.ty_to_string(self.cast_ty))
}, },
self.expr_ty) self.expr_ty)
.help(&format!("cast through {} first", .help(&format!("cast through {} first",
match e { match e {
CastError::NeedViaPtr => "a raw pointer", CastError::NeedViaInt => "an integer",
CastError::NeedViaThinPtr => "a thin pointer", _ => bug!(),
CastError::NeedViaInt => "an integer", }))
CastError::NeedViaUsize => "a usize", .emit();
_ => bug!(),
}))
.emit();
} }
CastError::CastToBool => { CastError::CastToBool => {
struct_span_err!(fcx.tcx.sess, self.span, E0054, "cannot cast as `bool`") struct_span_err!(fcx.tcx.sess, self.span, E0054, "cannot cast as `bool`")
@ -366,21 +378,23 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
(Int(Bool), Float) | (Int(Bool), Float) |
(Int(CEnum), Float) | (Int(CEnum), Float) |
(Int(Char), Float) => Err(CastError::NeedViaInt), (Int(Char), Float) => Err(CastError::NeedViaInt),
(Int(Bool), Ptr(_)) | (Int(Bool), Ptr(_)) |
(Int(CEnum), Ptr(_)) | (Int(CEnum), Ptr(_)) |
(Int(Char), Ptr(_)) => Err(CastError::NeedViaUsize), (Int(Char), Ptr(_)) |
(Ptr(_), Float) |
(FnPtr, Float) |
(Float, Ptr(_)) => Err(CastError::IllegalCast),
// ptr -> * // ptr -> *
(Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast (Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast
(Ptr(m_expr), Int(_)) => self.check_ptr_addr_cast(fcx, m_expr), // ptr-addr-cast (Ptr(m_expr), Int(_)) => self.check_ptr_addr_cast(fcx, m_expr), // ptr-addr-cast
(Ptr(_), Float) | (FnPtr, Float) => Err(CastError::NeedViaUsize),
(FnPtr, Int(_)) => Ok(CastKind::FnPtrAddrCast), (FnPtr, Int(_)) => Ok(CastKind::FnPtrAddrCast),
(RPtr(_), Int(_)) | (RPtr(_), Int(_)) |
(RPtr(_), Float) => Err(CastError::NeedViaPtr), (RPtr(_), Float) => Err(CastError::NeedViaPtr),
// * -> ptr // * -> ptr
(Int(_), Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt), // addr-ptr-cast (Int(_), Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt), // addr-ptr-cast
(FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt), (FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt),
(Float, Ptr(_)) => Err(CastError::NeedViaUsize),
(RPtr(rmt), Ptr(mt)) => self.check_ref_cast(fcx, rmt, mt), // array-ptr-cast (RPtr(rmt), Ptr(mt)) => self.check_ref_cast(fcx, rmt, mt), // array-ptr-cast
// prim -> prim // prim -> prim
@ -391,7 +405,6 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
(Int(_), Int(_)) | (Int(_), Float) | (Float, Int(_)) | (Float, Float) => { (Int(_), Int(_)) | (Int(_), Float) | (Float, Int(_)) | (Float, Float) => {
Ok(CastKind::NumericCast) Ok(CastKind::NumericCast)
} }
} }
} }

View File

@ -48,16 +48,13 @@ fn main()
let _ = v as f32; let _ = v as f32;
//~^ ERROR casting //~^ ERROR casting
//~^^ HELP through a usize first
let _ = main as f64; let _ = main as f64;
//~^ ERROR casting //~^ ERROR casting
//~^^ HELP through a usize first
let _ = &v as usize; let _ = &v as usize;
//~^ ERROR casting //~^ ERROR casting
//~^^ HELP through a raw pointer first //~^^ HELP through a raw pointer first
let _ = f as *const u8; let _ = f as *const u8;
//~^ ERROR casting //~^ ERROR casting
//~^^ HELP through a usize first
let _ = 3_i32 as bool; let _ = 3_i32 as bool;
//~^ ERROR cannot cast as `bool` [E0054] //~^ ERROR cannot cast as `bool` [E0054]
//~| unsupported cast //~| unsupported cast
@ -80,13 +77,10 @@ fn main()
let _ = false as *const u8; let _ = false as *const u8;
//~^ ERROR casting //~^ ERROR casting
//~^^ HELP through a usize first
let _ = E::A as *const u8; let _ = E::A as *const u8;
//~^ ERROR casting //~^ ERROR casting
//~^^ HELP through a usize first
let _ = 'a' as *const u8; let _ = 'a' as *const u8;
//~^ ERROR casting //~^ ERROR casting
//~^^ HELP through a usize first
let _ = 42usize as *const [u8]; //~ ERROR casting let _ = 42usize as *const [u8]; //~ ERROR casting
let _ = v as *const [u8]; //~ ERROR cannot cast let _ = v as *const [u8]; //~ ERROR cannot cast

View File

@ -19,6 +19,9 @@ fn main() {
a as usize; //~ ERROR casting a as usize; //~ ERROR casting
//~^ HELP cast through a raw pointer first //~^ HELP cast through a raw pointer first
a as isize; //~ ERROR casting
a as i16; //~ ERROR casting `&[i32]` as `i16` is invalid
a as u32; //~ ERROR casting `&[i32]` as `u32` is invalid
b as usize; //~ ERROR non-scalar cast b as usize; //~ ERROR non-scalar cast
p as usize; p as usize;
//~^ ERROR casting //~^ ERROR casting

View File

@ -15,5 +15,4 @@ enum Test {
fn main() { fn main() {
let _x = Test::Foo as *const isize; let _x = Test::Foo as *const isize;
//~^ ERROR casting `Test` as `*const isize` is invalid //~^ ERROR casting `Test` as `*const isize` is invalid
//~^^ HELP cast through a usize first
} }

View File

@ -13,5 +13,4 @@ struct Inches(i32);
fn main() { fn main() {
Inches as f32; Inches as f32;
//~^ ERROR casting //~^ ERROR casting
//~^^ cast through a usize first
} }

View File

@ -12,5 +12,4 @@ fn main() {
let x : i16 = 22; let x : i16 = 22;
((&x) as *const i16) as f32; ((&x) as *const i16) as f32;
//~^ ERROR casting `*const i16` as `f32` is invalid //~^ ERROR casting `*const i16` as `f32` is invalid
//~^^ HELP cast through a usize first
} }