From 37903bfcf6dc15f9647b1a7f08af4757198fa189 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 24 Oct 2016 14:52:14 +0200 Subject: [PATCH] Improve reference cast help message --- src/librustc_typeck/check/cast.rs | 59 +++++++++++-------- src/test/compile-fail/cast-rfc0401.rs | 6 -- src/test/compile-fail/fat-ptr-cast.rs | 3 + src/test/compile-fail/issue-17444.rs | 1 - src/test/compile-fail/issue-21554.rs | 1 - .../typeck-cast-pointer-to-float.rs | 1 - 6 files changed, 39 insertions(+), 32 deletions(-) diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index c456b9358b3e2..4edf0011cb390 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -105,7 +105,6 @@ enum CastError { NeedViaPtr, NeedViaThinPtr, NeedViaInt, - NeedViaUsize, NonScalar, } @@ -139,26 +138,39 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) { match e { - CastError::NeedViaPtr | CastError::NeedViaThinPtr | - CastError::NeedViaInt | - CastError::NeedViaUsize => { + CastError::NeedViaPtr => { + 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, - |actual| { - format!("casting `{}` as `{}` is invalid", - actual, - fcx.ty_to_string(self.cast_ty)) - }, - self.expr_ty) - .help(&format!("cast through {} first", - match e { - CastError::NeedViaPtr => "a raw pointer", - CastError::NeedViaThinPtr => "a thin pointer", - CastError::NeedViaInt => "an integer", - CastError::NeedViaUsize => "a usize", - _ => bug!(), - })) - .emit(); + |actual| { + format!("casting `{}` as `{}` is invalid", + actual, + fcx.ty_to_string(self.cast_ty)) + }, + self.expr_ty) + .help(&format!("cast through {} first", + match e { + CastError::NeedViaInt => "an integer", + _ => bug!(), + })) + .emit(); } CastError::CastToBool => { 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(CEnum), Float) | (Int(Char), Float) => Err(CastError::NeedViaInt), + (Int(Bool), Ptr(_)) | (Int(CEnum), Ptr(_)) | - (Int(Char), Ptr(_)) => Err(CastError::NeedViaUsize), + (Int(Char), Ptr(_)) | + (Ptr(_), Float) | + (FnPtr, Float) | + (Float, Ptr(_)) => Err(CastError::IllegalCast), // ptr -> * (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(_), Float) | (FnPtr, Float) => Err(CastError::NeedViaUsize), (FnPtr, Int(_)) => Ok(CastKind::FnPtrAddrCast), (RPtr(_), Int(_)) | (RPtr(_), Float) => Err(CastError::NeedViaPtr), // * -> ptr (Int(_), Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt), // addr-ptr-cast (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 // prim -> prim @@ -391,7 +405,6 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { (Int(_), Int(_)) | (Int(_), Float) | (Float, Int(_)) | (Float, Float) => { Ok(CastKind::NumericCast) } - } } diff --git a/src/test/compile-fail/cast-rfc0401.rs b/src/test/compile-fail/cast-rfc0401.rs index 0c373057c76e0..1dbad9e30e3ad 100644 --- a/src/test/compile-fail/cast-rfc0401.rs +++ b/src/test/compile-fail/cast-rfc0401.rs @@ -48,16 +48,13 @@ fn main() let _ = v as f32; //~^ ERROR casting - //~^^ HELP through a usize first let _ = main as f64; //~^ ERROR casting - //~^^ HELP through a usize first let _ = &v as usize; //~^ ERROR casting //~^^ HELP through a raw pointer first let _ = f as *const u8; //~^ ERROR casting - //~^^ HELP through a usize first let _ = 3_i32 as bool; //~^ ERROR cannot cast as `bool` [E0054] //~| unsupported cast @@ -80,13 +77,10 @@ fn main() let _ = false as *const u8; //~^ ERROR casting - //~^^ HELP through a usize first let _ = E::A as *const u8; //~^ ERROR casting - //~^^ HELP through a usize first let _ = 'a' as *const u8; //~^ ERROR casting - //~^^ HELP through a usize first let _ = 42usize as *const [u8]; //~ ERROR casting let _ = v as *const [u8]; //~ ERROR cannot cast diff --git a/src/test/compile-fail/fat-ptr-cast.rs b/src/test/compile-fail/fat-ptr-cast.rs index b2fd11d4b39ea..c62987a5b900e 100644 --- a/src/test/compile-fail/fat-ptr-cast.rs +++ b/src/test/compile-fail/fat-ptr-cast.rs @@ -19,6 +19,9 @@ fn main() { a as usize; //~ ERROR casting //~^ 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 p as usize; //~^ ERROR casting diff --git a/src/test/compile-fail/issue-17444.rs b/src/test/compile-fail/issue-17444.rs index c1d5827eb90ce..dafcff238387e 100644 --- a/src/test/compile-fail/issue-17444.rs +++ b/src/test/compile-fail/issue-17444.rs @@ -15,5 +15,4 @@ enum Test { fn main() { let _x = Test::Foo as *const isize; //~^ ERROR casting `Test` as `*const isize` is invalid - //~^^ HELP cast through a usize first } diff --git a/src/test/compile-fail/issue-21554.rs b/src/test/compile-fail/issue-21554.rs index 741707a47b607..1b87862a056df 100644 --- a/src/test/compile-fail/issue-21554.rs +++ b/src/test/compile-fail/issue-21554.rs @@ -13,5 +13,4 @@ struct Inches(i32); fn main() { Inches as f32; //~^ ERROR casting - //~^^ cast through a usize first } diff --git a/src/test/compile-fail/typeck-cast-pointer-to-float.rs b/src/test/compile-fail/typeck-cast-pointer-to-float.rs index 2277b1bad776d..3f8b8f49cb306 100644 --- a/src/test/compile-fail/typeck-cast-pointer-to-float.rs +++ b/src/test/compile-fail/typeck-cast-pointer-to-float.rs @@ -12,5 +12,4 @@ fn main() { let x : i16 = 22; ((&x) as *const i16) as f32; //~^ ERROR casting `*const i16` as `f32` is invalid - //~^^ HELP cast through a usize first }