]> git.lizzy.rs Git - rust.git/commitdiff
Add trivial cast lints.
authorNick Cameron <ncameron@mozilla.com>
Fri, 20 Mar 2015 04:15:27 +0000 (17:15 +1300)
committerNick Cameron <ncameron@mozilla.com>
Tue, 24 Mar 2015 21:03:57 +0000 (10:03 +1300)
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;
```

90 files changed:
src/libarena/lib.rs
src/libcollections/lib.rs
src/libcollections/vec.rs
src/libcore/cell.rs
src/libcore/fmt/mod.rs
src/libcore/fmt/num.rs
src/libcore/hash/mod.rs
src/libcore/mem.rs
src/libcore/num/i16.rs
src/libcore/num/i32.rs
src/libcore/num/i64.rs
src/libcore/num/i8.rs
src/libcore/num/int_macros.rs
src/libcore/num/isize.rs
src/libcore/num/mod.rs
src/libcore/num/u16.rs
src/libcore/num/u32.rs
src/libcore/num/u64.rs
src/libcore/num/u8.rs
src/libcore/num/uint_macros.rs
src/libcore/num/usize.rs
src/libcore/ptr.rs
src/libcore/str/mod.rs
src/libcoretest/mem.rs
src/libcoretest/ptr.rs
src/liblog/lib.rs
src/librand/distributions/range.rs
src/librand/isaac.rs
src/librbml/lib.rs
src/librustc/lib.rs
src/librustc/lint/builtin.rs
src/librustc/middle/ty.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_llvm/lib.rs
src/librustc_trans/lib.rs
src/librustc_trans/trans/datum.rs
src/librustc_trans/trans/expr.rs
src/librustc_trans/trans/meth.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/vtable.rs
src/librustdoc/html/markdown.rs
src/libserialize/json.rs
src/libstd/lib.rs
src/libstd/old_io/stdio.rs
src/libstd/rt/mod.rs
src/libsyntax/codemap.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/quote.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libterm/lib.rs
src/libterm/terminfo/mod.rs
src/libterm/terminfo/parser/compiled.rs
src/libtest/lib.rs
src/rustbook/subcommand.rs
src/test/auxiliary/issue-11224.rs
src/test/compile-fail/issue-14845.rs
src/test/compile-fail/issue-16538.rs
src/test/compile-fail/issue-5543.rs [deleted file]
src/test/compile-fail/kindck-impl-type-params.rs
src/test/compile-fail/lint-dead-code-3.rs
src/test/compile-fail/lint-unnecessary-casts.rs [deleted file]
src/test/compile-fail/liveness-unused.rs
src/test/compile-fail/object-safety-by-value-self.rs
src/test/compile-fail/regions-close-object-into-object-5.rs
src/test/compile-fail/regions-close-over-type-parameter-1.rs
src/test/compile-fail/type-parameter-defaults-referencing-Self-ppaux.rs
src/test/compile-fail/vector-cast-weirdness.rs
src/test/debuginfo/type-names.rs
src/test/pretty/path-type-bounds.rs
src/test/run-make/symbols-are-reasonable/lib.rs
src/test/run-pass/autoderef-method-on-trait.rs
src/test/run-pass/cast-region-to-uint.rs
src/test/run-pass/infer-container-across-object-cast.rs [deleted file]
src/test/run-pass/issue-15763.rs
src/test/run-pass/issue-5708.rs
src/test/run-pass/issue-9719.rs
src/test/run-pass/method-two-traits-distinguished-via-where-clause.rs
src/test/run-pass/object-one-type-two-traits.rs
src/test/run-pass/objects-coerce-freeze-borrored.rs
src/test/run-pass/regions-early-bound-trait-param.rs
src/test/run-pass/stable-addr-of.rs
src/test/run-pass/task-spawn-move-and-copy.rs
src/test/run-pass/typeck_type_placeholder_1.rs
src/test/run-pass/zero_sized_subslice_match.rs

index 1b0356b88b08dcdb9e3bf1a386f67052170b22f1..7843be0b483ebd8750e7eab20e73ae1014ea04b7 100644 (file)
@@ -429,7 +429,8 @@ unsafe fn destroy(&mut self, len: usize) {
         // Destroy the next chunk.
         let next = self.next;
         let size = calculate_size::<T>(self.capacity);
-        deallocate(self as *mut TypedArenaChunk<T> as *mut u8, size,
+        let self_ptr: *mut TypedArenaChunk<T> = self;
+        deallocate(self_ptr as *mut u8, size,
                    mem::min_align_of::<TypedArenaChunk<T>>());
         if !next.is_null() {
             let capacity = (*next).capacity;
index da2c61b6fd394a47cb1946a149376655c582010f..0a61eeb6e1c63b9ea6a19817fee42882b3c872f9 100644 (file)
@@ -24,6 +24,8 @@
        html_playground_url = "http://play.rust-lang.org/")]
 #![doc(test(no_crate_inject))]
 
+#![allow(trivial_cast)]
+#![allow(trivial_numeric_cast)]
 #![feature(alloc)]
 #![feature(box_syntax)]
 #![feature(box_patterns)]
index 59819d01bc601aeb2f651d4d332474b743c74f7d..af2daabc2d02ca080d5756c0bb9f12aa89d2826a 100644 (file)
@@ -1199,8 +1199,8 @@ pub fn dedup(&mut self) {
 
             // Avoid bounds checks by using unsafe pointers.
             let p = self.as_mut_ptr();
-            let mut r = 1;
-            let mut w = 1;
+            let mut r: usize = 1;
+            let mut w: usize = 1;
 
             while r < ln {
                 let p_r = p.offset(r as isize);
index a9c5de23d948bcbcde2650ae9833ecd172670fe7..f5db3e63c7ad478ff5800167290c1a8b013d15d5 100644 (file)
@@ -713,7 +713,11 @@ pub fn new(value: T) -> UnsafeCell<T> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn get(&self) -> *mut T { &self.value as *const T as *mut T }
+    pub fn get(&self) -> *mut T {
+        // FIXME(#23542) Replace with type ascription.
+        #![allow(trivial_cast)]
+        &self.value as *const T as *mut T
+    }
 
     /// Unwraps the value
     ///
index cf427c16588d9add3682c30ff51449be8380151f..e00cdc9de88da8e84c5a7dd4da1d2378b2d9bbda 100644 (file)
@@ -833,6 +833,8 @@ fn fmt(&self, f: &mut Formatter) -> Result {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Pointer for *mut T {
     fn fmt(&self, f: &mut Formatter) -> Result {
+        // FIXME(#23542) Replace with type ascription.
+        #![allow(trivial_cast)]
         Pointer::fmt(&(*self as *const T), f)
     }
 }
@@ -840,6 +842,8 @@ fn fmt(&self, f: &mut Formatter) -> Result {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Pointer for &'a T {
     fn fmt(&self, f: &mut Formatter) -> Result {
+        // FIXME(#23542) Replace with type ascription.
+        #![allow(trivial_cast)]
         Pointer::fmt(&(*self as *const T), f)
     }
 }
@@ -847,6 +851,8 @@ fn fmt(&self, f: &mut Formatter) -> Result {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Pointer for &'a mut T {
     fn fmt(&self, f: &mut Formatter) -> Result {
+        // FIXME(#23542) Replace with type ascription.
+        #![allow(trivial_cast)]
         Pointer::fmt(&(&**self as *const T), f)
     }
 }
index 49da99b97cb206571b768a1e88e94b6ae86a6d1e..d01d240e5b5f1eb80fe77b81d6d9d8b3ca00d86b 100644 (file)
@@ -13,6 +13,7 @@
 // FIXME: #6220 Implement floating point formatting
 
 #![allow(unsigned_negation)]
+#![allow(trivial_numeric_cast)]
 
 use fmt;
 use iter::IteratorExt;
index 1d5e174a8dc99ebf1fe59d769951ea8a2b7497e8..ccc1d32eab35bd098c552f357da29bcacd46ca56 100644 (file)
@@ -182,6 +182,8 @@ fn hash<H: Hasher>(&self, state: &mut H) {
                 }
 
                 fn hash_slice<H: Hasher>(data: &[$ty], state: &mut H) {
+                    // FIXME(#23542) Replace with type ascription.
+                    #![allow(trivial_cast)]
                     let newlen = data.len() * ::$ty::BYTES as usize;
                     let ptr = data.as_ptr() as *const u8;
                     state.write(unsafe { slice::from_raw_parts(ptr, newlen) })
index 551f97ead12d8262f1f2f30860ea91a410e9eb74..0bc41eb2c6eae3b0f6e614a325cd7ce7c970efc5 100644 (file)
@@ -313,6 +313,8 @@ pub fn drop<T>(_x: T) { }
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
+    // FIXME(#23542) Replace with type ascription.
+    #![allow(trivial_cast)]
     ptr::read(src as *const T as *const U)
 }
 
index 5ea60d0d96d29f44943a0c751cf760d7c7deef0c..1557434a28a27004aa4ab0ea0c9315e591e92a3c 100644 (file)
@@ -12,5 +12,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "i16")]
+#![allow(trivial_numeric_cast)]
 
 int_module! { i16, 16 }
index 7d9faa998c12e87769a8519d416b7085d802dcbf..bdccab4cb9a9f4920c158d31232856da7f4e7c91 100644 (file)
@@ -12,5 +12,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "i32")]
+#![allow(trivial_numeric_cast)]
 
 int_module! { i32, 32 }
index 5a70911387b9b7192ab7a86fae52a90e77ddaa7b..d8f5aa6e54836a3e81d12728e5cc0bfbf5fcb651 100644 (file)
@@ -12,5 +12,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "i64")]
+#![allow(trivial_numeric_cast)]
 
 int_module! { i64, 64 }
index 1d7d78ffa6c2352a20ad49cbfda99a0b3fc7ce17..da2410a04cfe47d28db9bd94c16bb1396049c242 100644 (file)
@@ -12,5 +12,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "i8")]
+#![allow(trivial_numeric_cast)]
 
 int_module! { i8, 8 }
index fe0d6d13c4c06483649bdbf737fe89c68048cf43..5f697e02a9943ea1d50c51f816f79a3ffe91ecc3 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![doc(hidden)]
+#![allow(trivial_numeric_cast)]
 
 macro_rules! int_module { ($T:ty, $bits:expr) => (
 
index 0fd0d90b12501ea87b257bb523b56a1c6d0f1b47..838caa59e47176e274720a6503e011169c64a11f 100644 (file)
@@ -16,6 +16,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "isize")]
+#![allow(trivial_numeric_cast)]
 
 #[cfg(target_pointer_width = "32")]
 int_module! { isize, 32 }
index 9ca7b48fbe5ef05b9a125ea7323266ce44cb0b4d..7686a990acc9d8f1c8598d2355edcb499fb86e04 100644 (file)
@@ -14,6 +14,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![allow(missing_docs)]
+#![allow(trivial_numeric_cast)]
 
 use self::wrapping::{OverflowingOps, WrappingOps};
 
index 21635799a77a26a458619bcd3b3431ce2ae0c7ba..9d91bbc7f9019b9d594873cd589111fe3377fbdc 100644 (file)
@@ -12,5 +12,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "u16")]
+#![allow(trivial_numeric_cast)]
 
 uint_module! { u16, i16, 16 }
index 7d520770503d4b2507cb483afc8bcf04204ca443..2d5f163e093c7fc53cbb4d7c4df1959287740cdb 100644 (file)
@@ -12,5 +12,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "u32")]
+#![allow(trivial_numeric_cast)]
 
 uint_module! { u32, i32, 32 }
index f10822077dc7511e3e44d12596e6e2198e0e941d..26813aa281c66d3deb79b85e22735d04f1c717e6 100644 (file)
@@ -12,5 +12,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "u64")]
+#![allow(trivial_numeric_cast)]
 
 uint_module! { u64, i64, 64 }
index 3d6922b07b19407b325941dd14888e4fea334214..7fb28f27d62aab254ae08ffdcd3aaa166189922a 100644 (file)
@@ -12,5 +12,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "u8")]
+#![allow(trivial_numeric_cast)]
 
 uint_module! { u8, i8, 8 }
index d0c4885ad00b77ebbfaef418cb230976e6955f21..9f502e3ea4312402eb3551f0acdd64106f9dbd2b 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![doc(hidden)]
+#![allow(trivial_numeric_cast)]
 
 macro_rules! uint_module { ($T:ty, $T_SIGNED:ty, $bits:expr) => (
 
index 602ef4fe45e734e0f1a931a2a50c98ce98e0511a..be5acaac92aea3529db25a6d1f589b32abb5ba5e 100644 (file)
@@ -16,5 +16,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "usize")]
+#![allow(trivial_numeric_cast)]
 
 uint_module! { usize, isize, ::isize::BITS }
index d92622eeb70e3c4e83c1db5de34c765fe3a8c211..9b3ee3ef5e0c28fb1a402d0b6100bf1af5ad2288 100644 (file)
@@ -529,7 +529,7 @@ impl<T: ?Sized> Unique<T> {
     /// Create a new `Unique`.
     #[unstable(feature = "unique")]
     pub unsafe fn new(ptr: *mut T) -> Unique<T> {
-        Unique { pointer: NonZero::new(ptr as *const T), _marker: PhantomData }
+        Unique { pointer: NonZero::new(ptr), _marker: PhantomData }
     }
 
     /// Dereference the content.
index b7285d30a7309cc9451a22aef5e4ba7170a3c250..035d070cd6d43f24348e4b992bf9b8e5ea01a30b 100644 (file)
@@ -261,7 +261,7 @@ pub unsafe fn from_utf8_unchecked<'a>(v: &'a [u8]) -> &'a str {
              reason = "use std::ffi::c_str_to_bytes + str::from_utf8")]
 pub unsafe fn from_c_str(s: *const i8) -> &'static str {
     let s = s as *const u8;
-    let mut len = 0;
+    let mut len: usize = 0;
     while *s.offset(len as isize) != 0 {
         len += 1;
     }
index bf3e1cf03cbddfb516fe2137b43d44e63d9b89a6..17d6b684c50e80a1111ee80cc5e47a1b329f347d 100644 (file)
@@ -95,7 +95,7 @@ fn test_transmute() {
     trait Foo { fn dummy(&self) { } }
     impl Foo for int {}
 
-    let a = box 100 as Box<Foo>;
+    let a = box 100isize as Box<Foo>;
     unsafe {
         let x: ::core::raw::TraitObject = transmute(a);
         assert!(*(x.data as *const int) == 100);
index adc15b9fbc27ffcd6bf38f74d4d9ec8246850baf..4f5f269d4375d0c0a6e2ec2c24ad3f19b476a065 100644 (file)
@@ -84,9 +84,9 @@ fn test_as_ref() {
         assert_eq!(q.as_ref().unwrap(), &2);
 
         // Lifetime inference
-        let u = 2;
+        let u = 2isize;
         {
-            let p: *const int = &u as *const _;
+            let p = &u as *const int;
             assert_eq!(p.as_ref().unwrap(), &2);
         }
     }
@@ -102,9 +102,9 @@ fn test_as_mut() {
         assert!(q.as_mut().unwrap() == &mut 2);
 
         // Lifetime inference
-        let mut u = 2;
+        let mut u = 2isize;
         {
-            let p: *mut int = &mut u as *mut _;
+            let p = &mut u as *mut int;
             assert!(p.as_mut().unwrap() == &mut 2);
         }
     }
@@ -170,9 +170,9 @@ fn test_set_memory() {
 
 #[test]
 fn test_unsized_unique() {
-    let xs: &mut [_] = &mut [1, 2, 3];
-    let ptr = unsafe { Unique::new(xs as *mut [_]) };
+    let xs: &mut [i32] = &mut [1, 2, 3];
+    let ptr = unsafe { Unique::new(xs as *mut [i32]) };
     let ys = unsafe { &mut **ptr };
-    let zs: &mut [_] = &mut [1, 2, 3];
+    let zs: &mut [i32] = &mut [1, 2, 3];
     assert!(ys == zs);
 }
index 4537fc763c9536caa7a6ba3ba6312cdff8b71ef4..2c431e1e05088ffacad06f7679eb6217d1261231 100644 (file)
@@ -304,10 +304,10 @@ pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) {
     // Completely remove the local logger from TLS in case anyone attempts to
     // frob the slot while we're doing the logging. This will destroy any logger
     // set during logging.
-    let mut logger = LOCAL_LOGGER.with(|s| {
+    let mut logger: Box<Logger + Send> = LOCAL_LOGGER.with(|s| {
         s.borrow_mut().take()
     }).unwrap_or_else(|| {
-        box DefaultLogger { handle: io::stderr() } as Box<Logger + Send>
+        box DefaultLogger { handle: io::stderr() }
     });
     logger.log(&LogRecord {
         level: LogLevel(level),
index e6f27a28ffa7ca118d7d6595c33afe8ae54b5b51..0001cb6e0caafaccd31026205ccd1632f1a83a50 100644 (file)
@@ -10,6 +10,8 @@
 
 //! Generating numbers between two others.
 
+#![allow(trivial_numeric_cast)]
+
 // this is surprisingly complicated to be both generic & correct
 
 use core::prelude::{PartialOrd};
index 7ea62b7fd3f413b62d35b1d365872e645d3cc4ee..673246fe30dc1500d84e3a43dc53b66e97d2843b 100644 (file)
@@ -447,6 +447,7 @@ fn next_u32(&mut self) -> u32 {
 
     #[inline]
     fn next_u64(&mut self) -> u64 {
+        #![allow(trivial_numeric_cast)]
         if self.cnt == 0 {
             // make some more numbers
             self.isaac64();
index 1a794f56f802c62c3a9c371f47acf6583e568111..182b05acbb61860d2133cd1db0027485f5f89b84 100644 (file)
@@ -353,7 +353,7 @@ pub fn vuint_at(data: &[u8], start: uint) -> DecodeResult<Res> {
             let (shift, mask) = SHIFT_MASK_TABLE[i];
             Ok(Res {
                 val: ((val >> shift) & mask) as uint,
-                next: start + (((32 - shift) >> 3) as uint)
+                next: start + ((32 - shift) >> 3),
             })
         }
     }
@@ -573,7 +573,7 @@ fn _next_int(&mut self,
                     0 => doc_as_u8(r_doc) as u64,
                     1 => doc_as_u16(r_doc) as u64,
                     2 => doc_as_u32(r_doc) as u64,
-                    3 => doc_as_u64(r_doc) as u64,
+                    3 => doc_as_u64(r_doc),
                     _ => unreachable!(),
                 }
             } else {
index 793eff6a9da6fc9763c02e68a72ee7ccecd5a5f6..dd5f3cccea54453557d0107b47affbe0677b0518 100644 (file)
@@ -47,6 +47,9 @@
 #![feature(into_cow)]
 #![cfg_attr(test, feature(test))]
 
+#![allow(trivial_cast)]
+#![allow(trivial_numeric_cast)]
+
 extern crate arena;
 extern crate flate;
 extern crate fmt_macros;
index 44718d1c5251dbfff6cfe42f55d9e7ee67d31df4..4f56f2441dc4199da1b1e6381b77d6592c1c0bd1 100644 (file)
     "detects transmutes of fat pointers"
 }
 
+declare_lint! {
+    pub TRIVIAL_CAST,
+    Warn,
+    "detects trivial casts which could be removed"
+}
+
+declare_lint! {
+    pub TRIVIAL_NUMERIC_CAST,
+    Warn,
+    "detects trivial casts of numeric types which could be removed"
+}
 /// Does nothing as a lint pass, but registers some `Lint`s
 /// which are used by other parts of the compiler.
 #[derive(Copy)]
@@ -121,7 +132,9 @@ fn get_lints(&self) -> LintArray {
             STABLE_FEATURES,
             UNKNOWN_CRATE_TYPES,
             VARIANT_SIZE_DIFFERENCES,
-            FAT_PTR_TRANSMUTES
+            FAT_PTR_TRANSMUTES,
+            TRIVIAL_CAST,
+            TRIVIAL_NUMERIC_CAST
         )
     }
 }
index e5e89c3fbd4b9802ed729631f7ad8dbafec6195f..38a20c61d2e631f263faa0fa19832fe662f22f28 100644 (file)
@@ -968,7 +968,7 @@ impl<'tcx> Eq for TyS<'tcx> {}
 
 impl<'tcx> Hash for TyS<'tcx> {
     fn hash<H: Hasher>(&self, s: &mut H) {
-        (self as *const _).hash(s)
+        (self as *const TyS).hash(s)
     }
 }
 
@@ -2721,7 +2721,7 @@ fn intern_ty<'tcx>(type_arena: &'tcx TypedArena<TyS<'tcx>>,
     };
 
     debug!("Interned type: {:?} Pointer: {:?}",
-           ty, ty as *const _);
+           ty, ty as *const TyS);
 
     interner.insert(InternedTy { ty: ty }, ty);
 
@@ -4806,32 +4806,6 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
             RvalueDpsExpr
         }
 
-        ast::ExprCast(..) => {
-            match tcx.node_types.borrow().get(&expr.id) {
-                Some(&ty) => {
-                    if type_is_trait(ty) {
-                        RvalueDpsExpr
-                    } else {
-                        RvalueDatumExpr
-                    }
-                }
-                None => {
-                    // Technically, it should not happen that the expr is not
-                    // present within the table.  However, it DOES happen
-                    // during type check, because the final types from the
-                    // expressions are not yet recorded in the tcx.  At that
-                    // time, though, we are only interested in knowing lvalue
-                    // vs rvalue.  It would be better to base this decision on
-                    // the AST type in cast node---but (at the time of this
-                    // writing) it's not easy to distinguish casts to traits
-                    // from other casts based on the AST.  This should be
-                    // easier in the future, when casts to traits
-                    // would like @Foo, Box<Foo>, or &Foo.
-                    RvalueDatumExpr
-                }
-            }
-        }
-
         ast::ExprBreak(..) |
         ast::ExprAgain(..) |
         ast::ExprRet(..) |
@@ -4847,7 +4821,8 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
         ast::ExprUnary(..) |
         ast::ExprBox(None, _) |
         ast::ExprAddrOf(..) |
-        ast::ExprBinary(..) => {
+        ast::ExprBinary(..) |
+        ast::ExprCast(..) => {
             RvalueDatumExpr
         }
 
index e65fe904dd29af28eb5e1a3e1dad8e836afde366..ef82a465ef4bf9944093a8bab32f72e37b8c0551 100644 (file)
@@ -1804,6 +1804,9 @@ fn get_lints(&self) -> LintArray {
 
     fn check_fn(&mut self, cx: &Context, fn_kind: visit::FnKind, _: &ast::FnDecl,
                 blk: &ast::Block, sp: Span, id: ast::NodeId) {
+        // FIXME(#23542) Replace with type ascription.
+        #![allow(trivial_cast)]
+
         type F = for<'tcx> fn(&ty::ctxt<'tcx>,
                               ast::NodeId, ast::NodeId, ast::Ident, ast::NodeId) -> bool;
 
index ef65acf8b13f4838d5f848de3e0051f86eb17aa0..f2d2db18da4b5e20496ea464bd0c714dce5fd186 100644 (file)
@@ -56,7 +56,7 @@
 pub use rustc::util as util;
 
 use session::Session;
-use lint::{LintPassObject, LintId};
+use lint::LintId;
 
 mod builtin;
 
@@ -67,7 +67,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
     macro_rules! add_builtin {
         ($sess:ident, $($name:ident),*,) => (
             {$(
-                store.register_pass($sess, false, box builtin::$name as LintPassObject);
+                store.register_pass($sess, false, box builtin::$name);
                 )*}
             )
     }
@@ -75,7 +75,7 @@ macro_rules! add_builtin {
     macro_rules! add_builtin_with_new {
         ($sess:ident, $($name:ident),*,) => (
             {$(
-                store.register_pass($sess, false, box builtin::$name::new() as LintPassObject);
+                store.register_pass($sess, false, box builtin::$name::new());
                 )*}
             )
     }
@@ -129,7 +129,7 @@ macro_rules! add_lint_group {
                     UNUSED_UNSAFE, PATH_STATEMENTS);
 
     // We have one lint pass defined specially
-    store.register_pass(sess, false, box lint::GatherNodeLevels as LintPassObject);
+    store.register_pass(sess, false, box lint::GatherNodeLevels);
 
     // Insert temporary renamings for a one-time deprecation
     store.register_renamed("raw_pointer_deriving", "raw_pointer_derive");
index 506bf4a058fc6f155e10b3b8a7a5ec4709c97d3f..4d821df72a6e0d7cc7948951001c30f0c7c01510 100644 (file)
@@ -14,6 +14,8 @@
 #![allow(non_camel_case_types)]
 #![allow(non_snake_case)]
 #![allow(dead_code)]
+#![allow(trivial_cast)]
+#![allow(trivial_numeric_cast)]
 
 #![crate_name = "rustc_llvm"]
 #![unstable(feature = "rustc_private")]
index b9ec22b86f0769e5b4ebf25c6fdecee6e365f55f..ef43b9c0de420364a32c39f7ce50e258b63395aa 100644 (file)
@@ -43,6 +43,9 @@
 #![feature(convert)]
 #![feature(path_relative_from)]
 
+#![allow(trivial_cast)]
+#![allow(trivial_numeric_cast)]
+
 extern crate arena;
 extern crate flate;
 extern crate getopts;
index e181df545e6fc06aa63f4b0e2a39f2ea835d9dea..15738d1e61ac14122f0161df205f0d536ebca146 100644 (file)
@@ -471,15 +471,6 @@ pub fn add_clean_if_rvalue<'blk>(self,
             })
     }
 
-    /// Ensures that `self` will get cleaned up, if it is not an lvalue already.
-    pub fn clean<'blk>(self,
-                       bcx: Block<'blk, 'tcx>,
-                       name: &'static str,
-                       expr_id: ast::NodeId)
-                       -> Block<'blk, 'tcx> {
-        self.to_lvalue_datum(bcx, name, expr_id).bcx
-    }
-
     pub fn to_lvalue_datum<'blk>(self,
                                  bcx: Block<'blk, 'tcx>,
                                  name: &str,
index ceb9a29efa8879a9d30ad4544d812c579e87f97f..4d7431a20b707e098f3ef6ea54f03b7853ea2763 100644 (file)
@@ -1227,22 +1227,9 @@ fn make_field(field_name: &str, expr: P<ast::Expr>) -> ast::Field {
             trans_overloaded_op(bcx, expr, MethodCall::expr(expr.id), base,
                                 vec![(idx_datum, idx.id)], Some(dest), true).bcx
         }
-        ast::ExprCast(ref val, _) => {
-            // DPS output mode means this is a trait cast:
-            if ty::type_is_trait(node_id_type(bcx, expr.id)) {
-                let trait_ref =
-                    bcx.tcx().object_cast_map.borrow()
-                                             .get(&expr.id)
-                                             .cloned()
-                                             .unwrap();
-                let trait_ref = bcx.monomorphize(&trait_ref);
-                let datum = unpack_datum!(bcx, trans(bcx, &**val));
-                meth::trans_trait_cast(bcx, datum, expr.id,
-                                       trait_ref, dest)
-            } else {
-                bcx.tcx().sess.span_bug(expr.span,
-                                        "expr_cast of non-trait");
-            }
+        ast::ExprCast(..) => {
+            // Trait casts used to come this way, now they should be coercions.
+            bcx.tcx().sess.span_bug(expr.span, "DPS expr_cast (residual trait cast?)")
         }
         ast::ExprAssignOp(op, ref dst, ref src) => {
             trans_assign_op(bcx, expr, op, &**dst, &**src)
@@ -2091,7 +2078,7 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let mut bcx = bcx;
     let ccx = bcx.ccx();
 
-    let t_in = expr_ty(bcx, expr);
+    let t_in = expr_ty_adjusted(bcx, expr);
     let t_out = node_id_type(bcx, id);
     let k_in = cast_type_kind(bcx.tcx(), t_in);
     let k_out = cast_type_kind(bcx.tcx(), t_out);
@@ -2103,7 +2090,8 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     // by-value as appropriate given its type:
     let mut datum = unpack_datum!(bcx, trans(bcx, expr));
 
-    if cast_is_noop(datum.ty, t_out) {
+    let datum_ty = monomorphize_type(bcx, datum.ty);
+    if cast_is_noop(datum_ty, t_out) {
         datum.ty = t_out;
         return DatumBlock::new(bcx, datum);
     }
index 4da17972c55fb68e4eda4207eb20911b0c67374c..d13076df637619767345910d37ced49b6ab7e879 100644 (file)
@@ -26,7 +26,7 @@
 use trans::consts;
 use trans::datum::*;
 use trans::debuginfo::DebugLoc;
-use trans::expr::{SaveIn, Ignore};
+use trans::expr::SaveIn;
 use trans::expr;
 use trans::glue;
 use trans::machine;
@@ -861,44 +861,6 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         .collect()
 }
 
-/// Generates the code to convert from a pointer (`Box<T>`, `&T`, etc) into an object
-/// (`Box<Trait>`, `&Trait`, etc). This means creating a pair where the first word is the vtable
-/// and the second word is the pointer.
-pub fn trans_trait_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                    datum: Datum<'tcx, Expr>,
-                                    id: ast::NodeId,
-                                    trait_ref: ty::PolyTraitRef<'tcx>,
-                                    dest: expr::Dest)
-                                    -> Block<'blk, 'tcx> {
-    let mut bcx = bcx;
-    let _icx = push_ctxt("meth::trans_trait_cast");
-
-    let lldest = match dest {
-        Ignore => {
-            return datum.clean(bcx, "trait_trait_cast", id);
-        }
-        SaveIn(dest) => dest
-    };
-
-    debug!("trans_trait_cast: trait_ref={}",
-           trait_ref.repr(bcx.tcx()));
-
-    let llty = type_of(bcx.ccx(), datum.ty);
-
-    // Store the pointer into the first half of pair.
-    let llboxdest = GEPi(bcx, lldest, &[0, abi::FAT_PTR_ADDR]);
-    let llboxdest = PointerCast(bcx, llboxdest, llty.ptr_to());
-    bcx = datum.store_to(bcx, llboxdest);
-
-    // Store the vtable into the second half of pair.
-    let vtable = get_vtable(bcx.ccx(), trait_ref, bcx.fcx.param_substs);
-    let llvtabledest = GEPi(bcx, lldest, &[0, abi::FAT_PTR_EXTRA]);
-    let llvtabledest = PointerCast(bcx, llvtabledest, val_ty(vtable).ptr_to());
-    Store(bcx, vtable, llvtabledest);
-
-    bcx
-}
-
 /// Replace the self type (&Self or Box<Self>) with an opaque pointer.
 pub fn opaque_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>, method_ty: &ty::BareFnTy<'tcx>)
         -> &'tcx ty::BareFnTy<'tcx> {
index f731507ba906dbeb7f0af6bfbc8bf6ea17ac875b..920154bc916f48f19603e62c82886dc3e761842d 100644 (file)
@@ -332,14 +332,14 @@ fn coerce_unsized(&self,
     // E.g., `[T, ..n]` -> `([T], UnsizeLength(n))`
     fn unsize_ty(&self,
                  ty_a: Ty<'tcx>,
-                 a: Ty<'tcx>,
+                 a: Ty<'tcx>, // TODO unwrap ty_a here, not in the caller
                  ty_b: Ty<'tcx>)
-                 -> Option<(Ty<'tcx>, ty::UnsizeKind<'tcx>)> {
-        debug!("unsize_ty(a={:?}, ty_b={})", a, ty_b.repr(self.tcx()));
-
+                 -> Option<(Ty<'tcx>, ty::UnsizeKind<'tcx>)>
+    {
         let tcx = self.tcx();
 
-        self.unpack_actual_value(ty_b, |b|
+        self.unpack_actual_value(ty_b, |b| {
+            debug!("unsize_ty(a={}, b={})", a.repr(self.tcx()), b.repr(self.tcx()));
             match (&a.sty, &b.sty) {
                 (&ty::ty_vec(t_a, Some(len)), &ty::ty_vec(_, None)) => {
                     let ty = ty::mk_vec(tcx, t_a, None);
@@ -438,7 +438,7 @@ fn unsize_ty(&self,
                 }
                 _ => None
             }
-        )
+        })
     }
 
     fn coerce_from_fn_pointer(&self,
index 6f2d0cb3667418023cc69a0d954305d84bab85cb..cd6a1226e00c9d639d8c83d38891caaf13122e85 100644 (file)
@@ -53,9 +53,11 @@ pub fn eqtype<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
     }
 }
 
-// Checks that the type `actual` can be coerced to `expected`.
-pub fn coerce<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
-                        expected: Ty<'tcx>, expr: &ast::Expr) {
+// Checks that the type of `expr` can be coerced to `expected`.
+pub fn coerce<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                        sp: Span,
+                        expected: Ty<'tcx>,
+                        expr: &ast::Expr) {
     let expr_ty = fcx.expr_ty(expr);
     debug!("demand::coerce(expected = {}, expr_ty = {})",
            expected.repr(fcx.ccx.tcx),
index c3f4937d26b045d9e788bfee33102aaebc456f41..4eddf8ae97a9019bfd2eaed2c1320f7bceabf424 100644 (file)
@@ -184,6 +184,8 @@ pub struct Inherited<'a, 'tcx: 'a> {
     // def-id of the closure, so that once we decide, we can easily go
     // back and process them.
     deferred_call_resolutions: RefCell<DefIdMap<Vec<DeferredCallResolutionHandler<'tcx>>>>,
+
+    deferred_cast_checks: RefCell<Vec<CastCheck<'tcx>>>,
 }
 
 trait DeferredCallResolution<'tcx> {
@@ -192,6 +194,15 @@ trait DeferredCallResolution<'tcx> {
 
 type DeferredCallResolutionHandler<'tcx> = Box<DeferredCallResolution<'tcx>+'tcx>;
 
+/// Reifies a cast check to be checked once we have full type information for
+/// a function context.
+struct CastCheck<'tcx> {
+    expr: ast::Expr,
+    expr_ty: Ty<'tcx>,
+    cast_ty: Ty<'tcx>,
+    span: Span,
+}
+
 /// When type-checking an expression, we propagate downward
 /// whatever type hint we are able in the form of an `Expectation`.
 #[derive(Copy)]
@@ -399,6 +410,7 @@ fn new(tcx: &'a ty::ctxt<'tcx>,
             fn_sig_map: RefCell::new(NodeMap()),
             fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
             deferred_call_resolutions: RefCell::new(DefIdMap()),
+            deferred_cast_checks: RefCell::new(Vec::new()),
         }
     }
 
@@ -508,6 +520,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             vtable::select_all_fcx_obligations_and_apply_defaults(&fcx);
             upvar::closure_analyze_fn(&fcx, fn_id, decl, body);
             vtable::select_all_fcx_obligations_or_error(&fcx);
+            fcx.check_casts();
             regionck::regionck_fn(&fcx, fn_id, fn_span, decl, body);
             writeback::resolve_type_vars_in_fn(&fcx, decl, body);
         }
@@ -1053,11 +1066,7 @@ fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 }
 
 
-fn check_cast_inner<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                              span: Span,
-                              t_1: Ty<'tcx>,
-                              t_e: Ty<'tcx>,
-                              e: &ast::Expr) {
+fn check_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, cast: &CastCheck<'tcx>) {
     fn cast_through_integer_err<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                           span: Span,
                                           t_1: Ty<'tcx>,
@@ -1070,6 +1079,33 @@ fn cast_through_integer_err<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         }, t_e, None);
     }
 
+    let span = cast.span;
+    let e = &cast.expr;
+    let t_e = structurally_resolved_type(fcx, span, cast.expr_ty);
+    let t_1 = structurally_resolved_type(fcx, span, cast.cast_ty);
+
+    // Check for trivial casts.
+    if !ty::type_has_ty_infer(t_1) {
+        if let Ok(()) = coercion::mk_assignty(fcx, e, t_e, t_1) {
+            if ty::type_is_numeric(t_1) && ty::type_is_numeric(t_e) {
+                fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_NUMERIC_CAST,
+                                        e.id,
+                                        span,
+                                        format!("trivial numeric cast: {} as {}",
+                                                fcx.infcx().ty_to_string(t_e),
+                                                fcx.infcx().ty_to_string(t_1)));
+            } else {
+                fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_CAST,
+                                        e.id,
+                                        span,
+                                        format!("trivial cast: {} as {}",
+                                                fcx.infcx().ty_to_string(t_e),
+                                                fcx.infcx().ty_to_string(t_1)));
+            }
+            return;
+        }
+    }
+
     let t_e_is_bare_fn_item = ty::type_is_bare_fn_item(t_e);
     let t_e_is_scalar = ty::type_is_scalar(t_e);
     let t_e_is_integral = ty::type_is_integral(t_e);
@@ -1085,18 +1121,17 @@ fn cast_through_integer_err<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
 
     if t_e_is_bare_fn_item && t_1_is_bare_fn {
-        demand::coerce(fcx, e.span, t_1, &*e);
+        demand::coerce(fcx, e.span, t_1, &e);
     } else if t_1_is_char {
         let t_e = fcx.infcx().shallow_resolve(t_e);
         if t_e.sty != ty::ty_uint(ast::TyU8) {
             fcx.type_error_message(span, |actual| {
-                format!("only `u8` can be cast as \
-                         `char`, not `{}`", actual)
+                format!("only `u8` can be cast as `char`, not `{}`", actual)
             }, t_e, None);
         }
     } else if t_1.sty == ty::ty_bool {
         span_err!(fcx.tcx().sess, span, E0054,
-            "cannot cast as `bool`, compare with zero instead");
+                  "cannot cast as `bool`, compare with zero instead");
     } else if t_1_is_float && (t_e_is_scalar || t_e_is_c_enum) && !(
         t_e_is_integral || t_e_is_float || t_e.sty == ty::ty_bool) {
         // Casts to float must go through an integer or boolean
@@ -1145,7 +1180,7 @@ fn types_compatible<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
                 /* this case is allowed */
             }
             _ => {
-                demand::coerce(fcx, e.span, t_1, &*e);
+                demand::coerce(fcx, e.span, t_1, &e);
             }
         }
     } else if !(t_e_is_scalar && t_1_is_trivial) {
@@ -1162,49 +1197,6 @@ fn types_compatible<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
     }
 }
 
-fn check_cast<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
-                       cast_expr: &ast::Expr,
-                       e: &'tcx ast::Expr,
-                       t: &ast::Ty) {
-    let id = cast_expr.id;
-    let span = cast_expr.span;
-
-    // Find the type of `e`. Supply hints based on the type we are casting to,
-    // if appropriate.
-    let t_1 = fcx.to_ty(t);
-    let t_1 = structurally_resolved_type(fcx, span, t_1);
-
-    check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1));
-
-    let t_e = fcx.expr_ty(e);
-
-    debug!("t_1={}", fcx.infcx().ty_to_string(t_1));
-    debug!("t_e={}", fcx.infcx().ty_to_string(t_e));
-
-    if ty::type_is_error(t_e) {
-        fcx.write_error(id);
-        return
-    }
-
-    if !fcx.type_is_known_to_be_sized(t_1, cast_expr.span) {
-        report_cast_to_unsized_type(fcx, span, t.span, e.span, t_1, t_e, id);
-        return
-    }
-
-    if ty::type_is_trait(t_1) {
-        // This will be looked up later on.
-        vtable::check_object_cast(fcx, cast_expr, e, t_1);
-        fcx.write_ty(id, t_1);
-        return
-    }
-
-    let t_1 = structurally_resolved_type(fcx, span, t_1);
-    let t_e = structurally_resolved_type(fcx, span, t_e);
-
-    check_cast_inner(fcx, span, t_1, t_e, e);
-    fcx.write_ty(id, t_1);
-}
-
 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
     fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
 
@@ -1372,7 +1364,8 @@ fn remove_deferred_call_resolutions(&self,
     }
 
     pub fn tag(&self) -> String {
-        format!("{:?}", self as *const FnCtxt)
+        let self_ptr: *const FnCtxt = self;
+        format!("{:?}", self_ptr)
     }
 
     pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
@@ -1416,14 +1409,6 @@ pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
         self.inh.node_types.borrow_mut().insert(node_id, ty);
     }
 
-    pub fn write_object_cast(&self,
-                             key: ast::NodeId,
-                             trait_ref: ty::PolyTraitRef<'tcx>) {
-        debug!("write_object_cast key={} trait_ref={}",
-               key, trait_ref.repr(self.tcx()));
-        self.inh.object_cast_map.borrow_mut().insert(key, trait_ref);
-    }
-
     pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
         if !substs.substs.is_noop() {
             debug!("write_substs({}, {}) in fcx {}",
@@ -1923,6 +1908,15 @@ pub fn lookup_tup_field_ty(&self,
         o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
                .map(|t| self.normalize_associated_types_in(span, &t))
     }
+
+    fn check_casts(&self) {
+        let mut deferred_cast_checks = self.inh.deferred_cast_checks.borrow_mut();
+        for check in deferred_cast_checks.iter() {
+            check_cast(self, check);
+        }
+
+        deferred_cast_checks.clear();
+    }
 }
 
 impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
@@ -3828,7 +3822,33 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
         if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
             check_expr_with_hint(fcx, &**count_expr, tcx.types.uint);
         }
-        check_cast(fcx, expr, &**e, &**t);
+
+        // Find the type of `e`. Supply hints based on the type we are casting to,
+        // if appropriate.
+        let t_1 = fcx.to_ty(t);
+        let t_1 = structurally_resolved_type(fcx, expr.span, t_1);
+        check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1));
+        let t_e = fcx.expr_ty(e);
+
+        // Eagerly check for some obvious errors.
+        if ty::type_is_error(t_e) {
+            fcx.write_error(id);
+        } else if !fcx.type_is_known_to_be_sized(t_1, expr.span) {
+            report_cast_to_unsized_type(fcx, expr.span, t.span, e.span, t_1, t_e, id);
+        } else {
+            // Write a type for the whole expression, assuming everything is going
+            // to work out Ok.
+            fcx.write_ty(id, t_1);
+
+            // Defer other checks until we're done type checking.
+            let mut deferred_cast_checks = fcx.inh.deferred_cast_checks.borrow_mut();
+            deferred_cast_checks.push(CastCheck {
+                expr: (**e).clone(),
+                expr_ty: t_e,
+                cast_ty: t_1,
+                span: expr.span,
+            });
+        }
       }
       ast::ExprVec(ref args) => {
         let uty = expected.to_option(fcx).and_then(|uty| {
@@ -4461,6 +4481,7 @@ fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     check_expr_with_hint(fcx, e, declty);
     demand::coerce(fcx, e.span, declty, e);
     vtable::select_all_fcx_obligations_or_error(fcx);
+    fcx.check_casts();
     regionck::regionck_expr(fcx, e);
     writeback::resolve_type_vars_in_expr(fcx, e);
 }
@@ -4560,6 +4581,8 @@ fn disr_in_range(ccx: &CrateCtxt,
                      ty: attr::IntType,
                      disr: ty::Disr) -> bool {
         fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
+            #![allow(trivial_numeric_cast)]
+
             match ty {
                 ast::TyU8 => disr as u8 as Disr == disr,
                 ast::TyU16 => disr as u16 as Disr == disr,
@@ -4588,6 +4611,7 @@ fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                           id: ast::NodeId,
                           hint: attr::ReprAttr)
                           -> Vec<Rc<ty::VariantInfo<'tcx>>> {
+        #![allow(trivial_numeric_cast)]
         use std::num::Int;
 
         let rty = ty::node_id_to_type(ccx.tcx, id);
index 963be9aa2e2d2b0cb77e2320f19796e5ebdb2c1e..2858dc9b569fe1adaa22ffb7cde199e4e375404a 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use check::{FnCtxt};
-use check::demand;
 use middle::traits::{self, ObjectSafetyViolation, MethodViolationCode};
 use middle::traits::{Obligation, ObligationCause};
 use middle::traits::report_fulfillment_errors;
 use util::nodemap::FnvHashSet;
 use util::ppaux::{Repr, UserString};
 
-pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                   cast_expr: &ast::Expr,
-                                   source_expr: &ast::Expr,
-                                   target_object_ty: Ty<'tcx>)
-{
-    let tcx = fcx.tcx();
-    debug!("check_object_cast(cast_expr={}, target_object_ty={})",
-           cast_expr.repr(tcx),
-           target_object_ty.repr(tcx));
-
-    // Look up vtables for the type we're casting to,
-    // passing in the source and target type.  The source
-    // must be a pointer type suitable to the object sigil,
-    // e.g.: `&x as &Trait` or `box x as Box<Trait>`
-
-    // First, construct a fresh type that we can feed into `<expr>`
-    // within `<expr> as <type>` to inform type inference (e.g. to
-    // tell it that we are expecting a `Box<_>` or an `&_`).
-    let fresh_ty = fcx.infcx().next_ty_var();
-    let (object_trait_ty, source_expected_ty) = match target_object_ty.sty {
-        ty::ty_uniq(object_trait_ty) => {
-            (object_trait_ty, ty::mk_uniq(fcx.tcx(), fresh_ty))
-        }
-        ty::ty_rptr(target_region, ty::mt { ty: object_trait_ty,
-                                            mutbl: target_mutbl }) => {
-            (object_trait_ty,
-             ty::mk_rptr(fcx.tcx(),
-                         target_region, ty::mt { ty: fresh_ty,
-                                                 mutbl: target_mutbl }))
-        }
-        _ => {
-            fcx.tcx().sess.span_bug(source_expr.span, "expected object type");
-        }
-    };
-
-    let source_ty = fcx.expr_ty(source_expr);
-    debug!("check_object_cast pre unify source_ty={}", source_ty.repr(tcx));
-
-    // This ensures that the source_ty <: source_expected_ty, which
-    // will ensure e.g. that &'a T <: &'b T when doing `&'a T as &'b Trait`
-    //
-    // FIXME (pnkfelix): do we need to use suptype_with_fn in order to
-    // override the error message emitted when the types do not work
-    // out in the manner desired?
-    demand::suptype(fcx, source_expr.span, source_expected_ty, source_ty);
-
-    debug!("check_object_cast postunify source_ty={}", source_ty.repr(tcx));
-
-    let object_trait = object_trait(&object_trait_ty);
-
-    // Ensure that if Ptr<T> is cast to Ptr<Trait>, then T : Trait.
-    push_cast_obligation(fcx, cast_expr, object_trait, fresh_ty);
-    check_object_safety(tcx, object_trait, source_expr.span);
-
-    fn object_trait<'a, 'tcx>(t: &'a Ty<'tcx>) -> &'a ty::TyTrait<'tcx> {
-        match t.sty {
-            ty::ty_trait(ref ty_trait) => &**ty_trait,
-            _ => panic!("expected ty_trait")
-        }
-    }
-
-    fn push_cast_obligation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                      cast_expr: &ast::Expr,
-                                      object_trait: &ty::TyTrait<'tcx>,
-                                      referent_ty: Ty<'tcx>) {
-        let object_trait_ref =
-            register_object_cast_obligations(fcx,
-                                             cast_expr.span,
-                                             object_trait,
-                                             referent_ty);
-
-        // Finally record the object_trait_ref for use during trans
-        // (it would prob be better not to do this, but it's just kind
-        // of a pain to have to reconstruct it).
-        fcx.write_object_cast(cast_expr.id, object_trait_ref);
-    }
-}
 
 // Check that a trait is 'object-safe'. This should be checked whenever a trait object
 // is created (by casting or coercion, etc.). A trait is object-safe if all its
index cdd8457687ac60d1b6cf9866303cb34083453d44..cfa84de5ca7c9f37577877f1bc6f38ea347300ca 100644 (file)
@@ -308,8 +308,8 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
         };
         (*((*renderer).opaque as *mut hoedown_html_renderer_state)).opaque
                 = &mut opaque as *mut _ as *mut libc::c_void;
-        (*renderer).blockcode = Some(block as blockcodefn);
-        (*renderer).header = Some(header as headerfn);
+        (*renderer).blockcode = Some(block);
+        (*renderer).header = Some(header);
 
         let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16);
         hoedown_document_render(document, ob, s.as_ptr(),
@@ -380,8 +380,8 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) {
     unsafe {
         let ob = hoedown_buffer_new(DEF_OUNIT);
         let renderer = hoedown_html_renderer_new(0, 0);
-        (*renderer).blockcode = Some(block as blockcodefn);
-        (*renderer).header = Some(header as headerfn);
+        (*renderer).blockcode = Some(block);
+        (*renderer).header = Some(header);
         (*((*renderer).opaque as *mut hoedown_html_renderer_state)).opaque
                 = tests as *mut _ as *mut libc::c_void;
 
@@ -501,10 +501,10 @@ pub fn plain_summary_line(md: &str) -> String {
     unsafe {
         let ob = hoedown_buffer_new(DEF_OUNIT);
         let mut plain_renderer: hoedown_renderer = ::std::mem::zeroed();
-        let renderer = &mut plain_renderer as *mut hoedown_renderer;
+        let renderer: *mut hoedown_renderer = &mut plain_renderer;
         (*renderer).opaque = ob as *mut libc::c_void;
-        (*renderer).link = Some(link as linkfn);
-        (*renderer).normal_text = Some(normal_text as normaltextfn);
+        (*renderer).link = Some(link);
+        (*renderer).normal_text = Some(normal_text);
 
         let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16);
         hoedown_document_render(document, ob, md.as_ptr(),
index abbfc82319f5b30e24035442aedaaa532c0e80a4..17c414485407b146325ce97aa35d60f726ece9ef 100644 (file)
@@ -2429,7 +2429,10 @@ pub trait ToJson {
 macro_rules! to_json_impl_i64 {
     ($($t:ty), +) => (
         $(impl ToJson for $t {
-            fn to_json(&self) -> Json { Json::I64(*self as i64) }
+            fn to_json(&self) -> Json {
+                #![allow(trivial_numeric_cast)]
+                Json::I64(*self as i64)
+            }
         })+
     )
 }
@@ -2439,7 +2442,10 @@ fn to_json(&self) -> Json { Json::I64(*self as i64) }
 macro_rules! to_json_impl_u64 {
     ($($t:ty), +) => (
         $(impl ToJson for $t {
-            fn to_json(&self) -> Json { Json::U64(*self as u64) }
+            fn to_json(&self) -> Json {
+                #![allow(trivial_numeric_cast)]
+                Json::U64(*self as u64)
+            }
         })+
     )
 }
index 90eca6168f266cd8c4c82ba8de0f76a5f58c914b..228b885b653c0671e6bd6e997d7498b07a6fc682 100644 (file)
 #![feature(no_std)]
 #![no_std]
 
+#![allow(trivial_cast)]
+#![allow(trivial_numeric_cast)]
 #![deny(missing_docs)]
 
 #[cfg(test)] extern crate test;
index ef811f832b394133a47b69f3591624db41ed8160..b77c8d50997f5edd07a01879cb022d31af248eb1 100644 (file)
@@ -337,10 +337,10 @@ pub fn set_stderr(_stderr: Box<Writer + Send>) -> Option<Box<Writer + Send>> {
 //      })
 //  })
 fn with_task_stdout<F>(f: F) where F: FnOnce(&mut Writer) -> IoResult<()> {
-    let mut my_stdout = LOCAL_STDOUT.with(|slot| {
+    let mut my_stdout: Box<Writer + Send> = LOCAL_STDOUT.with(|slot| {
         slot.borrow_mut().take()
     }).unwrap_or_else(|| {
-        box stdout() as Box<Writer + Send>
+        box stdout()
     });
     let result = f(&mut *my_stdout);
     let mut var = Some(my_stdout);
index e52e68dad23faec8358bd4c7f63b501eb1e39e49..86b1d031f688bee52a99417607893f6aa76827c2 100644 (file)
@@ -73,7 +73,7 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int {
     use thread::Thread;
 
     let something_around_the_top_of_the_stack = 1;
-    let addr = &something_around_the_top_of_the_stack as *const int;
+    let addr = &something_around_the_top_of_the_stack as *const _ as *const int;
     let my_stack_top = addr as uint;
 
     // FIXME #11359 we just assume that this thread has a stack of a
index 1abe8d0a3c1b1352e77100adb0f246b130981a04..6a00fff186002f4383ec2b0e24da9556d3b25dcd 100644 (file)
@@ -284,7 +284,7 @@ pub struct ExpnInfo {
 
 impl ExpnId {
     pub fn from_llvm_cookie(cookie: c_uint) -> ExpnId {
-        ExpnId(cookie as u32)
+        ExpnId(cookie)
     }
 
     pub fn to_llvm_cookie(self) -> i32 {
@@ -376,7 +376,7 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
                         match bytes_per_diff {
                             1 => for diff in diff_iter { try! { (diff.0 as u8).encode(s) } },
                             2 => for diff in diff_iter { try! { (diff.0 as u16).encode(s) } },
-                            4 => for diff in diff_iter { try! { (diff.0 as u32).encode(s) } },
+                            4 => for diff in diff_iter { try! { diff.0.encode(s) } },
                             _ => unreachable!()
                         }
                     }
@@ -650,7 +650,7 @@ pub fn span_to_lines(&self, sp: Span) -> FileLines {
         let lo = self.lookup_char_pos(sp.lo);
         let hi = self.lookup_char_pos(sp.hi);
         let mut lines = Vec::new();
-        for i in lo.line - 1..hi.line as usize {
+        for i in lo.line - 1..hi.line {
             lines.push(i);
         };
         FileLines {file: lo.file, lines: lines}
index 35449bde0b2e086e870198f5874dc882838a8e23..b679456b3537ba00ea448ec2ca0706e7da07bbd3 100644 (file)
@@ -264,7 +264,7 @@ pub fn $fld(v: $t) -> Box<MacResult> {
                     box MacEager {
                         $fld: Some(v),
                         ..Default::default()
-                    } as Box<MacResult>
+                    }
                 }
             )*
         }
@@ -330,7 +330,7 @@ impl DummyResult {
     /// Use this as a return value after hitting any errors and
     /// calling `span_err`.
     pub fn any(sp: Span) -> Box<MacResult+'static> {
-        box DummyResult { expr_only: false, span: sp } as Box<MacResult+'static>
+        box DummyResult { expr_only: false, span: sp }
     }
 
     /// Create a default MacResult that can only be an expression.
@@ -339,7 +339,7 @@ pub fn any(sp: Span) -> Box<MacResult+'static> {
     /// if an error is encountered internally, the user will receive
     /// an error that they also used it in the wrong place.
     pub fn expr(sp: Span) -> Box<MacResult+'static> {
-        box DummyResult { expr_only: true, span: sp } as Box<MacResult+'static>
+        box DummyResult { expr_only: true, span: sp }
     }
 
     /// A plain dummy expression.
index c11ffe66e6c392305450dd13706994e6ba3ed812..1aceec310e1afb1f8137e0a4a1412b7c3d5e500b 100644 (file)
@@ -262,6 +262,7 @@ fn to_source_with_hygiene(&self) -> String {
         (unsigned, $t:ty, $tag:expr) => (
             impl ToSource for $t {
                 fn to_source(&self) -> String {
+                    #![allow(trivial_numeric_cast)]
                     let lit = ast::LitInt(*self as u64, ast::UnsignedIntLit($tag));
                     pprust::lit_to_string(&dummy_spanned(lit))
                 }
index 5940b791843797cacf97c7225dd9a413e27d74c8..1e53db6030143bbcad443e12b866da8fa706c273 100644 (file)
@@ -169,7 +169,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
                 // Weird, but useful for X-macros.
                 return box ParserAnyMacro {
                     parser: RefCell::new(p),
-                } as Box<MacResult+'cx>
+                }
               }
               Failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo {
                 best_fail_spot = sp;
index e0953a8ace68d5c646ee23fa436766fca91b9ad5..0843713681bbdaad8b27502a7b8c34956ba151de 100644 (file)
@@ -758,7 +758,7 @@ fn scan_hex_digits(&mut self,
                 self.err_span_char(self.last_pos, self.pos,
                               "illegal character in numeric character escape", c);
                 0
-            }) as u32;
+            });
             self.bump();
         }
 
@@ -887,7 +887,7 @@ fn scan_unicode_escape(&mut self, delim: char) -> bool {
                     self.fatal_span_char(self.last_pos, self.pos,
                                    "illegal character in unicode escape", c);
                 }
-            }) as u32;
+            });
             self.bump();
             count += 1;
         }
index 4ae5e0faa310552144a04720e950c6c5d88d8dcd..44097ffeb205921da76a16ec591b2d2a1831862e 100644 (file)
@@ -865,7 +865,7 @@ pub fn bump(&mut self) {
         } else {
             // Avoid token copies with `replace`.
             let buffer_start = self.buffer_start as usize;
-            let next_index = (buffer_start + 1) & 3 as usize;
+            let next_index = (buffer_start + 1) & 3;
             self.buffer_start = next_index as isize;
 
             let placeholder = TokenAndSpan {
index 828d085fd432eb835fb5bf399ea8e0995d8260ee..5941f044a078a8975c8926b607284910bdcaea0c 100644 (file)
@@ -2831,7 +2831,7 @@ pub fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> {
             ast::LitBinary(ref v) => {
                 let mut escaped: String = String::new();
                 for &ch in &**v {
-                    escaped.extend(ascii::escape_default(ch as u8)
+                    escaped.extend(ascii::escape_default(ch)
                                          .map(|c| c as char));
                 }
                 word(&mut self.s, &format!("b\"{}\"", escaped))
index c907b87bc3c66e9f3ec9f5a9dd81abf8cadd559c..41e066cc94a92b2aab65ea336f0c2b16639bffe6 100644 (file)
@@ -103,7 +103,7 @@ fn flush(&mut self) -> io::Result<()> {
 /// opened.
 pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
     TerminfoTerminal::new(WriterWrapper {
-        wrapped: box std::io::stdout() as Box<Write + Send>,
+        wrapped: box std::io::stdout(),
     })
 }
 
@@ -112,14 +112,14 @@ pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
 /// opened.
 pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
     let ti = TerminfoTerminal::new(WriterWrapper {
-        wrapped: box std::io::stdout() as Box<Write + Send>,
+        wrapped: box std::io::stdout(),
     });
 
     match ti {
         Some(t) => Some(t),
         None => {
             WinConsole::new(WriterWrapper {
-                wrapped: box std::io::stdout() as Box<Write + Send>,
+                wrapped: box std::io::stdout(),
             })
         }
     }
@@ -130,7 +130,7 @@ pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
 /// opened.
 pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send>> {
     TerminfoTerminal::new(WriterWrapper {
-        wrapped: box std::io::stderr() as Box<Write + Send>,
+        wrapped: box std::io::stderr(),
     })
 }
 
@@ -139,14 +139,14 @@ pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send>> {
 /// opened.
 pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send>> {
     let ti = TerminfoTerminal::new(WriterWrapper {
-        wrapped: box std::io::stderr() as Box<Write + Send>,
+        wrapped: box std::io::stderr(),
     });
 
     match ti {
         Some(t) => Some(t),
         None => {
             WinConsole::new(WriterWrapper {
-                wrapped: box std::io::stderr() as Box<Write + Send>,
+                wrapped: box std::io::stderr(),
             })
         }
     }
index 309320b52ffe4aa641abdf485537f5452eb7f64a..1d6657d5932c0d5a410282254e8a7056571dc148 100644 (file)
@@ -190,7 +190,7 @@ pub fn new(out: T) -> Option<Box<Terminal<T>+Send+'static>> {
                         out: out,
                         ti: msys_terminfo(),
                         num_colors: 8,
-                    } as Box<Terminal<T>+Send>)
+                    })
                 },
                 _ => {
                     debug!("error finding terminfo entry: {:?}", err);
@@ -213,7 +213,7 @@ pub fn new(out: T) -> Option<Box<Terminal<T>+Send+'static>> {
 
         return Some(box TerminfoTerminal {out: out,
                                           ti: inf,
-                                          num_colors: nc} as Box<Terminal<T>+Send>);
+                                          num_colors: nc});
     }
 
     fn dim_if_necessary(&self, color: color::Color) -> color::Color {
index cc9a2880b5d07d10b5f8502315b1f9e9951f0798..8d0a9e6e9717d502d2e7b17fa1dd34dceddc90e4 100644 (file)
@@ -186,7 +186,7 @@ macro_rules! try { ($e:expr) => (
     let magic = try!(read_le_u16(file));
     if magic != 0x011A {
         return Err(format!("invalid magic number: expected {:x}, found {:x}",
-                           0x011A as usize, magic as usize));
+                           0x011A_usize, magic as usize));
     }
 
     let names_bytes          = try!(read_le_u16(file)) as int;
index 402774321bfcbccbd1475b2b46a7b86915c8ab2e..c48c7e413d03baa961ec62c60a07b19e82da678c 100644 (file)
@@ -1021,7 +1021,7 @@ pub fn fmt_metrics(&self) -> String {
         let MetricMap(ref mm) = *self;
         let v : Vec<String> = mm.iter()
             .map(|(k,v)| format!("{}: {} (+/- {})", *k,
-                                 v.value as f64, v.noise as f64))
+                                 v.value, v.noise))
             .collect();
         v.connect(", ")
     }
index 473739c919d64ee27fc4e3e3e40a85e3b0e29426..44af43be7877344cfd878700984662adb9f60058 100644 (file)
@@ -32,11 +32,11 @@ pub trait Subcommand {
 
 /// Create a Subcommand object based on its name.
 pub fn parse_name(name: &str) -> Option<Box<Subcommand>> {
-    for parser in [
-        help::parse_cmd as fn(&str) -> Option<Box<Subcommand>>,
-        build::parse_cmd as fn(&str) -> Option<Box<Subcommand>>,
-        serve::parse_cmd as fn(&str) -> Option<Box<Subcommand>>,
-        test::parse_cmd as fn(&str) -> Option<Box<Subcommand>>].iter() {
+    let cmds: [fn(&str) -> Option<Box<Subcommand>>; 4] = [help::parse_cmd,
+                                                          build::parse_cmd,
+                                                          serve::parse_cmd,
+                                                          test::parse_cmd];
+    for parser in cmds.iter() {
         let parsed = (*parser)(name);
         if parsed.is_some() { return parsed }
     }
index 560844332a128d4718362b8a7debb61deb7436a0..d66cfe9bf636b716867370a728bd5f52091142c6 100644 (file)
@@ -21,6 +21,6 @@ fn f() {}
 }
 
 pub fn foo() {
-    let a = &1 as &inner::Trait;
+    let a = &1i as &inner::Trait;
     a.f();
 }
index d7bb806999c74abe7291eac8f090a492a53ac417..3f994102a173e0853f052c0b7ba9f3d65e0864bc 100644 (file)
@@ -22,11 +22,11 @@ fn main() {
     //~| expected u8
     //~| found array of 1 elements
 
-    let local = [0];
+    let local: [u8; 1] = [0];
     let _v = &local as *mut u8;
     //~^ ERROR mismatched types
     //~| expected `*mut u8`
-    //~| found `&[_; 1]`
+    //~| found `&[u8; 1]`
     //~| expected u8,
     //~| found array of 1 elements
 }
index 6d2cfcab04e36aa757cf40418f7127e917453590..a4e0f69b63b39e0b55c2353ca65c1d95221c6180 100644 (file)
@@ -19,8 +19,7 @@ fn foo(value: *const X) -> *const X {
 }
 
 static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
-//~^ ERROR cannot refer to other statics by value
-//~| ERROR the trait `core::marker::Sync` is not implemented for the type
+//~^ ERROR the trait `core::marker::Sync` is not implemented for the type
 //~| ERROR function calls in statics are limited to struct and enum constructors
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-5543.rs b/src/test/compile-fail/issue-5543.rs
deleted file mode 100644 (file)
index c27362e..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-trait Foo { fn foo(&self) {} }
-impl Foo for u8 {}
-
-fn main() {
-    // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
-    let r: Box<Foo> = Box::new(5);
-    let _m: Box<Foo> = r as Box<Foo>;
-    //~^ ERROR `core::marker::Sized` is not implemented for the type `Foo`
-}
index dffc8fa2abd70d95def12e4df2eb40fdf247cea3..71494fd5f38dcef2116756b89e57a7c6edabdb7f 100644 (file)
@@ -28,6 +28,7 @@ fn f<T>(val: T) {
     let a = &t as &Gettable<T>;
     //~^ ERROR the trait `core::marker::Send` is not implemented
     //~^^ ERROR the trait `core::marker::Copy` is not implemented
+    //~^^^ ERROR the parameter type `T` may not live long enough
 }
 
 fn g<T>(val: T) {
index 13ee3f163616e8ccf207d9f283bed3fbebd30a4b..ba1b7f03b0f419b2fe15570b7594b77bf4a93f7d 100644 (file)
@@ -86,6 +86,6 @@ fn f() {}
 }
 
 pub fn foo() {
-    let a = &1 as &inner::Trait;
+    let a: &inner::Trait = &1_isize;
     a.f();
 }
diff --git a/src/test/compile-fail/lint-unnecessary-casts.rs b/src/test/compile-fail/lint-unnecessary-casts.rs
deleted file mode 100644 (file)
index b3cf825..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![forbid(unused_typecasts)]
-
-fn foo_i32(_: i32) {}
-
-fn foo_u64(a: u64) {
-    let b: i32 = a as i32;
-    foo_i32(b as i32); //~ ERROR: unnecessary type cast
-}
-
-fn main() {
-    let x: u64 = 1;
-    let y: u64 = x as u64; //~ ERROR: unnecessary type cast
-    foo_u64(y as u64); //~ ERROR: unnecessary type cast
-}
index ac4b8a5f3090b09102e7452c2af3277ebe1b339c..addeba03ab87025493ac7eedb62b944433a71bbe 100644 (file)
@@ -10,7 +10,7 @@
 
 #![deny(unused_variables)]
 #![deny(unused_assignments)]
-#![allow(dead_code, non_camel_case_types)]
+#![allow(dead_code, non_camel_case_types, trivial_numeric_cast)]
 
 fn f1(x: isize) {
     //~^ ERROR unused variable: `x`
index 976717249e8eb2400fe6e307b625bd0fc8e73e18..3b0e5786f3db3bc16a6f6fe0cf0df939789f2cb7 100644 (file)
@@ -12,6 +12,7 @@
 
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
+#![allow(trivial_cast)]
 
 trait Bar {
     fn bar(self);
index f3b5ccabe79eb7afef291eea61b5b03b2e599f17..253132e5f07d02ed93ea98fcb613cb440934a750 100644 (file)
@@ -24,6 +24,7 @@ impl<'a, T> X for B<'a, T> {}
 
 fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
     box B(&*v) as Box<X> //~ ERROR the parameter type `T` may not live long enough
+        //~^ ERROR the parameter type `T` may not live long enough
 }
 
 fn main() {}
index fc18095fc8336585a582c9e0d51edf0fa3ab340d..924044647d84a08473c547d8da2366d2bb8b34b6 100644 (file)
@@ -19,6 +19,7 @@
 fn make_object1<A:SomeTrait>(v: A) -> Box<SomeTrait+'static> {
     box v as Box<SomeTrait+'static>
         //~^ ERROR the parameter type `A` may not live long enough
+        //~^^ ERROR the parameter type `A` may not live long enough
 }
 
 fn make_object2<'a,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'a> {
@@ -28,6 +29,7 @@ fn make_object2<'a,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'a> {
 fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'b> {
     box v as Box<SomeTrait+'b>
         //~^ ERROR the parameter type `A` may not live long enough
+        //~^^ ERROR the parameter type `A` may not live long enough
 }
 
 fn main() { }
index 8ff514e04e360fbcef36cf6b39a4d61089b44214..8cc531625d17956c0d01223736884c2601774dc1 100644 (file)
@@ -20,7 +20,7 @@ fn add(&self, other: &i32) -> i32 { *self + *other }
 }
 
 fn main() {
-    let x = 5;
+    let x: i32 = 5;
     let y = x as MyAdd<i32>;
     //~^ ERROR as `MyAdd<i32>`
 }
index 97e67cd2eae273b1e9b06c03ef53138059305e94..cac52306d6ae0e1a4d08dfd13763c4552f6099a7 100644 (file)
@@ -10,6 +10,8 @@
 
 // Issue #14893. Tests that casts from vectors don't behave strangely in the
 // presence of the `_` type shorthand notation.
+// Update: after a change to the way casts are done, we have more type information
+// around and so the errors here are no longer exactly the same.
 
 struct X {
     y: [u8; 2],
@@ -18,12 +20,14 @@ struct X {
 fn main() {
     let x1 = X { y: [0, 0] };
 
-    let p1: *const u8 = &x1.y as *const _;  //~ ERROR mismatched types
+    // No longer a type mismatch - the `_` can be fully resolved by type inference.
+    let p1: *const u8 = &x1.y as *const _;
     let t1: *const [u8; 2] = &x1.y as *const _;
     let h1: *const [u8; 2] = &x1.y as *const [u8; 2];
 
     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 mismatched types
     let t1: *mut [u8; 2] = &mut x1.y as *mut _;
     let h1: *mut [u8; 2] = &mut x1.y as *mut [u8; 2];
index bf26fc23d3c16a1607af005ebe04e6cb26aad378..d4cbd255e34c2861bcc35fee75c15dc6134a9038 100644 (file)
@@ -291,15 +291,15 @@ fn main() {
     let slice2 = &*vec2;
 
     // Trait Objects
-    let box_trait = (box 0) as Box<Trait1>;
-    let ref_trait = &0 as &Trait1;
-    let mut mut_int1 = 0;
+    let box_trait = (box 0_isize) as Box<Trait1>;
+    let ref_trait = &0_isize as &Trait1;
+    let mut mut_int1 = 0_isize;
     let mut_ref_trait = (&mut mut_int1) as &mut Trait1;
 
-    let generic_box_trait = (box 0) as Box<Trait2<i32, Mod1::Struct2>>;
-    let generic_ref_trait  = (&0) as &Trait2<Struct1, Struct1>;
+    let generic_box_trait = (box 0_isize) as Box<Trait2<i32, Mod1::Struct2>>;
+    let generic_ref_trait  = (&0_isize) as &Trait2<Struct1, Struct1>;
 
-    let mut generic_mut_ref_trait_impl = 0;
+    let mut generic_mut_ref_trait_impl = 0_isize;
     let generic_mut_ref_trait = (&mut generic_mut_ref_trait_impl) as
         &mut Trait2<Mod1::Mod2::Struct3, GenericStruct<usize, isize>>;
 
index 0a20300e4f4de797ebe8dbd3eccba7fd3ed28547..42b2fe806e95f605bbd91febc4a4737d8fa117e4 100644 (file)
@@ -21,5 +21,5 @@ fn foo<'a>(x: Box<Tr+ Sync + 'a>) -> Box<Tr+ Sync + 'a> { x }
 fn main() {
     let x: Box<Tr+ Sync>;
 
-    Box::new(1) as Box<Tr+ Sync>;
+    Box::new(1isize) as Box<Tr+ Sync>;
 }
index f81d4803f8fa491f686137f91f428b85dc5e507a..474a6782b616b3af1ea845be56b948c662cda0b6 100644 (file)
@@ -16,5 +16,5 @@ impl Foo for uint {}
 
 pub fn dummy() {
     // force the vtable to be created
-    let _x = &1 as &Foo;
+    let _x = &1u as &Foo;
 }
index 6a038927f4a486016b69128b6a1d48b0a4340e9d..0bec3af4273afad2819f79523f6bba194425dae8 100644 (file)
@@ -22,6 +22,6 @@ fn double(self: Box<uint>) -> uint { *self * 2 }
 }
 
 pub fn main() {
-    let x: Box<_> = box() (box 3 as Box<double>);
+    let x: Box<_> = box() (box 3u as Box<double>);
     assert_eq!(x.double(), 6);
 }
index a298a08a1b7a099bcce4a7e20e38168a0269a735..deb0c0d0dc0df884c4c0c2ba01d3df22e309b47e 100644 (file)
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 pub fn main() {
-    let x = 3;
+    let x: int = 3;
     println!("&x={:x}", (&x as *const int as uint));
 }
diff --git a/src/test/run-pass/infer-container-across-object-cast.rs b/src/test/run-pass/infer-container-across-object-cast.rs
deleted file mode 100644 (file)
index 7347ded..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Given `<expr> as Box<Trait>`, we should be able to infer that a
-// `Box<_>` is the expected type.
-
-// pretty-expanded FIXME #23616
-
-trait Foo { fn foo(&self) -> u32; }
-impl Foo for u32 { fn foo(&self) -> u32 { *self } }
-
-// (another impl to ensure trait-matching cannot just choose from a singleton set)
-impl Foo for  () { fn foo(&self) -> u32 { -176 } }
-
-trait Boxed { fn make() -> Self; }
-impl Boxed for Box<u32> { fn make() -> Self { Box::new(7) } }
-
-// (another impl to ensure trait-matching cannot just choose from a singleton set)
-impl Boxed for () { fn make() -> Self { () } }
-
-fn boxed_foo() {
-    let b7 = Boxed::make() as Box<Foo>;
-    assert_eq!(b7.foo(), 7);
-}
-
-trait Refed<'a,T> { fn make(&'a T) -> Self; }
-impl<'a> Refed<'a, u32> for &'a u32 { fn make(x: &'a u32) -> Self { x } }
-
-// (another impl to ensure trait-matching cannot just choose from a singleton set)
-impl<'a,'b> Refed<'a, ()> for &'b () { fn make(_: &'a ()) -> Self { static U: () = (); &U } }
-
-fn refed_foo() {
-    let a = 8;
-    let b7 = Refed::make(&a) as &Foo;
-    assert_eq!(b7.foo(), 8);
-}
-
-fn check_subtyping_works() {
-    fn inner<'short, 'long:'short>(_s: &'short u32,
-                                   l: &'long u32) -> &'short (Foo+'short) {
-        Refed::make(l) as &Foo
-    }
-
-    let a = 9;
-    let b = 10;
-    let r = inner(&b, &a);
-    assert_eq!(r.foo(), 9);
-}
-
-pub fn main() {
-    boxed_foo();
-    refed_foo();
-    check_subtyping_works();
-}
index 7bfd8e0ab718942444aef42f8adf76889799e924..f30991a19635251797a88dc08e06e72980789f41 100644 (file)
@@ -87,12 +87,12 @@ fn main() {
     assert_eq!(cc().unwrap(), 3);
     assert_eq!(dd().unwrap(), 3);
 
-    let i = box 32 as Box<A>;
+    let i = box 32i as Box<A>;
     assert_eq!(i.aaa(), 3);
-    let i = box 32 as Box<A>;
+    let i = box 32i as Box<A>;
     assert_eq!(i.bbb(), 3);
-    let i = box 32 as Box<A>;
+    let i = box 32i as Box<A>;
     assert_eq!(i.ccc().unwrap(), 3);
-    let i = box 32 as Box<A>;
+    let i = box 32i as Box<A>;
     assert_eq!(i.ddd().unwrap(), 3);
 }
index 59bca87bed0b61a8432cf09be88ff86ebaf2ea17..54773d71cbec0464575cabb24c2ea131181cadab 100644 (file)
@@ -41,7 +41,7 @@ fn new(inner: &Inner) -> Outer {
 }
 
 pub fn main() {
-    let inner = 5;
+    let inner: int = 5;
     let outer = Outer::new(&inner as &Inner);
     outer.inner.print();
 }
index 669a5cdfe304a174fc77cd973eb3cd68fefdb19d..6e88379f9a41b2676b33eb65002d535cb57376a5 100644 (file)
@@ -21,7 +21,7 @@ fn dummy(&self) { }
     impl X for int {}
 
     pub struct Z<'a>(Enum<&'a (X+'a)>);
-    fn foo() { let x = 42; let z = Z(Enum::A(&x as &X)); let _ = z; }
+    fn foo() { let x: int = 42; let z = Z(Enum::A(&x as &X)); let _ = z; }
 }
 
 mod b {
@@ -34,7 +34,7 @@ struct Y<'a>{
     }
 
     fn bar() {
-        let x = 42;
+        let x: int = 42;
         let _y = Y { x: Some(&x as &X) };
     }
 }
@@ -43,7 +43,7 @@ mod c {
     pub trait X { fn f(&self); }
     impl X for int { fn f(&self) {} }
     pub struct Z<'a>(Option<&'a (X+'a)>);
-    fn main() { let x = 42; let z = Z(Some(&x as &X)); let _ = z; }
+    fn main() { let x: int = 42; let z = Z(Some(&x as &X)); let _ = z; }
 }
 
 pub fn main() {}
index c8da4852ad35f5cdedbe9a67200a9eaac16869fd..de8d116255ba227a2ae18f36f8a9103871d2bca3 100644 (file)
@@ -33,6 +33,6 @@ fn foo(self) {}
 
 fn main() {
     let x: [int; 4] = [1,2,3,4];
-    let xptr = x.as_slice() as *const _;
+    let xptr = x.as_slice() as *const [int];
     xptr.foo();
 }
index f8a3ce7cda01708bb6e0ddf4faec337b4f974313..baf8c6e4c97913e459911e0940be8e47220833d3 100644 (file)
@@ -35,7 +35,7 @@ fn is<T:'static>(x: &Any) -> bool {
 }
 
 fn main() {
-    let x = box 22 as Box<Wrap>;
+    let x = box 22isize as Box<Wrap>;
     println!("x={}", x.get());
     let y = x.wrap();
 }
index efdd42c382c1538b54b1dda4aa7b643adcaab0a5..368842ed1b0304244841ae3d233670baf9351281 100644 (file)
@@ -42,7 +42,7 @@ fn do_it_imm(obj: &Foo, v: uint) {
 }
 
 pub fn main() {
-    let mut x = 22;
+    let mut x: uint = 22;
     let obj = &mut x as &mut Foo;
     do_it_mut(obj);
     do_it_imm(obj, 23);
index 63fb18a8ba2c248c83c645a2d2fc80fc1b5092b9..c87c79ca24edaab83cd7ac4aba3063342ff95493 100644 (file)
@@ -83,7 +83,10 @@ fn short<'b>(&'b self) -> int {
 }
 
 impl<'t> MakerTrait for Box<Trait<'t>+'static> {
-    fn mk() -> Box<Trait<'t>+'static> { box() (4,5) as Box<Trait> }
+    fn mk() -> Box<Trait<'t>+'static> {
+        let tup: Box<(int, int)> = box() (4,5);
+        tup as Box<Trait>
+    }
 }
 
 enum List<'l> {
index 152fb5dc961072a29f9b51dcfe680794fe1d5da6..920cd9e03ab6b4ee97fd876a94e5c60bbfa44d92 100644 (file)
@@ -13,6 +13,6 @@
 // pretty-expanded FIXME #23616
 
 pub fn main() {
-    let foo = 1;
+    let foo: int = 1;
     assert_eq!(&foo as *const int, &foo as *const int);
 }
index a6c6db1a1273e4aa4222b8fae06625d8c7dad909..5c0d0fe9a63d8ed74b4ff05042e1562a6debf52c 100644 (file)
@@ -19,7 +19,7 @@
 pub fn main() {
     let (tx, rx) = channel::<uint>();
 
-    let x: Box<_> = box 1;
+    let x: Box<int> = box 1;
     let x_in_parent = &(*x) as *const int as uint;
 
     let _t = Thread::spawn(move || {
index f4c0992ae1a5645fdc71b1997f939546005e3e2c..53e78db68b19d485d7a4b81abc9fd4cfb0cd6c08 100644 (file)
 // pretty-expanded FIXME #23616
 
 struct TestStruct {
-    x: *const int
+    x: *const isize
 }
 
 unsafe impl Sync for TestStruct {}
 
-static CONSTEXPR: TestStruct = TestStruct{x: &413 as *const _};
+static CONSTEXPR: TestStruct = TestStruct{ x: &413 };
 
 
 pub fn main() {
     let x: Vec<_> = (0..5).collect();
-    let expected: &[uint] = &[0,1,2,3,4];
+    let expected: &[usize] = &[0,1,2,3,4];
     assert_eq!(x, expected);
 
     let x = (0..5).collect::<Vec<_>>();
@@ -33,8 +33,8 @@ pub fn main() {
     let y: _ = "hello";
     assert_eq!(y.len(), 5);
 
-    let ptr = &5;
+    let ptr: &usize = &5;
     let ptr2 = ptr as *const _;
 
-    assert_eq!(ptr as *const uint as uint, ptr2 as uint);
+    assert_eq!(ptr as *const usize as usize, ptr2 as usize);
 }
index 4cb7e40a4fbd14ad443ddcd51d29f363cfe3c010..ba12599747068ac7666d0655578f3181456dcc4d 100644 (file)
@@ -16,6 +16,6 @@ fn main() {
     // The subslice used to go out of bounds for zero-sized array items, check that this doesn't
     // happen anymore
     match x {
-        [_, y..] => assert_eq!(&x[1] as *const _, &y[0] as *const _)
+        [_, y..] => assert_eq!(&x[1] as *const (), &y[0] as *const ())
     }
 }