Improve typeck diagnostic messages

Mostly by splitting error messages into proper pairs of errors and helps
This commit is contained in:
Simonas Kazlauskas 2015-07-27 03:31:38 +03:00
parent 77e9228b4a
commit ffcdf0881b
13 changed files with 102 additions and 57 deletions

View File

@ -122,20 +122,21 @@ impl<'tcx> CastCheck<'tcx> {
CastError::NeedViaInt |
CastError::NeedViaUsize => {
fcx.type_error_message(self.span, |actual| {
format!("illegal cast; cast through {} first: `{}` as `{}`",
match e {
CastError::NeedViaPtr => "a raw pointer",
CastError::NeedViaInt => "an integer",
CastError::NeedViaUsize => "a usize",
_ => unreachable!()
},
format!("casting `{}` as `{}` is invalid",
actual,
fcx.infcx().ty_to_string(self.cast_ty))
}, self.expr_ty, None)
}, self.expr_ty, None);
fcx.ccx.tcx.sess.fileline_help(self.span,
&format!("cast through {} first", match e {
CastError::NeedViaPtr => "a raw pointer",
CastError::NeedViaInt => "an integer",
CastError::NeedViaUsize => "a usize",
_ => unreachable!()
}));
}
CastError::CastToBool => {
span_err!(fcx.tcx().sess, self.span, E0054,
"cannot cast as `bool`, compare with zero instead");
span_err!(fcx.tcx().sess, self.span, E0054, "cannot cast as `bool`");
fcx.ccx.tcx.sess.fileline_help(self.span, "compare with zero instead");
}
CastError::CastToChar => {
fcx.type_error_message(self.span, |actual| {
@ -151,17 +152,18 @@ impl<'tcx> CastCheck<'tcx> {
}
CastError::IllegalCast => {
fcx.type_error_message(self.span, |actual| {
format!("illegal cast: `{}` as `{}`",
format!("casting `{}` as `{}` is invalid",
actual,
fcx.infcx().ty_to_string(self.cast_ty))
}, self.expr_ty, None);
}
CastError::DifferingKinds => {
fcx.type_error_message(self.span, |actual| {
format!("illegal cast: `{}` as `{}`; vtable kinds may not match",
format!("casting `{}` as `{}` is invalid",
actual,
fcx.infcx().ty_to_string(self.cast_ty))
}, self.expr_ty, None);
fcx.ccx.tcx.sess.fileline_note(self.span, "vtable kinds may not match");
}
}
}
@ -285,7 +287,7 @@ impl<'tcx> CastCheck<'tcx> {
return Ok(CastKind::PtrPtrCast);
}
// sized -> unsized? report illegal cast (don't complain about vtable kinds)
// sized -> unsized? report invalid cast (don't complain about vtable kinds)
if fcx.type_is_known_to_be_sized(m_expr.ty, self.span) {
return Err(CastError::IllegalCast);
}

View File

@ -8,5 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern: cannot cast as `bool`, compare with zero instead
fn main() { let u = (5 as bool); }
fn main() {
let u = (5 as bool);
//~^ ERROR cannot cast as `bool`
//~^^ HELP compare with zero instead
}

View File

@ -10,12 +10,16 @@
fn illegal_cast<U:?Sized,V:?Sized>(u: *const U) -> *const V
{
u as *const V //~ ERROR vtable kinds
u as *const V
//~^ ERROR casting
//~^^ NOTE vtable kinds
}
fn illegal_cast_2<U:?Sized>(u: *const U) -> *const str
{
u as *const str //~ ERROR vtable kinds
u as *const str
//~^ ERROR casting
//~^^ NOTE vtable kinds
}
trait Foo { fn foo(&self) {} }
@ -41,32 +45,58 @@ fn main()
let _ = v as (u32,); //~ ERROR non-scalar
let _ = Some(&v) as *const u8; //~ ERROR non-scalar
let _ = v as f32; //~ ERROR through a usize first
let _ = main as f64; //~ ERROR through a usize first
let _ = &v as usize; //~ ERROR through a raw pointer first
let _ = f as *const u8; //~ ERROR through a usize first
let _ = 3 as bool; //~ ERROR compare with zero
let _ = E::A as bool; //~ ERROR compare with zero
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 as bool;
//~^ ERROR cannot cast as `bool`
//~^^ HELP compare with zero
let _ = E::A as bool;
//~^ ERROR cannot cast as `bool`
//~^^ HELP compare with zero
let _ = 0x61u32 as char; //~ ERROR only `u8` can be cast
let _ = false as f32; //~ ERROR through an integer first
let _ = E::A as f32; //~ ERROR through an integer first
let _ = 'a' as f32; //~ ERROR through an integer first
let _ = false as f32;
//~^ ERROR casting
//~^^ HELP through an integer first
let _ = E::A as f32;
//~^ ERROR casting
//~^^ HELP through an integer first
let _ = 'a' as f32;
//~^ ERROR casting
//~^^ HELP through an integer first
let _ = false as *const u8; //~ ERROR through a usize first
let _ = E::A as *const u8; //~ ERROR through a usize first
let _ = 'a' as *const u8; //~ ERROR through a usize first
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 illegal cast
let _ = v as *const [u8]; //~ ERROR illegal cast
let _ = 42usize as *const [u8]; //~ ERROR casting
let _ = v as *const [u8]; //~ ERROR casting
let _ = fat_v as *const Foo;
//~^ ERROR `core::marker::Sized` is not implemented for the type `[u8]`
let _ = foo as *const str; //~ ERROR illegal cast
let _ = foo as *mut str; //~ ERROR illegal cast
let _ = main as *mut str; //~ ERROR illegal cast
let _ = &f as *mut f32; //~ ERROR illegal cast
let _ = &f as *const f64; //~ ERROR illegal cast
let _ = fat_v as usize; //~ ERROR through a raw pointer first
let _ = foo as *const str; //~ ERROR casting
let _ = foo as *mut str; //~ ERROR casting
let _ = main as *mut str; //~ ERROR casting
let _ = &f as *mut f32; //~ ERROR casting
let _ = &f as *const f64; //~ ERROR casting
let _ = fat_v as usize;
//~^ ERROR casting
//~^^ HELP through a raw pointer first
let a : *const str = "hello";
let _ = a as *const Foo;
@ -76,6 +106,10 @@ fn main()
let _ = main.f as *const u32; //~ ERROR attempted access of field
let cf: *const Foo = &0;
let _ = cf as *const [u8]; //~ ERROR vtable kinds
let _ = cf as *const Bar; //~ ERROR vtable kinds
let _ = cf as *const [u8];
//~^ ERROR casting
//~^^ NOTE vtable kinds
let _ = cf as *const Bar;
//~^ ERROR casting
//~^^ NOTE vtable kinds
}

View File

@ -9,8 +9,8 @@
// except according to those terms.
static a: &'static str = "foo";
static b: *const u8 = a as *const u8; //~ ERROR illegal cast
static c: *const u8 = &a as *const u8; //~ ERROR illegal cast
static b: *const u8 = a as *const u8; //~ ERROR casting
static c: *const u8 = &a as *const u8; //~ ERROR casting
fn main() {
}

View File

@ -21,8 +21,8 @@ enum F {
}
pub fn main() {
let a = E::L0 as f32; //~ ERROR illegal cast
let c = F::H1 as f32; //~ ERROR illegal cast
let a = E::L0 as f32; //~ ERROR casting
let c = F::H1 as f32; //~ ERROR casting
assert_eq!(a, -1.0f32);
assert_eq!(c, -1.0f32);
}

View File

@ -20,8 +20,8 @@ enum F {
H1 = 0xFFFFFFFFFFFFFFFF
}
static C0: f32 = E::L0 as f32; //~ ERROR illegal cast
static C1: f32 = F::H1 as f32; //~ ERROR illegal cast
static C0: f32 = E::L0 as f32; //~ ERROR casting
static C1: f32 = F::H1 as f32; //~ ERROR casting
pub fn main() {
let b = C0;

View File

@ -17,14 +17,16 @@ fn main() {
let p = a as *const [i32];
let q = a.as_ptr();
a as usize; //~ ERROR illegal cast
a as usize; //~ ERROR casting
b as usize; //~ ERROR non-scalar cast
p as usize; //~ ERROR illegal cast; cast through a raw pointer
p as usize;
//~^ ERROR casting
//~^^ HELP cast through a raw pointer
// #22955
q as *const [i32]; //~ ERROR illegal cast
q as *const [i32]; //~ ERROR casting
// #21397
let t: *mut (Trait + 'static) = 0 as *mut _; //~ ERROR illegal cast
let mut fail: *const str = 0 as *const str; //~ ERROR illegal cast
let t: *mut (Trait + 'static) = 0 as *mut _; //~ ERROR casting
let mut fail: *const str = 0 as *const str; //~ ERROR casting
}

View File

@ -15,8 +15,8 @@ struct X {
fn main() {
let x = X { a: [0] };
let _f = &x.a as *mut u8; //~ ERROR illegal cast
let _f = &x.a as *mut u8; //~ ERROR casting
let local: [u8; 1] = [0];
let _v = &local as *mut u8; //~ ERROR illegal cast
let _v = &local as *mut u8; //~ ERROR casting
}

View File

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

View File

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

View File

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

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern:illegal cast
// error-pattern:casting
#![feature(libc)]

View File

@ -28,7 +28,7 @@ fn main() {
let mut x1 = X { y: [0, 0] };
// This is still an error since we don't allow casts from &mut [T; n] to *mut T.
let p1: *mut u8 = &mut x1.y as *mut _; //~ ERROR illegal cast
let p1: *mut u8 = &mut x1.y as *mut _; //~ ERROR casting
let t1: *mut [u8; 2] = &mut x1.y as *mut _;
let h1: *mut [u8; 2] = &mut x1.y as *mut [u8; 2];
}