From 32fe2e3ad452128d17ab1ce15f2c77b8cb42a3ea Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Thu, 14 May 2015 15:04:49 +0300 Subject: [PATCH] Address review commets I think I didn't run tests properly - my second call to select_all_obligations_or_error has made 3 tests fail. However, this is just an error message change - integer fallback never worked with casts. --- src/librustc/middle/cast.rs | 20 +++-- src/librustc/middle/check_const.rs | 4 +- src/librustc_trans/trans/consts.rs | 36 ++++---- src/librustc_trans/trans/expr.rs | 10 ++- src/librustc_typeck/check/cast.rs | 88 ++++++++++--------- src/librustc_typeck/check/mod.rs | 30 +++---- .../associated-types-incomplete-object.rs | 8 +- src/test/compile-fail/cast-rfc0401.rs | 4 + .../compile-fail/destructure-trait-ref.rs | 18 ++-- src/test/compile-fail/issue-17458.rs | 2 +- src/test/compile-fail/issue-5153.rs | 2 +- .../compile-fail/kindck-impl-type-params.rs | 1 - .../cast-enum-with-dtor.rs | 0 .../run-pass/cast-rfc0401-vtable-kinds.rs | 3 + 14 files changed, 123 insertions(+), 103 deletions(-) rename src/test/{run-pass => run-pass-valgrind}/cast-enum-with-dtor.rs (100%) diff --git a/src/librustc/middle/cast.rs b/src/librustc/middle/cast.rs index 4b876cfd80f..c534a3ca038 100644 --- a/src/librustc/middle/cast.rs +++ b/src/librustc/middle/cast.rs @@ -15,7 +15,7 @@ use syntax::ast; - +/// Types that are represented as ints. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum IntTy { U(ast::UintTy), @@ -28,10 +28,16 @@ pub enum IntTy { // Valid types for the result of a non-coercion cast #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum CastTy<'tcx> { + /// Various types that are represented as ints and handled mostly + /// in the same way, merged for easier matching. Int(IntTy), + /// Floating-Point types Float, - FPtr, + /// Function Pointers + FnPtr, + /// Raw pointers Ptr(&'tcx ty::mt<'tcx>), + /// References RPtr(&'tcx ty::mt<'tcx>), } @@ -47,13 +53,13 @@ pub enum CastKind { PrimIntCast, U8CharCast, ArrayPtrCast, - FPtrPtrCast, - FPtrAddrCast + FnPtrPtrCast, + FnPtrAddrCast } impl<'tcx> CastTy<'tcx> { - pub fn recognize(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) - -> Option> { + pub fn from_ty(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) + -> Option> { match t.sty { ty::ty_bool => Some(CastTy::Int(IntTy::Bool)), ty::ty_char => Some(CastTy::Int(IntTy::Char)), @@ -64,7 +70,7 @@ pub fn recognize(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) tcx, t) => Some(CastTy::Int(IntTy::CEnum)), ty::ty_ptr(ref mt) => Some(CastTy::Ptr(mt)), ty::ty_rptr(_, ref mt) => Some(CastTy::RPtr(mt)), - ty::ty_bare_fn(..) => Some(CastTy::FPtr), + ty::ty_bare_fn(..) => Some(CastTy::FnPtr), _ => None, } } diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index 6d2465a5cb9..794cc4ff38d 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -443,11 +443,11 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, debug!("Checking const cast(id={})", from.id); match v.tcx.cast_kinds.borrow().get(&from.id) { None => v.tcx.sess.span_bug(e.span, "no kind for cast"), - Some(&CastKind::PtrAddrCast) | Some(&CastKind::FPtrAddrCast) => { + Some(&CastKind::PtrAddrCast) | Some(&CastKind::FnPtrAddrCast) => { v.add_qualif(ConstQualif::NOT_CONST); if v.mode != Mode::Var { span_err!(v.tcx.sess, e.span, E0018, - "can not cast a pointer to an integer in {}s", v.msg()); + "can't cast a pointer to an integer in {}s", v.msg()); } } _ => {} diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 29430ad10e6..828e4bcc65c 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -617,41 +617,41 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } } ast::ExprCast(ref base, _) => { - let t_1 = ety; - let llty = type_of::type_of(cx, t_1); - let (v, t_e) = const_expr(cx, &**base, param_substs); - debug!("trans_const_cast({} as {})", t_e.repr(cx.tcx()), t_1.repr(cx.tcx())); - if expr::cast_is_noop(cx.tcx(), base, t_e, t_1) { + let t_cast = ety; + let llty = type_of::type_of(cx, t_cast); + let (v, t_expr) = const_expr(cx, &**base, param_substs); + debug!("trans_const_cast({} as {})", t_expr.repr(cx.tcx()), t_cast.repr(cx.tcx())); + if expr::cast_is_noop(cx.tcx(), base, t_expr, t_cast) { return v; } - if type_is_fat_ptr(cx.tcx(), t_e) { + if type_is_fat_ptr(cx.tcx(), t_expr) { // Fat pointer casts. - let t_1_inner = ty::deref(t_1, true).expect("cast to non-pointer").ty; - let ptr_ty = type_of::in_memory_type_of(cx, t_1_inner).ptr_to(); + let t_cast_inner = ty::deref(t_cast, true).expect("cast to non-pointer").ty; + let ptr_ty = type_of::in_memory_type_of(cx, t_cast_inner).ptr_to(); let addr = ptrcast(const_get_elt(cx, v, &[abi::FAT_PTR_ADDR as u32]), ptr_ty); - if type_is_fat_ptr(cx.tcx(), t_1) { + if type_is_fat_ptr(cx.tcx(), t_cast) { let info = const_get_elt(cx, v, &[abi::FAT_PTR_EXTRA as u32]); return C_struct(cx, &[addr, info], false) } else { return addr; } } - match (CastTy::recognize(cx.tcx(), t_e).expect("bad input type for cast"), - CastTy::recognize(cx.tcx(), t_1).expect("bad output type for cast")) { + match (CastTy::from_ty(cx.tcx(), t_expr).expect("bad input type for cast"), + CastTy::from_ty(cx.tcx(), t_cast).expect("bad output type for cast")) { (CastTy::Int(IntTy::CEnum), CastTy::Int(_)) => { - let repr = adt::represent_type(cx, t_e); + let repr = adt::represent_type(cx, t_expr); let discr = adt::const_get_discrim(cx, &*repr, v); let iv = C_integral(cx.int_type(), discr, false); let s = adt::is_discr_signed(&*repr) as Bool; llvm::LLVMConstIntCast(iv, llty.to_ref(), s) } (CastTy::Int(_), CastTy::Int(_)) => { - let s = ty::type_is_signed(t_e) as Bool; + let s = ty::type_is_signed(t_expr) as Bool; llvm::LLVMConstIntCast(v, llty.to_ref(), s) } (CastTy::Int(_), CastTy::Float) => { - if ty::type_is_signed(t_e) { + if ty::type_is_signed(t_expr) { llvm::LLVMConstSIToFP(v, llty.to_ref()) } else { llvm::LLVMConstUIToFP(v, llty.to_ref()) @@ -661,18 +661,18 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, llvm::LLVMConstFPCast(v, llty.to_ref()) } (CastTy::Float, CastTy::Int(_)) => { - if ty::type_is_signed(t_1) { llvm::LLVMConstFPToSI(v, llty.to_ref()) } + if ty::type_is_signed(t_expr) { llvm::LLVMConstFPToSI(v, llty.to_ref()) } else { llvm::LLVMConstFPToUI(v, llty.to_ref()) } } - (CastTy::Ptr(_), CastTy::Ptr(_)) | (CastTy::FPtr, CastTy::Ptr(_)) + (CastTy::Ptr(_), CastTy::Ptr(_)) | (CastTy::FnPtr, CastTy::Ptr(_)) | (CastTy::RPtr(_), CastTy::Ptr(_)) => { ptrcast(v, llty) } - (CastTy::FPtr, CastTy::FPtr) => ptrcast(v, llty), // isn't this a coercion? + (CastTy::FnPtr, CastTy::FnPtr) => ptrcast(v, llty), // isn't this a coercion? (CastTy::Int(_), CastTy::Ptr(_)) => { llvm::LLVMConstIntToPtr(v, llty.to_ref()) } - (CastTy::Ptr(_), CastTy::Int(_)) | (CastTy::FPtr, CastTy::Int(_)) => { + (CastTy::Ptr(_), CastTy::Int(_)) | (CastTy::FnPtr, CastTy::Int(_)) => { llvm::LLVMConstPtrToInt(v, llty.to_ref()) } _ => { diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index e5c9a818183..90741d1d58f 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -2086,8 +2086,8 @@ fn float_cast(bcx: Block, } } - let r_t_in = CastTy::recognize(bcx.tcx(), t_in).expect("bad input type for cast"); - let r_t_out = CastTy::recognize(bcx.tcx(), t_out).expect("bad output type for cast"); + let r_t_in = CastTy::from_ty(bcx.tcx(), t_in).expect("bad input type for cast"); + let r_t_out = CastTy::from_ty(bcx.tcx(), t_out).expect("bad output type for cast"); let (llexpr, signed) = if let Int(CEnum) = r_t_in { let repr = adt::represent_type(ccx, t_in); @@ -2102,8 +2102,10 @@ fn float_cast(bcx: Block, }; let newval = match (r_t_in, r_t_out) { - (Ptr(_), Ptr(_)) | (FPtr, Ptr(_)) | (RPtr(_), Ptr(_)) => PointerCast(bcx, llexpr, ll_t_out), - (Ptr(_), Int(_)) | (FPtr, Int(_)) => PtrToInt(bcx, llexpr, ll_t_out), + (Ptr(_), Ptr(_)) | (FnPtr, Ptr(_)) | (RPtr(_), Ptr(_)) => { + PointerCast(bcx, llexpr, ll_t_out) + } + (Ptr(_), Int(_)) | (FnPtr, Int(_)) => PtrToInt(bcx, llexpr, ll_t_out), (Int(_), Ptr(_)) => IntToPtr(bcx, llexpr, ll_t_out), (Int(_), Int(_)) => int_cast(bcx, ll_t_out, ll_t_in, llexpr, signed), diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index c3432546b7c..5258a77204d 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -56,11 +56,16 @@ pub struct CastCheck<'tcx> { span: Span, } +/// The kind of the unsize info (length or vtable) - we only allow casts between +/// fat pointers if their unsize-infos have the same kind. #[derive(Copy, Clone, PartialEq, Eq)] enum UnsizeKind<'tcx> { Vtable, Length, - OfTy(Ty<'tcx>) + /// The unsize info of this projection + OfProjection(&'tcx ty::ProjectionTy<'tcx>), + /// The unsize info of this parameter + OfParam(&'tcx ty::ParamTy) } /// Returns the kind of unsize information of t, or None @@ -77,8 +82,9 @@ fn unsize_kind<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>, Some(f) => unsize_kind(fcx, f.mt.ty) } } - ty::ty_projection(..) | ty::ty_param(..) => - Some(UnsizeKind::OfTy(t)), + // We should really try to normalize here. + ty::ty_projection(ref pi) => Some(UnsizeKind::OfProjection(pi)), + ty::ty_param(ref p) => Some(UnsizeKind::OfParam(p)), _ => None } } @@ -164,17 +170,17 @@ fn report_cast_error<'a>(&self, fcx: &FnCtxt<'a, 'tcx>, } fn trivial_cast_lint<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) { - let t_1 = self.cast_ty; - let t_e = self.expr_ty; - if ty::type_is_numeric(t_1) && ty::type_is_numeric(t_e) { + let t_cast = self.cast_ty; + let t_expr = self.expr_ty; + if ty::type_is_numeric(t_cast) && ty::type_is_numeric(t_expr) { fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_NUMERIC_CASTS, self.expr.id, self.span, format!("trivial numeric cast: `{}` as `{}`. Cast can be \ replaced by coercion, this might require type \ ascription or a temporary variable", - fcx.infcx().ty_to_string(t_e), - fcx.infcx().ty_to_string(t_1))); + fcx.infcx().ty_to_string(t_expr), + fcx.infcx().ty_to_string(t_cast))); } else { fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_CASTS, self.expr.id, @@ -182,8 +188,8 @@ fn trivial_cast_lint<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) { format!("trivial cast: `{}` as `{}`. Cast can be \ replaced by coercion, this might require type \ ascription or a temporary variable", - fcx.infcx().ty_to_string(t_e), - fcx.infcx().ty_to_string(t_1))); + fcx.infcx().ty_to_string(t_expr), + fcx.infcx().ty_to_string(t_cast))); } } @@ -211,24 +217,24 @@ pub fn check<'a>(mut self, fcx: &FnCtxt<'a, 'tcx>) { };} } - /// Check a cast, and report an error if one exists. In some cases, - /// this can return Ok and create type errors rather than returning + /// Check a cast, and report an error if one exists. In some cases, this + /// can return Ok and create type errors in the fcx rather than returning /// directly. coercion-cast is handled in check instead of here. fn do_check<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result { use middle::cast::IntTy::*; use middle::cast::CastTy::*; - let (t_e, t_1) = match (CastTy::recognize(fcx.tcx(), self.expr_ty), - CastTy::recognize(fcx.tcx(), self.cast_ty)) { - (Some(t_e), Some(t_1)) => (t_e, t_1), + let (t_from, t_cast) = match (CastTy::from_ty(fcx.tcx(), self.expr_ty), + CastTy::from_ty(fcx.tcx(), self.cast_ty)) { + (Some(t_from), Some(t_cast)) => (t_from, t_cast), _ => { return Err(CastError::NonScalar) } }; - match (t_e, t_1) { + match (t_from, t_cast) { // These types have invariants! can't cast into them. - (_, RPtr(_)) | (_, Int(CEnum)) | (_, FPtr) => Err(CastError::NonScalar), + (_, RPtr(_)) | (_, Int(CEnum)) | (_, FnPtr) => Err(CastError::NonScalar), // * -> Bool (_, Int(Bool)) => Err(CastError::CastToBool), @@ -244,14 +250,14 @@ fn do_check<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result { => Err(CastError::NeedViaUsize), // ptr -> * - (Ptr(m1), Ptr(m2)) => self.check_ptr_ptr_cast(fcx, m1, m2), // ptr-ptr-cast - (Ptr(m_e), Int(_)) => self.check_ptr_addr_cast(fcx, m_e), // ptr-addr-cast - (Ptr(_), Float) | (FPtr, Float) => Err(CastError::NeedViaUsize), - (FPtr, Int(_)) => Ok(CastKind::FPtrAddrCast), + (Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast + (Ptr(m_expr), Int(_)) => self.check_ptr_addr_cast(fcx, m_expr), // ptr-addr-cast + (Ptr(_), Float) | (FnPtr, Float) => Err(CastError::NeedViaUsize), + (FnPtr, Int(_)) => Ok(CastKind::FnPtrAddrCast), (RPtr(_), Int(_)) | (RPtr(_), Float) => Err(CastError::NeedViaPtr), // * -> ptr (Int(_), Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt), // addr-ptr-cast - (FPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt), + (FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt), (Float, Ptr(_)) => Err(CastError::NeedViaUsize), (RPtr(rmt), Ptr(mt)) => self.check_ref_cast(fcx, rmt, mt), // array-ptr-cast @@ -269,26 +275,26 @@ fn do_check<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result { fn check_ptr_ptr_cast<'a>(&self, fcx: &FnCtxt<'a, 'tcx>, - m_e: &'tcx ty::mt<'tcx>, - m_1: &'tcx ty::mt<'tcx>) + m_expr: &'tcx ty::mt<'tcx>, + m_cast: &'tcx ty::mt<'tcx>) -> Result { - debug!("check_ptr_ptr_cast m_e={} m_1={}", - m_e.repr(fcx.tcx()), m_1.repr(fcx.tcx())); + debug!("check_ptr_ptr_cast m_expr={} m_cast={}", + m_expr.repr(fcx.tcx()), m_cast.repr(fcx.tcx())); // ptr-ptr cast. vtables must match. // Cast to sized is OK - if fcx.type_is_known_to_be_sized(m_1.ty, self.span) { + if fcx.type_is_known_to_be_sized(m_cast.ty, self.span) { return Ok(CastKind::PtrPtrCast); } // sized -> unsized? report illegal cast (don't complain about vtable kinds) - if fcx.type_is_known_to_be_sized(m_e.ty, self.span) { + if fcx.type_is_known_to_be_sized(m_expr.ty, self.span) { return Err(CastError::IllegalCast); } // vtable kinds must match - match (unsize_kind(fcx, m_1.ty), unsize_kind(fcx, m_e.ty)) { + match (unsize_kind(fcx, m_cast.ty), unsize_kind(fcx, m_expr.ty)) { (Some(a), Some(b)) if a == b => Ok(CastKind::PtrPtrCast), _ => Err(CastError::DifferingKinds) } @@ -296,13 +302,13 @@ fn check_ptr_ptr_cast<'a>(&self, fn check_fptr_ptr_cast<'a>(&self, fcx: &FnCtxt<'a, 'tcx>, - m_1: &'tcx ty::mt<'tcx>) + m_cast: &'tcx ty::mt<'tcx>) -> Result { // fptr-ptr cast. must be to sized ptr - if fcx.type_is_known_to_be_sized(m_1.ty, self.span) { - Ok(CastKind::FPtrPtrCast) + if fcx.type_is_known_to_be_sized(m_cast.ty, self.span) { + Ok(CastKind::FnPtrPtrCast) } else { Err(CastError::IllegalCast) } @@ -310,12 +316,12 @@ fn check_fptr_ptr_cast<'a>(&self, fn check_ptr_addr_cast<'a>(&self, fcx: &FnCtxt<'a, 'tcx>, - m_e: &'tcx ty::mt<'tcx>) + m_expr: &'tcx ty::mt<'tcx>) -> Result { // ptr-addr cast. must be from sized ptr - if fcx.type_is_known_to_be_sized(m_e.ty, self.span) { + if fcx.type_is_known_to_be_sized(m_expr.ty, self.span) { Ok(CastKind::PtrAddrCast) } else { Err(CastError::NeedViaPtr) @@ -324,14 +330,14 @@ fn check_ptr_addr_cast<'a>(&self, fn check_ref_cast<'a>(&self, fcx: &FnCtxt<'a, 'tcx>, - m_e: &'tcx ty::mt<'tcx>, - m_1: &'tcx ty::mt<'tcx>) + m_expr: &'tcx ty::mt<'tcx>, + m_cast: &'tcx ty::mt<'tcx>) -> Result { // array-ptr-cast. - if m_e.mutbl == ast::MutImmutable && m_1.mutbl == ast::MutImmutable { - if let ty::ty_vec(ety, Some(_)) = m_e.ty.sty { + if m_expr.mutbl == ast::MutImmutable && m_cast.mutbl == ast::MutImmutable { + if let ty::ty_vec(ety, Some(_)) = m_expr.ty.sty { // Due to the limitations of LLVM global constants, // region pointers end up pointing at copies of // vector elements instead of the original values. @@ -340,7 +346,7 @@ fn check_ref_cast<'a>(&self, // from a region pointer to a vector. // this will report a type mismatch if needed - demand::eqtype(fcx, self.span, ety, m_1.ty); + demand::eqtype(fcx, self.span, ety, m_cast.ty); return Ok(CastKind::ArrayPtrCast); } } @@ -350,11 +356,11 @@ fn check_ref_cast<'a>(&self, fn check_addr_ptr_cast<'a>(&self, fcx: &FnCtxt<'a, 'tcx>, - m_1: &'tcx ty::mt<'tcx>) + m_cast: &'tcx ty::mt<'tcx>) -> Result { // ptr-addr cast. pointer must be thin. - if fcx.type_is_known_to_be_sized(m_1.ty, self.span) { + if fcx.type_is_known_to_be_sized(m_cast.ty, self.span) { Ok(CastKind::AddrPtrCast) } else { Err(CastError::IllegalCast) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d5e3139016f..0e64063d6a4 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1115,20 +1115,20 @@ fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, t_span: Span, e_span: Span, - t_1: Ty<'tcx>, - t_e: Ty<'tcx>, + t_cast: Ty<'tcx>, + t_expr: Ty<'tcx>, id: ast::NodeId) { - let tstr = fcx.infcx().ty_to_string(t_1); + let tstr = fcx.infcx().ty_to_string(t_cast); fcx.type_error_message(span, |actual| { format!("cast to unsized type: `{}` as `{}`", actual, tstr) - }, t_e, None); - match t_e.sty { + }, t_expr, None); + match t_expr.sty { ty::ty_rptr(_, ty::mt { mutbl: mt, .. }) => { let mtstr = match mt { ast::MutMutable => "mut ", ast::MutImmutable => "" }; - if ty::type_is_trait(t_1) { + if ty::type_is_trait(t_cast) { match fcx.tcx().sess.codemap().span_to_snippet(t_span) { Ok(s) => { fcx.tcx().sess.span_suggestion(t_span, @@ -3404,24 +3404,24 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, // 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); + let t_cast = fcx.to_ty(t); + let t_cast = structurally_resolved_type(fcx, expr.span, t_cast); + check_expr_with_expectation(fcx, e, ExpectCastableToType(t_cast)); + let t_expr = fcx.expr_ty(e); // Eagerly check for some obvious errors. - if ty::type_is_error(t_e) { + if ty::type_is_error(t_expr) { 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 if !fcx.type_is_known_to_be_sized(t_cast, expr.span) { + report_cast_to_unsized_type(fcx, expr.span, t.span, e.span, t_cast, t_expr, id); } else { // Write a type for the whole expression, assuming everything is going // to work out Ok. - fcx.write_ty(id, t_1); + fcx.write_ty(id, t_cast); // Defer other checks until we're done type checking. let mut deferred_cast_checks = fcx.inh.deferred_cast_checks.borrow_mut(); - let cast_check = cast::CastCheck::new((**e).clone(), t_e, t_1, expr.span); + let cast_check = cast::CastCheck::new((**e).clone(), t_expr, t_cast, expr.span); deferred_cast_checks.push(cast_check); } } diff --git a/src/test/compile-fail/associated-types-incomplete-object.rs b/src/test/compile-fail/associated-types-incomplete-object.rs index 1c708da30a7..c1feb8ac459 100644 --- a/src/test/compile-fail/associated-types-incomplete-object.rs +++ b/src/test/compile-fail/associated-types-incomplete-object.rs @@ -28,15 +28,15 @@ fn boo(&self) -> usize { } pub fn main() { - let a = &42 as &Foo; + let a = &42isize as &Foo; - let b = &42 as &Foo; + let b = &42isize as &Foo; //~^ ERROR the value of the associated type `B` (from the trait `Foo`) must be specified - let c = &42 as &Foo; + let c = &42isize as &Foo; //~^ ERROR the value of the associated type `A` (from the trait `Foo`) must be specified - let d = &42 as &Foo; + let d = &42isize as &Foo; //~^ ERROR the value of the associated type `A` (from the trait `Foo`) must be specified //~| ERROR the value of the associated type `B` (from the trait `Foo`) must be specified } diff --git a/src/test/compile-fail/cast-rfc0401.rs b/src/test/compile-fail/cast-rfc0401.rs index 69ef5421377..f3537e54135 100644 --- a/src/test/compile-fail/cast-rfc0401.rs +++ b/src/test/compile-fail/cast-rfc0401.rs @@ -65,6 +65,10 @@ fn main() let _ = &f as *const f64; //~ ERROR illegal cast let _ = fat_v as usize; //~ ERROR through a raw pointer first + let a : *const str = "hello"; + let _ = a as *const Foo; + //~^ ERROR `core::marker::Sized` is not implemented for the type `str` + // check no error cascade let _ = main.f as *const u32; //~ ERROR attempted access of field diff --git a/src/test/compile-fail/destructure-trait-ref.rs b/src/test/compile-fail/destructure-trait-ref.rs index 3f455e148a0..08db643df00 100644 --- a/src/test/compile-fail/destructure-trait-ref.rs +++ b/src/test/compile-fail/destructure-trait-ref.rs @@ -28,29 +28,29 @@ fn main() { // if n > m, it's a type mismatch error. // n < m - let &x = &(&1 as &T); - let &x = &&(&1 as &T); - let &&x = &&(&1 as &T); + let &x = &(&1isize as &T); + let &x = &&(&1isize as &T); + let &&x = &&(&1isize as &T); // n == m - let &x = &1 as &T; //~ ERROR type `&T` cannot be dereferenced - let &&x = &(&1 as &T); //~ ERROR type `&T` cannot be dereferenced - let box x = box 1 as Box; //~ ERROR the trait `core::marker::Sized` is not implemented + let &x = &1isize as &T; //~ ERROR type `&T` cannot be dereferenced + let &&x = &(&1isize as &T); //~ ERROR type `&T` cannot be dereferenced + let box x = box 1isize as Box; //~ ERROR the trait `core::marker::Sized` is not implemented // n > m - let &&x = &1 as &T; + let &&x = &1isize as &T; //~^ ERROR mismatched types //~| expected `T` //~| found `&_` //~| expected trait T //~| found &-ptr - let &&&x = &(&1 as &T); + let &&&x = &(&1isize as &T); //~^ ERROR mismatched types //~| expected `T` //~| found `&_` //~| expected trait T //~| found &-ptr - let box box x = box 1 as Box; + let box box x = box 1isize as Box; //~^ ERROR mismatched types //~| expected `T` //~| found `Box<_>` diff --git a/src/test/compile-fail/issue-17458.rs b/src/test/compile-fail/issue-17458.rs index d6f70ae1e57..a3a9e17cb3c 100644 --- a/src/test/compile-fail/issue-17458.rs +++ b/src/test/compile-fail/issue-17458.rs @@ -9,7 +9,7 @@ // except according to those terms. static X: usize = 0 as *const usize as usize; -//~^ ERROR: can not cast a pointer to an integer in statics +//~^ ERROR: can't cast a pointer to an integer in statics fn main() { assert_eq!(X, 0); diff --git a/src/test/compile-fail/issue-5153.rs b/src/test/compile-fail/issue-5153.rs index da32408e199..b1d96f9b527 100644 --- a/src/test/compile-fail/issue-5153.rs +++ b/src/test/compile-fail/issue-5153.rs @@ -17,6 +17,6 @@ fn foo(self: Box) { } } fn main() { - (&5 as &Foo).foo(); + (&5isize as &Foo).foo(); //~^ ERROR: no method named `foo` found for type `&Foo` in the current scope } diff --git a/src/test/compile-fail/kindck-impl-type-params.rs b/src/test/compile-fail/kindck-impl-type-params.rs index d4ee93e9ca5..988a7837b59 100644 --- a/src/test/compile-fail/kindck-impl-type-params.rs +++ b/src/test/compile-fail/kindck-impl-type-params.rs @@ -28,7 +28,6 @@ fn f(val: T) { let a = &t as &Gettable; //~^ 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(val: T) { diff --git a/src/test/run-pass/cast-enum-with-dtor.rs b/src/test/run-pass-valgrind/cast-enum-with-dtor.rs similarity index 100% rename from src/test/run-pass/cast-enum-with-dtor.rs rename to src/test/run-pass-valgrind/cast-enum-with-dtor.rs diff --git a/src/test/run-pass/cast-rfc0401-vtable-kinds.rs b/src/test/run-pass/cast-rfc0401-vtable-kinds.rs index 76516a69f79..e53d4af8e36 100644 --- a/src/test/run-pass/cast-rfc0401-vtable-kinds.rs +++ b/src/test/run-pass/cast-rfc0401-vtable-kinds.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Check that you can cast between different pointers to trait objects +// whose vtable have the same kind (both lengths, or both trait pointers). + trait Foo { fn foo(&self, _: T) -> u32 { 42 } } -- 2.44.0