Skip to content

Commit 3ebb495

Browse files
committed
Add trivial cast lints.
This permits all coercions to be performed in casts, but adds lints to warn in those cases. Part of this patch moves cast checking to a later stage of type checking. We acquire obligations to check casts as part of type checking where we previously checked them. Once we have type checked a function or module, then we check any cast obligations which have been acquired. That means we have more type information available to check casts (this was crucial to making coercions work properly in place of some casts), but it means that casts cannot feed input into type inference. [breaking change] * Adds two new lints for trivial casts and trivial numeric casts, these are warn by default, but can cause errors if you build with warnings as errors. Previously, trivial numeric casts and casts to trait objects were allowed. * The unused casts lint has gone. * Interactions between casting and type inference have changed in subtle ways. Two ways this might manifest are: - You may need to 'direct' casts more with extra type information, for example, in some cases where `foo as _ as T` succeeded, you may now need to specify the type for `_` - Casts do not influence inference of integer types. E.g., the following used to type check: ``` let x = 42; let y = &x as *const u32; ``` Because the cast would inform inference that `x` must have type `u32`. This no longer applies and the compiler will fallback to `i32` for `x` and thus there will be a type error in the cast. The solution is to add more type information: ``` let x: u32 = 42; let y = &x as *const u32; ```
1 parent b0aad7d commit 3ebb495

File tree

90 files changed

+287
-447
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+287
-447
lines changed

src/libarena/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,8 @@ impl<T> TypedArenaChunk<T> {
429429
// Destroy the next chunk.
430430
let next = self.next;
431431
let size = calculate_size::<T>(self.capacity);
432-
deallocate(self as *mut TypedArenaChunk<T> as *mut u8, size,
432+
let self_ptr: *mut TypedArenaChunk<T> = self;
433+
deallocate(self_ptr as *mut u8, size,
433434
mem::min_align_of::<TypedArenaChunk<T>>());
434435
if !next.is_null() {
435436
let capacity = (*next).capacity;

src/libcollections/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
html_root_url = "http://doc.rust-lang.org/nightly/",
2424
html_playground_url = "http://play.rust-lang.org/")]
2525

26+
#![allow(trivial_cast)]
27+
#![allow(trivial_numeric_cast)]
2628
#![feature(alloc)]
2729
#![feature(box_syntax)]
2830
#![feature(box_patterns)]

src/libcollections/vec.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,8 +1186,8 @@ impl<T: PartialEq> Vec<T> {
11861186

11871187
// Avoid bounds checks by using unsafe pointers.
11881188
let p = self.as_mut_ptr();
1189-
let mut r = 1;
1190-
let mut w = 1;
1189+
let mut r: usize = 1;
1190+
let mut w: usize = 1;
11911191

11921192
while r < ln {
11931193
let p_r = p.offset(r as isize);

src/libcore/cell.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,11 @@ impl<T> UnsafeCell<T> {
712712
/// ```
713713
#[inline]
714714
#[stable(feature = "rust1", since = "1.0.0")]
715-
pub fn get(&self) -> *mut T { &self.value as *const T as *mut T }
715+
pub fn get(&self) -> *mut T {
716+
// FIXME(#23542) Replace with type ascription.
717+
#![allow(trivial_cast)]
718+
&self.value as *const T as *mut T
719+
}
716720

717721
/// Unwraps the value
718722
///

src/libcore/fmt/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,20 +829,26 @@ impl<T> Pointer for *const T {
829829
#[stable(feature = "rust1", since = "1.0.0")]
830830
impl<T> Pointer for *mut T {
831831
fn fmt(&self, f: &mut Formatter) -> Result {
832+
// FIXME(#23542) Replace with type ascription.
833+
#![allow(trivial_cast)]
832834
Pointer::fmt(&(*self as *const T), f)
833835
}
834836
}
835837

836838
#[stable(feature = "rust1", since = "1.0.0")]
837839
impl<'a, T> Pointer for &'a T {
838840
fn fmt(&self, f: &mut Formatter) -> Result {
841+
// FIXME(#23542) Replace with type ascription.
842+
#![allow(trivial_cast)]
839843
Pointer::fmt(&(*self as *const T), f)
840844
}
841845
}
842846

843847
#[stable(feature = "rust1", since = "1.0.0")]
844848
impl<'a, T> Pointer for &'a mut T {
845849
fn fmt(&self, f: &mut Formatter) -> Result {
850+
// FIXME(#23542) Replace with type ascription.
851+
#![allow(trivial_cast)]
846852
Pointer::fmt(&(&**self as *const T), f)
847853
}
848854
}

src/libcore/fmt/num.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// FIXME: #6220 Implement floating point formatting
1414

1515
#![allow(unsigned_negation)]
16+
#![allow(trivial_numeric_cast)]
1617

1718
use fmt;
1819
use iter::IteratorExt;

src/libcore/hash/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ mod impls {
180180
}
181181

182182
fn hash_slice<H: Hasher>(data: &[$ty], state: &mut H) {
183+
// FIXME(#23542) Replace with type ascription.
184+
#![allow(trivial_cast)]
183185
let newlen = data.len() * ::$ty::BYTES as usize;
184186
let ptr = data.as_ptr() as *const u8;
185187
state.write(unsafe { slice::from_raw_parts(ptr, newlen) })

src/libcore/mem.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,8 @@ pub fn drop<T>(_x: T) { }
313313
#[inline]
314314
#[stable(feature = "rust1", since = "1.0.0")]
315315
pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
316+
// FIXME(#23542) Replace with type ascription.
317+
#![allow(trivial_cast)]
316318
ptr::read(src as *const T as *const U)
317319
}
318320

src/libcore/num/i16.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@
1212
1313
#![stable(feature = "rust1", since = "1.0.0")]
1414
#![doc(primitive = "i16")]
15+
#![allow(trivial_numeric_cast)]
1516

1617
int_module! { i16, 16 }

src/libcore/num/i32.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@
1212
1313
#![stable(feature = "rust1", since = "1.0.0")]
1414
#![doc(primitive = "i32")]
15+
#![allow(trivial_numeric_cast)]
1516

1617
int_module! { i32, 32 }

src/libcore/num/i64.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@
1212
1313
#![stable(feature = "rust1", since = "1.0.0")]
1414
#![doc(primitive = "i64")]
15+
#![allow(trivial_numeric_cast)]
1516

1617
int_module! { i64, 64 }

src/libcore/num/i8.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@
1212
1313
#![stable(feature = "rust1", since = "1.0.0")]
1414
#![doc(primitive = "i8")]
15+
#![allow(trivial_numeric_cast)]
1516

1617
int_module! { i8, 8 }

src/libcore/num/int_macros.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
#![doc(hidden)]
12+
#![allow(trivial_numeric_cast)]
1213

1314
macro_rules! int_module { ($T:ty, $bits:expr) => (
1415

src/libcore/num/isize.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
1717
#![stable(feature = "rust1", since = "1.0.0")]
1818
#![doc(primitive = "isize")]
19+
#![allow(trivial_numeric_cast)]
1920

2021
#[cfg(target_pointer_width = "32")]
2122
int_module! { isize, 32 }

src/libcore/num/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
1515
#![stable(feature = "rust1", since = "1.0.0")]
1616
#![allow(missing_docs)]
17+
#![allow(trivial_numeric_cast)]
1718

1819
use self::wrapping::{OverflowingOps, WrappingOps};
1920

src/libcore/num/u16.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@
1212
1313
#![stable(feature = "rust1", since = "1.0.0")]
1414
#![doc(primitive = "u16")]
15+
#![allow(trivial_numeric_cast)]
1516

1617
uint_module! { u16, i16, 16 }

src/libcore/num/u32.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@
1212
1313
#![stable(feature = "rust1", since = "1.0.0")]
1414
#![doc(primitive = "u32")]
15+
#![allow(trivial_numeric_cast)]
1516

1617
uint_module! { u32, i32, 32 }

src/libcore/num/u64.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@
1212
1313
#![stable(feature = "rust1", since = "1.0.0")]
1414
#![doc(primitive = "u64")]
15+
#![allow(trivial_numeric_cast)]
1516

1617
uint_module! { u64, i64, 64 }

src/libcore/num/u8.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@
1212
1313
#![stable(feature = "rust1", since = "1.0.0")]
1414
#![doc(primitive = "u8")]
15+
#![allow(trivial_numeric_cast)]
1516

1617
uint_module! { u8, i8, 8 }

src/libcore/num/uint_macros.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
#![doc(hidden)]
12+
#![allow(trivial_numeric_cast)]
1213

1314
macro_rules! uint_module { ($T:ty, $T_SIGNED:ty, $bits:expr) => (
1415

src/libcore/num/usize.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,6 @@
1616
1717
#![stable(feature = "rust1", since = "1.0.0")]
1818
#![doc(primitive = "usize")]
19+
#![allow(trivial_numeric_cast)]
1920

2021
uint_module! { usize, isize, ::isize::BITS }

src/libcore/ptr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ impl<T: ?Sized> Unique<T> {
544544
/// Create a new `Unique`.
545545
#[unstable(feature = "unique")]
546546
pub unsafe fn new(ptr: *mut T) -> Unique<T> {
547-
Unique { pointer: NonZero::new(ptr as *const T), _marker: PhantomData }
547+
Unique { pointer: NonZero::new(ptr), _marker: PhantomData }
548548
}
549549

550550
/// Dereference the content.

src/libcore/str/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ pub unsafe fn from_utf8_unchecked<'a>(v: &'a [u8]) -> &'a str {
244244
reason = "use std::ffi::c_str_to_bytes + str::from_utf8")]
245245
pub unsafe fn from_c_str(s: *const i8) -> &'static str {
246246
let s = s as *const u8;
247-
let mut len = 0;
247+
let mut len: usize = 0;
248248
while *s.offset(len as isize) != 0 {
249249
len += 1;
250250
}

src/libcoretest/mem.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ fn test_transmute() {
9595
trait Foo { fn dummy(&self) { } }
9696
impl Foo for int {}
9797

98-
let a = box 100 as Box<Foo>;
98+
let a = box 100isize as Box<Foo>;
9999
unsafe {
100100
let x: ::core::raw::TraitObject = transmute(a);
101101
assert!(*(x.data as *const int) == 100);

src/libcoretest/ptr.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ fn test_as_ref() {
8484
assert_eq!(q.as_ref().unwrap(), &2);
8585

8686
// Lifetime inference
87-
let u = 2;
87+
let u = 2isize;
8888
{
89-
let p: *const int = &u as *const _;
89+
let p = &u as *const int;
9090
assert_eq!(p.as_ref().unwrap(), &2);
9191
}
9292
}
@@ -102,9 +102,9 @@ fn test_as_mut() {
102102
assert!(q.as_mut().unwrap() == &mut 2);
103103

104104
// Lifetime inference
105-
let mut u = 2;
105+
let mut u = 2isize;
106106
{
107-
let p: *mut int = &mut u as *mut _;
107+
let p = &mut u as *mut int;
108108
assert!(p.as_mut().unwrap() == &mut 2);
109109
}
110110
}
@@ -170,9 +170,9 @@ fn test_set_memory() {
170170

171171
#[test]
172172
fn test_unsized_unique() {
173-
let xs: &mut [_] = &mut [1, 2, 3];
174-
let ptr = unsafe { Unique::new(xs as *mut [_]) };
173+
let xs: &mut [i32] = &mut [1, 2, 3];
174+
let ptr = unsafe { Unique::new(xs as *mut [i32]) };
175175
let ys = unsafe { &mut **ptr };
176-
let zs: &mut [_] = &mut [1, 2, 3];
176+
let zs: &mut [i32] = &mut [1, 2, 3];
177177
assert!(ys == zs);
178178
}

src/liblog/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,10 +304,10 @@ pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) {
304304
// Completely remove the local logger from TLS in case anyone attempts to
305305
// frob the slot while we're doing the logging. This will destroy any logger
306306
// set during logging.
307-
let mut logger = LOCAL_LOGGER.with(|s| {
307+
let mut logger: Box<Logger + Send> = LOCAL_LOGGER.with(|s| {
308308
s.borrow_mut().take()
309309
}).unwrap_or_else(|| {
310-
box DefaultLogger { handle: io::stderr() } as Box<Logger + Send>
310+
box DefaultLogger { handle: io::stderr() }
311311
});
312312
logger.log(&LogRecord {
313313
level: LogLevel(level),

src/librand/distributions/range.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
//! Generating numbers between two others.
1212
13+
#![allow(trivial_numeric_cast)]
14+
1315
// this is surprisingly complicated to be both generic & correct
1416

1517
use core::prelude::{PartialOrd};

src/librand/isaac.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,7 @@ impl Rng for Isaac64Rng {
447447

448448
#[inline]
449449
fn next_u64(&mut self) -> u64 {
450+
#![allow(trivial_numeric_cast)]
450451
if self.cnt == 0 {
451452
// make some more numbers
452453
self.isaac64();

src/librbml/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ pub mod reader {
353353
let (shift, mask) = SHIFT_MASK_TABLE[i];
354354
Ok(Res {
355355
val: ((val >> shift) & mask) as uint,
356-
next: start + (((32 - shift) >> 3) as uint)
356+
next: start + ((32 - shift) >> 3),
357357
})
358358
}
359359
}
@@ -573,7 +573,7 @@ pub mod reader {
573573
0 => doc_as_u8(r_doc) as u64,
574574
1 => doc_as_u16(r_doc) as u64,
575575
2 => doc_as_u32(r_doc) as u64,
576-
3 => doc_as_u64(r_doc) as u64,
576+
3 => doc_as_u64(r_doc),
577577
_ => unreachable!(),
578578
}
579579
} else {

src/librustc/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@
4545
#![feature(str_char)]
4646
#![cfg_attr(test, feature(test))]
4747

48+
#![allow(trivial_cast)]
49+
#![allow(trivial_numeric_cast)]
50+
4851
extern crate arena;
4952
extern crate flate;
5053
extern crate fmt_macros;

src/librustc/lint/builtin.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,17 @@ declare_lint! {
100100
"detects transmutes of fat pointers"
101101
}
102102

103+
declare_lint! {
104+
pub TRIVIAL_CAST,
105+
Warn,
106+
"detects trivial casts which could be removed"
107+
}
108+
109+
declare_lint! {
110+
pub TRIVIAL_NUMERIC_CAST,
111+
Warn,
112+
"detects trivial casts of numeric types which could be removed"
113+
}
103114
/// Does nothing as a lint pass, but registers some `Lint`s
104115
/// which are used by other parts of the compiler.
105116
#[derive(Copy)]
@@ -121,7 +132,9 @@ impl LintPass for HardwiredLints {
121132
STABLE_FEATURES,
122133
UNKNOWN_CRATE_TYPES,
123134
VARIANT_SIZE_DIFFERENCES,
124-
FAT_PTR_TRANSMUTES
135+
FAT_PTR_TRANSMUTES,
136+
TRIVIAL_CAST,
137+
TRIVIAL_NUMERIC_CAST
125138
)
126139
}
127140
}

0 commit comments

Comments
 (0)