Skip to content

Commit

Permalink
Improve typeck diagnostic messages
Browse files Browse the repository at this point in the history
Mostly by splitting error messages into proper pairs of errors and helps
  • Loading branch information
nagisa committed Jul 28, 2015
1 parent 77e9228 commit ffcdf08
Show file tree
Hide file tree
Showing 13 changed files with 102 additions and 57 deletions.
28 changes: 15 additions & 13 deletions src/librustc_typeck/check/cast.rs
Expand Up @@ -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| {
Expand All @@ -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");
}
}
}
Expand Down Expand Up @@ -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);
}
Expand Down
7 changes: 5 additions & 2 deletions src/test/compile-fail/cast-as-bool.rs
Expand Up @@ -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
}
82 changes: 58 additions & 24 deletions src/test/compile-fail/cast-rfc0401.rs
Expand Up @@ -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) {} }
Expand All @@ -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;
Expand All @@ -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
}
4 changes: 2 additions & 2 deletions src/test/compile-fail/const-cast-different-types.rs
Expand Up @@ -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() {
}
4 changes: 2 additions & 2 deletions src/test/compile-fail/enum-to-float-cast-2.rs
Expand Up @@ -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);
}
4 changes: 2 additions & 2 deletions src/test/compile-fail/enum-to-float-cast.rs
Expand Up @@ -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;
Expand Down
12 changes: 7 additions & 5 deletions src/test/compile-fail/fat-ptr-cast.rs
Expand Up @@ -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
}
4 changes: 2 additions & 2 deletions src/test/compile-fail/issue-14845.rs
Expand Up @@ -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
}
3 changes: 2 additions & 1 deletion src/test/compile-fail/issue-17444.rs
Expand Up @@ -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
}
4 changes: 3 additions & 1 deletion src/test/compile-fail/issue-21554.rs
Expand Up @@ -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
}
3 changes: 2 additions & 1 deletion src/test/compile-fail/typeck-cast-pointer-to-float.rs
Expand Up @@ -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
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/unsupported-cast.rs
Expand Up @@ -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)]

Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/vector-cast-weirdness.rs
Expand Up @@ -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];
}

0 comments on commit ffcdf08

Please sign in to comment.