rollup merge of #23630: nrc/coerce-tidy
See notes on the first commit Closes #18601 r? @nikomatsakis cc @eddyb
This commit is contained in:
commit
a1d2e62c1f
@ -429,7 +429,8 @@ impl<T> TypedArenaChunk<T> {
|
||||
// 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;
|
||||
|
@ -24,6 +24,8 @@
|
||||
html_playground_url = "http://play.rust-lang.org/")]
|
||||
#![doc(test(no_crate_inject))]
|
||||
|
||||
#![allow(trivial_casts)]
|
||||
#![allow(trivial_numeric_casts)]
|
||||
#![feature(alloc)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(box_patterns)]
|
||||
|
@ -1199,8 +1199,8 @@ impl<T: PartialEq> Vec<T> {
|
||||
|
||||
// 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);
|
||||
|
@ -713,7 +713,11 @@ impl<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_casts)]
|
||||
&self.value as *const T as *mut T
|
||||
}
|
||||
|
||||
/// Unwraps the value
|
||||
///
|
||||
|
@ -833,6 +833,8 @@ impl<T> Pointer for *const T {
|
||||
#[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_casts)]
|
||||
Pointer::fmt(&(*self as *const T), f)
|
||||
}
|
||||
}
|
||||
@ -840,6 +842,8 @@ impl<T> Pointer for *mut T {
|
||||
#[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_casts)]
|
||||
Pointer::fmt(&(*self as *const T), f)
|
||||
}
|
||||
}
|
||||
@ -847,6 +851,8 @@ impl<'a, T> Pointer for &'a T {
|
||||
#[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_casts)]
|
||||
Pointer::fmt(&(&**self as *const T), f)
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
// FIXME: #6220 Implement floating point formatting
|
||||
|
||||
#![allow(unsigned_negation)]
|
||||
#![allow(trivial_numeric_casts)]
|
||||
|
||||
use fmt;
|
||||
use iter::IteratorExt;
|
||||
|
@ -182,6 +182,8 @@ mod impls {
|
||||
}
|
||||
|
||||
fn hash_slice<H: Hasher>(data: &[$ty], state: &mut H) {
|
||||
// FIXME(#23542) Replace with type ascription.
|
||||
#![allow(trivial_casts)]
|
||||
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) })
|
||||
|
@ -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_casts)]
|
||||
ptr::read(src as *const T as *const U)
|
||||
}
|
||||
|
||||
|
@ -12,5 +12,6 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
#![doc(primitive = "i16")]
|
||||
#![allow(trivial_numeric_casts)]
|
||||
|
||||
int_module! { i16, 16 }
|
||||
|
@ -12,5 +12,6 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
#![doc(primitive = "i32")]
|
||||
#![allow(trivial_numeric_casts)]
|
||||
|
||||
int_module! { i32, 32 }
|
||||
|
@ -12,5 +12,6 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
#![doc(primitive = "i64")]
|
||||
#![allow(trivial_numeric_casts)]
|
||||
|
||||
int_module! { i64, 64 }
|
||||
|
@ -12,5 +12,6 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
#![doc(primitive = "i8")]
|
||||
#![allow(trivial_numeric_casts)]
|
||||
|
||||
int_module! { i8, 8 }
|
||||
|
@ -9,6 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
#![doc(hidden)]
|
||||
#![allow(trivial_numeric_casts)]
|
||||
|
||||
macro_rules! int_module { ($T:ty, $bits:expr) => (
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
#![doc(primitive = "isize")]
|
||||
#![allow(trivial_numeric_casts)]
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
int_module! { isize, 32 }
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
#![allow(missing_docs)]
|
||||
#![allow(trivial_numeric_casts)]
|
||||
|
||||
use self::wrapping::{OverflowingOps, WrappingOps};
|
||||
|
||||
|
@ -12,5 +12,6 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
#![doc(primitive = "u16")]
|
||||
#![allow(trivial_numeric_casts)]
|
||||
|
||||
uint_module! { u16, i16, 16 }
|
||||
|
@ -12,5 +12,6 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
#![doc(primitive = "u32")]
|
||||
#![allow(trivial_numeric_casts)]
|
||||
|
||||
uint_module! { u32, i32, 32 }
|
||||
|
@ -12,5 +12,6 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
#![doc(primitive = "u64")]
|
||||
#![allow(trivial_numeric_casts)]
|
||||
|
||||
uint_module! { u64, i64, 64 }
|
||||
|
@ -12,5 +12,6 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
#![doc(primitive = "u8")]
|
||||
#![allow(trivial_numeric_casts)]
|
||||
|
||||
uint_module! { u8, i8, 8 }
|
||||
|
@ -9,6 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
#![doc(hidden)]
|
||||
#![allow(trivial_numeric_casts)]
|
||||
|
||||
macro_rules! uint_module { ($T:ty, $T_SIGNED:ty, $bits:expr) => (
|
||||
|
||||
|
@ -16,5 +16,6 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
#![doc(primitive = "usize")]
|
||||
#![allow(trivial_numeric_casts)]
|
||||
|
||||
uint_module! { usize, isize, ::isize::BITS }
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
//! Generating numbers between two others.
|
||||
|
||||
#![allow(trivial_numeric_casts)]
|
||||
|
||||
// this is surprisingly complicated to be both generic & correct
|
||||
|
||||
use core::prelude::{PartialOrd};
|
||||
|
@ -447,6 +447,7 @@ impl Rng for Isaac64Rng {
|
||||
|
||||
#[inline]
|
||||
fn next_u64(&mut self) -> u64 {
|
||||
#![allow(trivial_numeric_casts)]
|
||||
if self.cnt == 0 {
|
||||
// make some more numbers
|
||||
self.isaac64();
|
||||
|
@ -353,7 +353,7 @@ pub mod reader {
|
||||
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 @@ pub mod reader {
|
||||
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 {
|
||||
|
@ -47,6 +47,9 @@
|
||||
#![feature(into_cow)]
|
||||
#![cfg_attr(test, feature(test))]
|
||||
|
||||
#![allow(trivial_casts)]
|
||||
#![allow(trivial_numeric_casts)]
|
||||
|
||||
extern crate arena;
|
||||
extern crate flate;
|
||||
extern crate fmt_macros;
|
||||
|
@ -100,6 +100,17 @@ declare_lint! {
|
||||
"detects transmutes of fat pointers"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub TRIVIAL_CASTS,
|
||||
Warn,
|
||||
"detects trivial casts which could be removed"
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
pub TRIVIAL_NUMERIC_CASTS,
|
||||
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 @@ impl LintPass for HardwiredLints {
|
||||
STABLE_FEATURES,
|
||||
UNKNOWN_CRATE_TYPES,
|
||||
VARIANT_SIZE_DIFFERENCES,
|
||||
FAT_PTR_TRANSMUTES
|
||||
FAT_PTR_TRANSMUTES,
|
||||
TRIVIAL_CASTS,
|
||||
TRIVIAL_NUMERIC_CASTS
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2738,7 +2738,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);
|
||||
|
||||
@ -4823,32 +4823,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(..) |
|
||||
@ -4864,7 +4838,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
|
||||
}
|
||||
|
||||
|
@ -84,30 +84,6 @@ impl LintPass for WhileTrue {
|
||||
}
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
UNUSED_TYPECASTS,
|
||||
Allow,
|
||||
"detects unnecessary type casts that can be removed"
|
||||
}
|
||||
|
||||
#[derive(Copy)]
|
||||
pub struct UnusedCasts;
|
||||
|
||||
impl LintPass for UnusedCasts {
|
||||
fn get_lints(&self) -> LintArray {
|
||||
lint_array!(UNUSED_TYPECASTS)
|
||||
}
|
||||
|
||||
fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
|
||||
if let ast::ExprCast(ref expr, ref ty) = e.node {
|
||||
let t_t = ty::expr_ty(cx.tcx, e);
|
||||
if ty::expr_ty(cx.tcx, &**expr) == t_t {
|
||||
cx.span_lint(UNUSED_TYPECASTS, ty.span, "unnecessary type cast");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
UNSIGNED_NEGATION,
|
||||
Warn,
|
||||
@ -1804,6 +1780,9 @@ impl LintPass for UnconditionalRecursion {
|
||||
|
||||
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_casts)]
|
||||
|
||||
type F = for<'tcx> fn(&ty::ctxt<'tcx>,
|
||||
ast::NodeId, ast::NodeId, ast::Ident, ast::NodeId) -> bool;
|
||||
|
||||
|
@ -56,7 +56,7 @@ pub use rustc::session as session;
|
||||
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 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
||||
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());
|
||||
)*}
|
||||
)
|
||||
}
|
||||
@ -89,7 +89,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
||||
add_builtin!(sess,
|
||||
HardwiredLints,
|
||||
WhileTrue,
|
||||
UnusedCasts,
|
||||
ImproperCTypes,
|
||||
BoxPointers,
|
||||
UnusedAttributes,
|
||||
@ -129,7 +128,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
||||
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");
|
||||
|
@ -14,6 +14,8 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(trivial_casts)]
|
||||
#![allow(trivial_numeric_casts)]
|
||||
|
||||
#![crate_name = "rustc_llvm"]
|
||||
#![unstable(feature = "rustc_private")]
|
||||
|
@ -43,6 +43,9 @@
|
||||
#![feature(convert)]
|
||||
#![feature(path_relative_from)]
|
||||
|
||||
#![allow(trivial_casts)]
|
||||
#![allow(trivial_numeric_casts)]
|
||||
|
||||
extern crate arena;
|
||||
extern crate flate;
|
||||
extern crate getopts;
|
||||
|
@ -471,15 +471,6 @@ impl<'tcx> Datum<'tcx, Expr> {
|
||||
})
|
||||
}
|
||||
|
||||
/// 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,
|
||||
|
@ -1227,22 +1227,9 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
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);
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ use trans::common::*;
|
||||
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;
|
||||
@ -863,44 +863,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> {
|
||||
|
@ -258,70 +258,64 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
|
||||
match (&a.sty, &b.sty) {
|
||||
(&ty::ty_rptr(_, ty::mt{ty: t_a, mutbl: mutbl_a}), &ty::ty_rptr(_, mt_b)) => {
|
||||
self.unpack_actual_value(t_a, |a| {
|
||||
match self.unsize_ty(t_a, a, mt_b.ty) {
|
||||
Some((ty, kind)) => {
|
||||
if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) {
|
||||
return Err(ty::terr_mutability);
|
||||
}
|
||||
|
||||
let coercion = Coercion(self.trace.clone());
|
||||
let r_borrow = self.fcx.infcx().next_region_var(coercion);
|
||||
let ty = ty::mk_rptr(self.tcx(),
|
||||
self.tcx().mk_region(r_borrow),
|
||||
ty::mt{ty: ty, mutbl: mt_b.mutbl});
|
||||
try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
|
||||
debug!("Success, coerced with AutoDerefRef(1, \
|
||||
AutoPtr(AutoUnsize({:?})))", kind);
|
||||
Ok(Some(AdjustDerefRef(AutoDerefRef {
|
||||
autoderefs: 1,
|
||||
autoref: Some(ty::AutoPtr(r_borrow, mt_b.mutbl,
|
||||
Some(box AutoUnsize(kind))))
|
||||
})))
|
||||
match self.unsize_ty(t_a, mt_b.ty) {
|
||||
Some((ty, kind)) => {
|
||||
if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) {
|
||||
return Err(ty::terr_mutability);
|
||||
}
|
||||
_ => Err(ty::terr_mismatch)
|
||||
|
||||
let coercion = Coercion(self.trace.clone());
|
||||
let r_borrow = self.fcx.infcx().next_region_var(coercion);
|
||||
let ty = ty::mk_rptr(self.tcx(),
|
||||
self.tcx().mk_region(r_borrow),
|
||||
ty::mt{ty: ty, mutbl: mt_b.mutbl});
|
||||
try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
|
||||
debug!("Success, coerced with AutoDerefRef(1, \
|
||||
AutoPtr(AutoUnsize({:?})))", kind);
|
||||
Ok(Some(AdjustDerefRef(AutoDerefRef {
|
||||
autoderefs: 1,
|
||||
autoref: Some(ty::AutoPtr(r_borrow, mt_b.mutbl,
|
||||
Some(box AutoUnsize(kind))))
|
||||
})))
|
||||
}
|
||||
})
|
||||
_ => Err(ty::terr_mismatch)
|
||||
}
|
||||
}
|
||||
(&ty::ty_rptr(_, ty::mt{ty: t_a, mutbl: mutbl_a}), &ty::ty_ptr(mt_b)) => {
|
||||
self.unpack_actual_value(t_a, |a| {
|
||||
match self.unsize_ty(t_a, a, mt_b.ty) {
|
||||
Some((ty, kind)) => {
|
||||
if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) {
|
||||
return Err(ty::terr_mutability);
|
||||
}
|
||||
|
||||
let ty = ty::mk_ptr(self.tcx(),
|
||||
ty::mt{ty: ty, mutbl: mt_b.mutbl});
|
||||
try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
|
||||
debug!("Success, coerced with AutoDerefRef(1, \
|
||||
AutoPtr(AutoUnsize({:?})))", kind);
|
||||
Ok(Some(AdjustDerefRef(AutoDerefRef {
|
||||
autoderefs: 1,
|
||||
autoref: Some(ty::AutoUnsafe(mt_b.mutbl,
|
||||
Some(box AutoUnsize(kind))))
|
||||
})))
|
||||
match self.unsize_ty(t_a, mt_b.ty) {
|
||||
Some((ty, kind)) => {
|
||||
if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) {
|
||||
return Err(ty::terr_mutability);
|
||||
}
|
||||
_ => Err(ty::terr_mismatch)
|
||||
|
||||
let ty = ty::mk_ptr(self.tcx(),
|
||||
ty::mt{ty: ty, mutbl: mt_b.mutbl});
|
||||
try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
|
||||
debug!("Success, coerced with AutoDerefRef(1, \
|
||||
AutoPtr(AutoUnsize({:?})))", kind);
|
||||
Ok(Some(AdjustDerefRef(AutoDerefRef {
|
||||
autoderefs: 1,
|
||||
autoref: Some(ty::AutoUnsafe(mt_b.mutbl,
|
||||
Some(box AutoUnsize(kind))))
|
||||
})))
|
||||
}
|
||||
})
|
||||
_ => Err(ty::terr_mismatch)
|
||||
}
|
||||
}
|
||||
(&ty::ty_uniq(t_a), &ty::ty_uniq(t_b)) => {
|
||||
self.unpack_actual_value(t_a, |a| {
|
||||
match self.unsize_ty(t_a, a, t_b) {
|
||||
Some((ty, kind)) => {
|
||||
let ty = ty::mk_uniq(self.tcx(), ty);
|
||||
try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
|
||||
debug!("Success, coerced with AutoDerefRef(1, \
|
||||
AutoUnsizeUniq({:?}))", kind);
|
||||
Ok(Some(AdjustDerefRef(AutoDerefRef {
|
||||
autoderefs: 1,
|
||||
autoref: Some(ty::AutoUnsizeUniq(kind))
|
||||
})))
|
||||
}
|
||||
_ => Err(ty::terr_mismatch)
|
||||
match self.unsize_ty(t_a, t_b) {
|
||||
Some((ty, kind)) => {
|
||||
let ty = ty::mk_uniq(self.tcx(), ty);
|
||||
try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
|
||||
debug!("Success, coerced with AutoDerefRef(1, \
|
||||
AutoUnsizeUniq({:?}))", kind);
|
||||
Ok(Some(AdjustDerefRef(AutoDerefRef {
|
||||
autoderefs: 1,
|
||||
autoref: Some(ty::AutoUnsizeUniq(kind))
|
||||
})))
|
||||
}
|
||||
})
|
||||
_ => Err(ty::terr_mismatch)
|
||||
}
|
||||
}
|
||||
_ => Err(ty::terr_mismatch)
|
||||
}
|
||||
@ -332,113 +326,112 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
// E.g., `[T, ..n]` -> `([T], UnsizeLength(n))`
|
||||
fn unsize_ty(&self,
|
||||
ty_a: Ty<'tcx>,
|
||||
a: Ty<'tcx>,
|
||||
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|
|
||||
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);
|
||||
Some((ty, ty::UnsizeLength(len)))
|
||||
}
|
||||
(&ty::ty_trait(ref data_a), &ty::ty_trait(ref data_b)) => {
|
||||
// Upcasts permit two things:
|
||||
//
|
||||
// 1. Dropping builtin bounds, e.g. `Foo+Send` to `Foo`
|
||||
// 2. Tightening the region bound, e.g. `Foo+'a` to `Foo+'b` if `'a : 'b`
|
||||
//
|
||||
// Note that neither of these changes requires any
|
||||
// change at runtime. Eventually this will be
|
||||
// generalized.
|
||||
//
|
||||
// We always upcast when we can because of reason
|
||||
// #2 (region bounds).
|
||||
if data_a.bounds.builtin_bounds.is_superset(&data_b.bounds.builtin_bounds) {
|
||||
// construct a type `a1` which is a version of
|
||||
// `a` using the upcast bounds from `b`
|
||||
let bounds_a1 = ty::ExistentialBounds {
|
||||
// From type b
|
||||
region_bound: data_b.bounds.region_bound,
|
||||
builtin_bounds: data_b.bounds.builtin_bounds,
|
||||
|
||||
// From type a
|
||||
projection_bounds: data_a.bounds.projection_bounds.clone(),
|
||||
};
|
||||
let ty_a1 = ty::mk_trait(tcx, data_a.principal.clone(), bounds_a1);
|
||||
|
||||
// relate `a1` to `b`
|
||||
let result = self.fcx.infcx().try(|_| {
|
||||
// it's ok to upcast from Foo+'a to Foo+'b so long as 'a : 'b
|
||||
try!(self.outlives(data_a.bounds.region_bound,
|
||||
data_b.bounds.region_bound));
|
||||
self.subtype(ty_a1, ty_b)
|
||||
});
|
||||
|
||||
// if that was successful, we have a coercion
|
||||
match result {
|
||||
Ok(_) => Some((ty_b, ty::UnsizeUpcast(ty_b))),
|
||||
Err(_) => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
self.unpack_actual_value(ty_a, |a| {
|
||||
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);
|
||||
Some((ty, ty::UnsizeLength(len)))
|
||||
}
|
||||
}
|
||||
(_, &ty::ty_trait(ref data)) => {
|
||||
Some((ty_b, ty::UnsizeVtable(ty::TyTrait { principal: data.principal.clone(),
|
||||
bounds: data.bounds.clone() },
|
||||
ty_a)))
|
||||
}
|
||||
(&ty::ty_struct(did_a, substs_a), &ty::ty_struct(did_b, substs_b))
|
||||
if did_a == did_b => {
|
||||
debug!("unsizing a struct");
|
||||
// Try unsizing each type param in turn to see if we end up with ty_b.
|
||||
let ty_substs_a = substs_a.types.get_slice(subst::TypeSpace);
|
||||
let ty_substs_b = substs_b.types.get_slice(subst::TypeSpace);
|
||||
assert!(ty_substs_a.len() == ty_substs_b.len());
|
||||
(&ty::ty_trait(ref data_a), &ty::ty_trait(ref data_b)) => {
|
||||
// Upcasts permit two things:
|
||||
//
|
||||
// 1. Dropping builtin bounds, e.g. `Foo+Send` to `Foo`
|
||||
// 2. Tightening the region bound, e.g. `Foo+'a` to `Foo+'b` if `'a : 'b`
|
||||
//
|
||||
// Note that neither of these changes requires any
|
||||
// change at runtime. Eventually this will be
|
||||
// generalized.
|
||||
//
|
||||
// We always upcast when we can because of reason
|
||||
// #2 (region bounds).
|
||||
if data_a.bounds.builtin_bounds.is_superset(&data_b.bounds.builtin_bounds) {
|
||||
// construct a type `a1` which is a version of
|
||||
// `a` using the upcast bounds from `b`
|
||||
let bounds_a1 = ty::ExistentialBounds {
|
||||
// From type b
|
||||
region_bound: data_b.bounds.region_bound,
|
||||
builtin_bounds: data_b.bounds.builtin_bounds,
|
||||
|
||||
let mut result = None;
|
||||
let tps = ty_substs_a.iter().zip(ty_substs_b.iter()).enumerate();
|
||||
for (i, (tp_a, tp_b)) in tps {
|
||||
if self.fcx.infcx().try(|_| self.subtype(*tp_a, *tp_b)).is_ok() {
|
||||
continue;
|
||||
// From type a
|
||||
projection_bounds: data_a.bounds.projection_bounds.clone(),
|
||||
};
|
||||
let ty_a1 = ty::mk_trait(tcx, data_a.principal.clone(), bounds_a1);
|
||||
|
||||
// relate `a1` to `b`
|
||||
let result = self.fcx.infcx().try(|_| {
|
||||
// it's ok to upcast from Foo+'a to Foo+'b so long as 'a : 'b
|
||||
try!(self.outlives(data_a.bounds.region_bound,
|
||||
data_b.bounds.region_bound));
|
||||
self.subtype(ty_a1, ty_b)
|
||||
});
|
||||
|
||||
// if that was successful, we have a coercion
|
||||
match result {
|
||||
Ok(_) => Some((ty_b, ty::UnsizeUpcast(ty_b))),
|
||||
Err(_) => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
match
|
||||
self.unpack_actual_value(
|
||||
*tp_a,
|
||||
|tp| self.unsize_ty(*tp_a, tp, *tp_b))
|
||||
{
|
||||
Some((new_tp, k)) => {
|
||||
// Check that the whole types match.
|
||||
let mut new_substs = substs_a.clone();
|
||||
new_substs.types.get_mut_slice(subst::TypeSpace)[i] = new_tp;
|
||||
let ty = ty::mk_struct(tcx, did_a, tcx.mk_substs(new_substs));
|
||||
if self.fcx.infcx().try(|_| self.subtype(ty, ty_b)).is_err() {
|
||||
debug!("Unsized type parameter '{}', but still \
|
||||
could not match types {} and {}",
|
||||
ppaux::ty_to_string(tcx, *tp_a),
|
||||
ppaux::ty_to_string(tcx, ty),
|
||||
ppaux::ty_to_string(tcx, ty_b));
|
||||
// We can only unsize a single type parameter, so
|
||||
// if we unsize one and it doesn't give us the
|
||||
// type we want, then we won't succeed later.
|
||||
}
|
||||
(_, &ty::ty_trait(ref data)) => {
|
||||
Some((ty_b, ty::UnsizeVtable(ty::TyTrait {
|
||||
principal: data.principal.clone(),
|
||||
bounds: data.bounds.clone()
|
||||
},
|
||||
ty_a)))
|
||||
}
|
||||
(&ty::ty_struct(did_a, substs_a), &ty::ty_struct(did_b, substs_b))
|
||||
if did_a == did_b => {
|
||||
debug!("unsizing a struct");
|
||||
// Try unsizing each type param in turn to see if we end up with ty_b.
|
||||
let ty_substs_a = substs_a.types.get_slice(subst::TypeSpace);
|
||||
let ty_substs_b = substs_b.types.get_slice(subst::TypeSpace);
|
||||
assert!(ty_substs_a.len() == ty_substs_b.len());
|
||||
|
||||
let mut result = None;
|
||||
let tps = ty_substs_a.iter().zip(ty_substs_b.iter()).enumerate();
|
||||
for (i, (tp_a, tp_b)) in tps {
|
||||
if self.fcx.infcx().try(|_| self.subtype(*tp_a, *tp_b)).is_ok() {
|
||||
continue;
|
||||
}
|
||||
match self.unsize_ty(*tp_a, *tp_b) {
|
||||
Some((new_tp, k)) => {
|
||||
// Check that the whole types match.
|
||||
let mut new_substs = substs_a.clone();
|
||||
new_substs.types.get_mut_slice(subst::TypeSpace)[i] = new_tp;
|
||||
let ty = ty::mk_struct(tcx, did_a, tcx.mk_substs(new_substs));
|
||||
if self.fcx.infcx().try(|_| self.subtype(ty, ty_b)).is_err() {
|
||||
debug!("Unsized type parameter '{}', but still \
|
||||
could not match types {} and {}",
|
||||
ppaux::ty_to_string(tcx, *tp_a),
|
||||
ppaux::ty_to_string(tcx, ty),
|
||||
ppaux::ty_to_string(tcx, ty_b));
|
||||
// We can only unsize a single type parameter, so
|
||||
// if we unsize one and it doesn't give us the
|
||||
// type we want, then we won't succeed later.
|
||||
break;
|
||||
}
|
||||
|
||||
result = Some((ty, ty::UnsizeStruct(box k, i)));
|
||||
break;
|
||||
}
|
||||
|
||||
result = Some((ty, ty::UnsizeStruct(box k, i)));
|
||||
break;
|
||||
None => {}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
result
|
||||
}
|
||||
result
|
||||
_ => None
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn coerce_from_fn_pointer(&self,
|
||||
|
@ -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),
|
||||
|
@ -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 @@ impl<'a, 'tcx> Inherited<'a, '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 check_cast_inner<'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_CASTS,
|
||||
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_CASTS,
|
||||
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 check_cast_inner<'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 check_cast_inner<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
/* 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 check_cast_inner<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
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 @@ impl<'a, 'tcx> FnCtxt<'a, '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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
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_expr_with_unifier<'a, 'tcx, F>(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 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
|
||||
ty: attr::IntType,
|
||||
disr: ty::Disr) -> bool {
|
||||
fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
|
||||
#![allow(trivial_numeric_casts)]
|
||||
|
||||
match ty {
|
||||
ast::TyU8 => disr as u8 as Disr == disr,
|
||||
ast::TyU16 => disr as u16 as Disr == disr,
|
||||
@ -4588,6 +4611,7 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
|
||||
id: ast::NodeId,
|
||||
hint: attr::ReprAttr)
|
||||
-> Vec<Rc<ty::VariantInfo<'tcx>>> {
|
||||
#![allow(trivial_numeric_casts)]
|
||||
use std::num::Int;
|
||||
|
||||
let rty = ty::node_id_to_type(ccx.tcx, id);
|
||||
|
@ -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;
|
||||
@ -19,83 +18,6 @@ use syntax::codemap::Span;
|
||||
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
|
||||
|
@ -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(),
|
||||
|
@ -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_casts)]
|
||||
Json::I64(*self as i64)
|
||||
}
|
||||
})+
|
||||
)
|
||||
}
|
||||
@ -2439,7 +2442,10 @@ to_json_impl_i64! { int, i8, i16, i32, 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_casts)]
|
||||
Json::U64(*self as u64)
|
||||
}
|
||||
})+
|
||||
)
|
||||
}
|
||||
|
@ -135,6 +135,8 @@
|
||||
#![feature(no_std)]
|
||||
#![no_std]
|
||||
|
||||
#![allow(trivial_casts)]
|
||||
#![allow(trivial_numeric_casts)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
#[cfg(test)] extern crate test;
|
||||
|
@ -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);
|
||||
|
@ -68,7 +68,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
|
||||
|
@ -109,7 +109,7 @@ impl Iterator for Env {
|
||||
if *self.cur == 0 { return None }
|
||||
let p = &*self.cur;
|
||||
let mut len = 0;
|
||||
while *(p as *const _).offset(len) != 0 {
|
||||
while *(p as *const u16).offset(len) != 0 {
|
||||
len += 1;
|
||||
}
|
||||
let p = p as *const u16;
|
||||
|
@ -176,6 +176,7 @@ macro_rules! __thread_local_inner {
|
||||
}
|
||||
};
|
||||
|
||||
#[allow(trivial_casts)]
|
||||
#[cfg(any(not(any(target_os = "macos", target_os = "linux")), target_arch = "aarch64"))]
|
||||
const _INIT: ::std::thread::__local::__impl::KeyInner<$t> = {
|
||||
::std::thread::__local::__impl::KeyInner {
|
||||
|
@ -284,7 +284,7 @@ pub const COMMAND_LINE_EXPN: ExpnId = ExpnId(-2);
|
||||
|
||||
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 @@ impl Encodable for FileMap {
|
||||
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 @@ impl CodeMap {
|
||||
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}
|
||||
|
@ -264,7 +264,7 @@ macro_rules! make_MacEager {
|
||||
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 @@ impl DummyResult {
|
||||
/// 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.
|
||||
|
@ -262,6 +262,7 @@ pub mod rt {
|
||||
(unsigned, $t:ty, $tag:expr) => (
|
||||
impl ToSource for $t {
|
||||
fn to_source(&self) -> String {
|
||||
#![allow(trivial_numeric_casts)]
|
||||
let lit = ast::LitInt(*self as u64, ast::UnsignedIntLit($tag));
|
||||
pprust::lit_to_string(&dummy_spanned(lit))
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -758,7 +758,7 @@ impl<'a> StringReader<'a> {
|
||||
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 @@ impl<'a> StringReader<'a> {
|
||||
self.fatal_span_char(self.last_pos, self.pos,
|
||||
"illegal character in unicode escape", c);
|
||||
}
|
||||
}) as u32;
|
||||
});
|
||||
self.bump();
|
||||
count += 1;
|
||||
}
|
||||
|
@ -865,7 +865,7 @@ impl<'a> Parser<'a> {
|
||||
} 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 {
|
||||
|
@ -2831,7 +2831,7 @@ impl<'a> State<'a> {
|
||||
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))
|
||||
|
@ -103,7 +103,7 @@ impl Write for WriterWrapper {
|
||||
/// 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(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ impl<T: Write+Send+'static> TerminfoTerminal<T> {
|
||||
out: out,
|
||||
ti: msys_terminfo(),
|
||||
num_colors: 8,
|
||||
} as Box<Terminal<T>+Send>)
|
||||
})
|
||||
},
|
||||
_ => {
|
||||
debug!("error finding terminfo entry: {:?}", err);
|
||||
@ -213,7 +213,7 @@ impl<T: Write+Send+'static> TerminfoTerminal<T> {
|
||||
|
||||
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 {
|
||||
|
@ -186,7 +186,7 @@ pub fn parse(file: &mut Read, longnames: bool)
|
||||
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;
|
||||
|
@ -126,7 +126,7 @@ impl<T: Write+Send+'static> WinConsole<T> {
|
||||
}
|
||||
Some(box WinConsole { buf: out,
|
||||
def_foreground: fg, def_background: bg,
|
||||
foreground: fg, background: bg } as Box<Terminal<T>+Send>)
|
||||
foreground: fg, background: bg })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1021,7 +1021,7 @@ impl MetricMap {
|
||||
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(", ")
|
||||
}
|
||||
|
@ -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 }
|
||||
}
|
||||
|
@ -21,6 +21,6 @@ mod inner {
|
||||
}
|
||||
|
||||
pub fn foo() {
|
||||
let a = &1 as &inner::Trait;
|
||||
let a = &1i as &inner::Trait;
|
||||
a.f();
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -19,8 +19,7 @@ mod Y {
|
||||
}
|
||||
|
||||
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() {}
|
||||
|
@ -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`
|
||||
}
|
@ -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) {
|
||||
|
@ -86,6 +86,6 @@ mod inner {
|
||||
}
|
||||
|
||||
pub fn foo() {
|
||||
let a = &1 as &inner::Trait;
|
||||
let a: &inner::Trait = &1_isize;
|
||||
a.f();
|
||||
}
|
||||
|
@ -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
|
||||
}
|
@ -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_casts)]
|
||||
|
||||
fn f1(x: isize) {
|
||||
//~^ ERROR unused variable: `x`
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(trivial_casts)]
|
||||
|
||||
trait Bar {
|
||||
fn bar(self);
|
||||
|
@ -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() {}
|
||||
|
@ -19,6 +19,7 @@ trait SomeTrait { fn get(&self) -> isize; }
|
||||
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() { }
|
||||
|
94
src/test/compile-fail/trivial_casts.rs
Normal file
94
src/test/compile-fail/trivial_casts.rs
Normal file
@ -0,0 +1,94 @@
|
||||
// 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.
|
||||
|
||||
// Test the trivial_casts and trivial_numeric_casts lints. For each error we also
|
||||
// check that the cast can be done using just coercion.
|
||||
|
||||
#![deny(trivial_casts, trivial_numeric_casts)]
|
||||
|
||||
trait Foo {
|
||||
fn foo(&self) {}
|
||||
}
|
||||
|
||||
pub struct Bar;
|
||||
|
||||
impl Foo for Bar {}
|
||||
|
||||
pub fn main() {
|
||||
// Numeric
|
||||
let _ = 42_i32 as i32; //~ ERROR trivial numeric cast: `i32` as `i32`
|
||||
let _: i32 = 42_i32;
|
||||
|
||||
let _ = 42_u8 as u8; //~ ERROR trivial numeric cast: `u8` as `u8`
|
||||
let _: u8 = 42_u8;
|
||||
|
||||
// & to * pointers
|
||||
let x: &u32 = &42;
|
||||
let _ = x as *const u32; //~ERROR trivial cast: `&u32` as `*const u32`
|
||||
let _: *const u32 = x;
|
||||
|
||||
let x: &mut u32 = &mut 42;
|
||||
let _ = x as *mut u32; //~ERROR trivial cast: `&mut u32` as `*mut u32`
|
||||
let _: *mut u32 = x;
|
||||
|
||||
// unsize array
|
||||
let x: &[u32; 3] = &[42, 43, 44];
|
||||
let _ = x as &[u32]; //~ERROR trivial cast: `&[u32; 3]` as `&[u32]`
|
||||
let _ = x as *const [u32]; //~ERROR trivial cast: `&[u32; 3]` as `*const [u32]`
|
||||
let _: &[u32] = x;
|
||||
let _: *const [u32] = x;
|
||||
|
||||
let x: &mut [u32; 3] = &mut [42, 43, 44];
|
||||
let _ = x as &mut [u32]; //~ERROR trivial cast: `&mut [u32; 3]` as `&mut [u32]`
|
||||
let _ = x as *mut [u32]; //~ERROR trivial cast: `&mut [u32; 3]` as `*mut [u32]`
|
||||
let _: &mut [u32] = x;
|
||||
let _: *mut [u32] = x;
|
||||
|
||||
let x: Box<[u32; 3]> = Box::new([42, 43, 44]);
|
||||
let _ = x as Box<[u32]>; //~ERROR trivial cast: `Box<[u32; 3]>` as `Box<[u32]>`
|
||||
let x: Box<[u32; 3]> = Box::new([42, 43, 44]);
|
||||
let _: Box<[u32]> = x;
|
||||
|
||||
// unsize trait
|
||||
let x: &Bar = &Bar;
|
||||
let _ = x as &Foo; //~ERROR trivial cast: `&Bar` as `&Foo`
|
||||
let _ = x as *const Foo; //~ERROR trivial cast: `&Bar` as `*const Foo`
|
||||
let _: &Foo = x;
|
||||
let _: *const Foo = x;
|
||||
|
||||
let x: &mut Bar = &mut Bar;
|
||||
let _ = x as &mut Foo; //~ERROR trivial cast: `&mut Bar` as `&mut Foo`
|
||||
let _ = x as *mut Foo; //~ERROR trivial cast: `&mut Bar` as `*mut Foo`
|
||||
let _: &mut Foo = x;
|
||||
let _: *mut Foo = x;
|
||||
|
||||
let x: Box<Bar> = Box::new(Bar);
|
||||
let _ = x as Box<Foo>; //~ERROR trivial cast: `Box<Bar>` as `Box<Foo>`
|
||||
let x: Box<Bar> = Box::new(Bar);
|
||||
let _: Box<Foo> = x;
|
||||
|
||||
// functions
|
||||
fn baz(_x: i32) {}
|
||||
let _ = &baz as &Fn(i32); //~ERROR trivial cast: `&fn(i32) {main::baz}` as `&core::ops::Fn(i32)`
|
||||
let _: &Fn(i32) = &baz;
|
||||
let x = |_x: i32| {};
|
||||
let _ = &x as &Fn(i32); //~ERROR trivial cast
|
||||
let _: &Fn(i32) = &x;
|
||||
}
|
||||
|
||||
// subtyping
|
||||
pub fn test_subtyping<'a, 'b: 'a>(a: &'a Bar, b: &'b Bar) {
|
||||
let _ = a as &'a Bar; //~ERROR trivial cast
|
||||
let _: &'a Bar = a;
|
||||
let _ = b as &'a Bar; //~ERROR trivial cast
|
||||
let _: &'a Bar = b;
|
||||
let _ = b as &'b Bar; //~ERROR trivial cast
|
||||
let _: &'b Bar = b;
|
||||
}
|
@ -20,7 +20,7 @@ impl MyAdd for i32 {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = 5;
|
||||
let x: i32 = 5;
|
||||
let y = x as MyAdd<i32>;
|
||||
//~^ ERROR as `MyAdd<i32>`
|
||||
}
|
||||
|
@ -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];
|
||||
|
@ -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>>;
|
||||
|
||||
|
@ -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>;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -22,6 +22,6 @@ impl double for uint {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ impl<'a> Outer<'a> {
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let inner = 5;
|
||||
let inner: int = 5;
|
||||
let outer = Outer::new(&inner as &Inner);
|
||||
outer.inner.print();
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ mod a {
|
||||
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 @@ mod b {
|
||||
}
|
||||
|
||||
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() {}
|
||||
|
@ -33,6 +33,6 @@ impl<T> B for *const [T] {
|
||||
|
||||
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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -83,7 +83,10 @@ impl<'s> Trait<'s> for (int,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> {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ use std::sync::mpsc::channel;
|
||||
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 || {
|
||||
|
71
src/test/run-pass/trivial_casts.rs
Normal file
71
src/test/run-pass/trivial_casts.rs
Normal file
@ -0,0 +1,71 @@
|
||||
// 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.
|
||||
|
||||
// Test that all coercions can actually be done using casts (modulo the lints).
|
||||
|
||||
#![allow(trivial_casts, trivial_numeric_casts)]
|
||||
|
||||
trait Foo {
|
||||
fn foo(&self) {}
|
||||
}
|
||||
|
||||
pub struct Bar;
|
||||
|
||||
impl Foo for Bar {}
|
||||
|
||||
pub fn main() {
|
||||
// Numeric
|
||||
let _ = 42_i32 as i32;
|
||||
let _ = 42_u8 as u8;
|
||||
|
||||
// & to * pointers
|
||||
let x: &u32 = &42;
|
||||
let _ = x as *const u32;
|
||||
|
||||
let x: &mut u32 = &mut 42;
|
||||
let _ = x as *mut u32;
|
||||
|
||||
// unsize array
|
||||
let x: &[u32; 3] = &[42, 43, 44];
|
||||
let _ = x as &[u32];
|
||||
let _ = x as *const [u32];
|
||||
|
||||
let x: &mut [u32; 3] = &mut [42, 43, 44];
|
||||
let _ = x as &mut [u32];
|
||||
let _ = x as *mut [u32];
|
||||
|
||||
let x: Box<[u32; 3]> = Box::new([42, 43, 44]);
|
||||
let _ = x as Box<[u32]>;
|
||||
|
||||
// unsize trait
|
||||
let x: &Bar = &Bar;
|
||||
let _ = x as &Foo;
|
||||
let _ = x as *const Foo;
|
||||
|
||||
let x: &mut Bar = &mut Bar;
|
||||
let _ = x as &mut Foo;
|
||||
let _ = x as *mut Foo;
|
||||
|
||||
let x: Box<Bar> = Box::new(Bar);
|
||||
let _ = x as Box<Foo>;
|
||||
|
||||
// functions
|
||||
fn baz(_x: i32) {}
|
||||
let _ = &baz as &Fn(i32);
|
||||
let x = |_x: i32| {};
|
||||
let _ = &x as &Fn(i32);
|
||||
}
|
||||
|
||||
// subtyping
|
||||
pub fn test_subtyping<'a, 'b: 'a>(a: &'a Bar, b: &'b Bar) {
|
||||
let _ = a as &'a Bar;
|
||||
let _ = b as &'a Bar;
|
||||
let _ = b as &'b Bar;
|
||||
}
|
@ -14,17 +14,17 @@
|
||||
// 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);
|
||||
}
|
||||
|
@ -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 ())
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user