Skip to content

Commit 24ec21b

Browse files
Ariel Ben-Yehudaarielb1
Ariel Ben-Yehuda
authored andcommitted
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.
1 parent da0e10f commit 24ec21b

File tree

14 files changed

+123
-103
lines changed

14 files changed

+123
-103
lines changed

src/librustc/middle/cast.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use middle::ty::{self, Ty};
1515

1616
use syntax::ast;
1717

18-
18+
/// Types that are represented as ints.
1919
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2020
pub enum IntTy {
2121
U(ast::UintTy),
@@ -28,10 +28,16 @@ pub enum IntTy {
2828
// Valid types for the result of a non-coercion cast
2929
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
3030
pub enum CastTy<'tcx> {
31+
/// Various types that are represented as ints and handled mostly
32+
/// in the same way, merged for easier matching.
3133
Int(IntTy),
34+
/// Floating-Point types
3235
Float,
33-
FPtr,
36+
/// Function Pointers
37+
FnPtr,
38+
/// Raw pointers
3439
Ptr(&'tcx ty::mt<'tcx>),
40+
/// References
3541
RPtr(&'tcx ty::mt<'tcx>),
3642
}
3743

@@ -47,13 +53,13 @@ pub enum CastKind {
4753
PrimIntCast,
4854
U8CharCast,
4955
ArrayPtrCast,
50-
FPtrPtrCast,
51-
FPtrAddrCast
56+
FnPtrPtrCast,
57+
FnPtrAddrCast
5258
}
5359

5460
impl<'tcx> CastTy<'tcx> {
55-
pub fn recognize(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>)
56-
-> Option<CastTy<'tcx>> {
61+
pub fn from_ty(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>)
62+
-> Option<CastTy<'tcx>> {
5763
match t.sty {
5864
ty::ty_bool => Some(CastTy::Int(IntTy::Bool)),
5965
ty::ty_char => Some(CastTy::Int(IntTy::Char)),
@@ -64,7 +70,7 @@ impl<'tcx> CastTy<'tcx> {
6470
tcx, t) => Some(CastTy::Int(IntTy::CEnum)),
6571
ty::ty_ptr(ref mt) => Some(CastTy::Ptr(mt)),
6672
ty::ty_rptr(_, ref mt) => Some(CastTy::RPtr(mt)),
67-
ty::ty_bare_fn(..) => Some(CastTy::FPtr),
73+
ty::ty_bare_fn(..) => Some(CastTy::FnPtr),
6874
_ => None,
6975
}
7076
}

src/librustc/middle/check_const.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -443,11 +443,11 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
443443
debug!("Checking const cast(id={})", from.id);
444444
match v.tcx.cast_kinds.borrow().get(&from.id) {
445445
None => v.tcx.sess.span_bug(e.span, "no kind for cast"),
446-
Some(&CastKind::PtrAddrCast) | Some(&CastKind::FPtrAddrCast) => {
446+
Some(&CastKind::PtrAddrCast) | Some(&CastKind::FnPtrAddrCast) => {
447447
v.add_qualif(ConstQualif::NOT_CONST);
448448
if v.mode != Mode::Var {
449449
span_err!(v.tcx.sess, e.span, E0018,
450-
"can not cast a pointer to an integer in {}s", v.msg());
450+
"can't cast a pointer to an integer in {}s", v.msg());
451451
}
452452
}
453453
_ => {}

src/librustc_trans/trans/consts.rs

+18-18
Original file line numberDiff line numberDiff line change
@@ -617,41 +617,41 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
617617
}
618618
}
619619
ast::ExprCast(ref base, _) => {
620-
let t_1 = ety;
621-
let llty = type_of::type_of(cx, t_1);
622-
let (v, t_e) = const_expr(cx, &**base, param_substs);
623-
debug!("trans_const_cast({} as {})", t_e.repr(cx.tcx()), t_1.repr(cx.tcx()));
624-
if expr::cast_is_noop(cx.tcx(), base, t_e, t_1) {
620+
let t_cast = ety;
621+
let llty = type_of::type_of(cx, t_cast);
622+
let (v, t_expr) = const_expr(cx, &**base, param_substs);
623+
debug!("trans_const_cast({} as {})", t_expr.repr(cx.tcx()), t_cast.repr(cx.tcx()));
624+
if expr::cast_is_noop(cx.tcx(), base, t_expr, t_cast) {
625625
return v;
626626
}
627-
if type_is_fat_ptr(cx.tcx(), t_e) {
627+
if type_is_fat_ptr(cx.tcx(), t_expr) {
628628
// Fat pointer casts.
629-
let t_1_inner = ty::deref(t_1, true).expect("cast to non-pointer").ty;
630-
let ptr_ty = type_of::in_memory_type_of(cx, t_1_inner).ptr_to();
629+
let t_cast_inner = ty::deref(t_cast, true).expect("cast to non-pointer").ty;
630+
let ptr_ty = type_of::in_memory_type_of(cx, t_cast_inner).ptr_to();
631631
let addr = ptrcast(const_get_elt(cx, v, &[abi::FAT_PTR_ADDR as u32]),
632632
ptr_ty);
633-
if type_is_fat_ptr(cx.tcx(), t_1) {
633+
if type_is_fat_ptr(cx.tcx(), t_cast) {
634634
let info = const_get_elt(cx, v, &[abi::FAT_PTR_EXTRA as u32]);
635635
return C_struct(cx, &[addr, info], false)
636636
} else {
637637
return addr;
638638
}
639639
}
640-
match (CastTy::recognize(cx.tcx(), t_e).expect("bad input type for cast"),
641-
CastTy::recognize(cx.tcx(), t_1).expect("bad output type for cast")) {
640+
match (CastTy::from_ty(cx.tcx(), t_expr).expect("bad input type for cast"),
641+
CastTy::from_ty(cx.tcx(), t_cast).expect("bad output type for cast")) {
642642
(CastTy::Int(IntTy::CEnum), CastTy::Int(_)) => {
643-
let repr = adt::represent_type(cx, t_e);
643+
let repr = adt::represent_type(cx, t_expr);
644644
let discr = adt::const_get_discrim(cx, &*repr, v);
645645
let iv = C_integral(cx.int_type(), discr, false);
646646
let s = adt::is_discr_signed(&*repr) as Bool;
647647
llvm::LLVMConstIntCast(iv, llty.to_ref(), s)
648648
}
649649
(CastTy::Int(_), CastTy::Int(_)) => {
650-
let s = ty::type_is_signed(t_e) as Bool;
650+
let s = ty::type_is_signed(t_expr) as Bool;
651651
llvm::LLVMConstIntCast(v, llty.to_ref(), s)
652652
}
653653
(CastTy::Int(_), CastTy::Float) => {
654-
if ty::type_is_signed(t_e) {
654+
if ty::type_is_signed(t_expr) {
655655
llvm::LLVMConstSIToFP(v, llty.to_ref())
656656
} else {
657657
llvm::LLVMConstUIToFP(v, llty.to_ref())
@@ -661,18 +661,18 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
661661
llvm::LLVMConstFPCast(v, llty.to_ref())
662662
}
663663
(CastTy::Float, CastTy::Int(_)) => {
664-
if ty::type_is_signed(t_1) { llvm::LLVMConstFPToSI(v, llty.to_ref()) }
664+
if ty::type_is_signed(t_expr) { llvm::LLVMConstFPToSI(v, llty.to_ref()) }
665665
else { llvm::LLVMConstFPToUI(v, llty.to_ref()) }
666666
}
667-
(CastTy::Ptr(_), CastTy::Ptr(_)) | (CastTy::FPtr, CastTy::Ptr(_))
667+
(CastTy::Ptr(_), CastTy::Ptr(_)) | (CastTy::FnPtr, CastTy::Ptr(_))
668668
| (CastTy::RPtr(_), CastTy::Ptr(_)) => {
669669
ptrcast(v, llty)
670670
}
671-
(CastTy::FPtr, CastTy::FPtr) => ptrcast(v, llty), // isn't this a coercion?
671+
(CastTy::FnPtr, CastTy::FnPtr) => ptrcast(v, llty), // isn't this a coercion?
672672
(CastTy::Int(_), CastTy::Ptr(_)) => {
673673
llvm::LLVMConstIntToPtr(v, llty.to_ref())
674674
}
675-
(CastTy::Ptr(_), CastTy::Int(_)) | (CastTy::FPtr, CastTy::Int(_)) => {
675+
(CastTy::Ptr(_), CastTy::Int(_)) | (CastTy::FnPtr, CastTy::Int(_)) => {
676676
llvm::LLVMConstPtrToInt(v, llty.to_ref())
677677
}
678678
_ => {

src/librustc_trans/trans/expr.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -2086,8 +2086,8 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
20862086
}
20872087
}
20882088

2089-
let r_t_in = CastTy::recognize(bcx.tcx(), t_in).expect("bad input type for cast");
2090-
let r_t_out = CastTy::recognize(bcx.tcx(), t_out).expect("bad output type for cast");
2089+
let r_t_in = CastTy::from_ty(bcx.tcx(), t_in).expect("bad input type for cast");
2090+
let r_t_out = CastTy::from_ty(bcx.tcx(), t_out).expect("bad output type for cast");
20912091

20922092
let (llexpr, signed) = if let Int(CEnum) = r_t_in {
20932093
let repr = adt::represent_type(ccx, t_in);
@@ -2102,8 +2102,10 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
21022102
};
21032103

21042104
let newval = match (r_t_in, r_t_out) {
2105-
(Ptr(_), Ptr(_)) | (FPtr, Ptr(_)) | (RPtr(_), Ptr(_)) => PointerCast(bcx, llexpr, ll_t_out),
2106-
(Ptr(_), Int(_)) | (FPtr, Int(_)) => PtrToInt(bcx, llexpr, ll_t_out),
2105+
(Ptr(_), Ptr(_)) | (FnPtr, Ptr(_)) | (RPtr(_), Ptr(_)) => {
2106+
PointerCast(bcx, llexpr, ll_t_out)
2107+
}
2108+
(Ptr(_), Int(_)) | (FnPtr, Int(_)) => PtrToInt(bcx, llexpr, ll_t_out),
21072109
(Int(_), Ptr(_)) => IntToPtr(bcx, llexpr, ll_t_out),
21082110

21092111
(Int(_), Int(_)) => int_cast(bcx, ll_t_out, ll_t_in, llexpr, signed),

src/librustc_typeck/check/cast.rs

+47-41
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,16 @@ pub struct CastCheck<'tcx> {
5656
span: Span,
5757
}
5858

59+
/// The kind of the unsize info (length or vtable) - we only allow casts between
60+
/// fat pointers if their unsize-infos have the same kind.
5961
#[derive(Copy, Clone, PartialEq, Eq)]
6062
enum UnsizeKind<'tcx> {
6163
Vtable,
6264
Length,
63-
OfTy(Ty<'tcx>)
65+
/// The unsize info of this projection
66+
OfProjection(&'tcx ty::ProjectionTy<'tcx>),
67+
/// The unsize info of this parameter
68+
OfParam(&'tcx ty::ParamTy)
6469
}
6570

6671
/// Returns the kind of unsize information of t, or None
@@ -77,8 +82,9 @@ fn unsize_kind<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
7782
Some(f) => unsize_kind(fcx, f.mt.ty)
7883
}
7984
}
80-
ty::ty_projection(..) | ty::ty_param(..) =>
81-
Some(UnsizeKind::OfTy(t)),
85+
// We should really try to normalize here.
86+
ty::ty_projection(ref pi) => Some(UnsizeKind::OfProjection(pi)),
87+
ty::ty_param(ref p) => Some(UnsizeKind::OfParam(p)),
8288
_ => None
8389
}
8490
}
@@ -164,26 +170,26 @@ impl<'tcx> CastCheck<'tcx> {
164170
}
165171

166172
fn trivial_cast_lint<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) {
167-
let t_1 = self.cast_ty;
168-
let t_e = self.expr_ty;
169-
if ty::type_is_numeric(t_1) && ty::type_is_numeric(t_e) {
173+
let t_cast = self.cast_ty;
174+
let t_expr = self.expr_ty;
175+
if ty::type_is_numeric(t_cast) && ty::type_is_numeric(t_expr) {
170176
fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_NUMERIC_CASTS,
171177
self.expr.id,
172178
self.span,
173179
format!("trivial numeric cast: `{}` as `{}`. Cast can be \
174180
replaced by coercion, this might require type \
175181
ascription or a temporary variable",
176-
fcx.infcx().ty_to_string(t_e),
177-
fcx.infcx().ty_to_string(t_1)));
182+
fcx.infcx().ty_to_string(t_expr),
183+
fcx.infcx().ty_to_string(t_cast)));
178184
} else {
179185
fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_CASTS,
180186
self.expr.id,
181187
self.span,
182188
format!("trivial cast: `{}` as `{}`. Cast can be \
183189
replaced by coercion, this might require type \
184190
ascription or a temporary variable",
185-
fcx.infcx().ty_to_string(t_e),
186-
fcx.infcx().ty_to_string(t_1)));
191+
fcx.infcx().ty_to_string(t_expr),
192+
fcx.infcx().ty_to_string(t_cast)));
187193
}
188194

189195
}
@@ -211,24 +217,24 @@ impl<'tcx> CastCheck<'tcx> {
211217
};}
212218
}
213219

214-
/// Check a cast, and report an error if one exists. In some cases,
215-
/// this can return Ok and create type errors rather than returning
220+
/// Check a cast, and report an error if one exists. In some cases, this
221+
/// can return Ok and create type errors in the fcx rather than returning
216222
/// directly. coercion-cast is handled in check instead of here.
217223
fn do_check<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<CastKind, CastError> {
218224
use middle::cast::IntTy::*;
219225
use middle::cast::CastTy::*;
220226

221-
let (t_e, t_1) = match (CastTy::recognize(fcx.tcx(), self.expr_ty),
222-
CastTy::recognize(fcx.tcx(), self.cast_ty)) {
223-
(Some(t_e), Some(t_1)) => (t_e, t_1),
227+
let (t_from, t_cast) = match (CastTy::from_ty(fcx.tcx(), self.expr_ty),
228+
CastTy::from_ty(fcx.tcx(), self.cast_ty)) {
229+
(Some(t_from), Some(t_cast)) => (t_from, t_cast),
224230
_ => {
225231
return Err(CastError::NonScalar)
226232
}
227233
};
228234

229-
match (t_e, t_1) {
235+
match (t_from, t_cast) {
230236
// These types have invariants! can't cast into them.
231-
(_, RPtr(_)) | (_, Int(CEnum)) | (_, FPtr) => Err(CastError::NonScalar),
237+
(_, RPtr(_)) | (_, Int(CEnum)) | (_, FnPtr) => Err(CastError::NonScalar),
232238

233239
// * -> Bool
234240
(_, Int(Bool)) => Err(CastError::CastToBool),
@@ -244,14 +250,14 @@ impl<'tcx> CastCheck<'tcx> {
244250
=> Err(CastError::NeedViaUsize),
245251

246252
// ptr -> *
247-
(Ptr(m1), Ptr(m2)) => self.check_ptr_ptr_cast(fcx, m1, m2), // ptr-ptr-cast
248-
(Ptr(m_e), Int(_)) => self.check_ptr_addr_cast(fcx, m_e), // ptr-addr-cast
249-
(Ptr(_), Float) | (FPtr, Float) => Err(CastError::NeedViaUsize),
250-
(FPtr, Int(_)) => Ok(CastKind::FPtrAddrCast),
253+
(Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast
254+
(Ptr(m_expr), Int(_)) => self.check_ptr_addr_cast(fcx, m_expr), // ptr-addr-cast
255+
(Ptr(_), Float) | (FnPtr, Float) => Err(CastError::NeedViaUsize),
256+
(FnPtr, Int(_)) => Ok(CastKind::FnPtrAddrCast),
251257
(RPtr(_), Int(_)) | (RPtr(_), Float) => Err(CastError::NeedViaPtr),
252258
// * -> ptr
253259
(Int(_), Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt), // addr-ptr-cast
254-
(FPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt),
260+
(FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt),
255261
(Float, Ptr(_)) => Err(CastError::NeedViaUsize),
256262
(RPtr(rmt), Ptr(mt)) => self.check_ref_cast(fcx, rmt, mt), // array-ptr-cast
257263

@@ -269,53 +275,53 @@ impl<'tcx> CastCheck<'tcx> {
269275

270276
fn check_ptr_ptr_cast<'a>(&self,
271277
fcx: &FnCtxt<'a, 'tcx>,
272-
m_e: &'tcx ty::mt<'tcx>,
273-
m_1: &'tcx ty::mt<'tcx>)
278+
m_expr: &'tcx ty::mt<'tcx>,
279+
m_cast: &'tcx ty::mt<'tcx>)
274280
-> Result<CastKind, CastError>
275281
{
276-
debug!("check_ptr_ptr_cast m_e={} m_1={}",
277-
m_e.repr(fcx.tcx()), m_1.repr(fcx.tcx()));
282+
debug!("check_ptr_ptr_cast m_expr={} m_cast={}",
283+
m_expr.repr(fcx.tcx()), m_cast.repr(fcx.tcx()));
278284
// ptr-ptr cast. vtables must match.
279285

280286
// Cast to sized is OK
281-
if fcx.type_is_known_to_be_sized(m_1.ty, self.span) {
287+
if fcx.type_is_known_to_be_sized(m_cast.ty, self.span) {
282288
return Ok(CastKind::PtrPtrCast);
283289
}
284290

285291
// sized -> unsized? report illegal cast (don't complain about vtable kinds)
286-
if fcx.type_is_known_to_be_sized(m_e.ty, self.span) {
292+
if fcx.type_is_known_to_be_sized(m_expr.ty, self.span) {
287293
return Err(CastError::IllegalCast);
288294
}
289295

290296
// vtable kinds must match
291-
match (unsize_kind(fcx, m_1.ty), unsize_kind(fcx, m_e.ty)) {
297+
match (unsize_kind(fcx, m_cast.ty), unsize_kind(fcx, m_expr.ty)) {
292298
(Some(a), Some(b)) if a == b => Ok(CastKind::PtrPtrCast),
293299
_ => Err(CastError::DifferingKinds)
294300
}
295301
}
296302

297303
fn check_fptr_ptr_cast<'a>(&self,
298304
fcx: &FnCtxt<'a, 'tcx>,
299-
m_1: &'tcx ty::mt<'tcx>)
305+
m_cast: &'tcx ty::mt<'tcx>)
300306
-> Result<CastKind, CastError>
301307
{
302308
// fptr-ptr cast. must be to sized ptr
303309

304-
if fcx.type_is_known_to_be_sized(m_1.ty, self.span) {
305-
Ok(CastKind::FPtrPtrCast)
310+
if fcx.type_is_known_to_be_sized(m_cast.ty, self.span) {
311+
Ok(CastKind::FnPtrPtrCast)
306312
} else {
307313
Err(CastError::IllegalCast)
308314
}
309315
}
310316

311317
fn check_ptr_addr_cast<'a>(&self,
312318
fcx: &FnCtxt<'a, 'tcx>,
313-
m_e: &'tcx ty::mt<'tcx>)
319+
m_expr: &'tcx ty::mt<'tcx>)
314320
-> Result<CastKind, CastError>
315321
{
316322
// ptr-addr cast. must be from sized ptr
317323

318-
if fcx.type_is_known_to_be_sized(m_e.ty, self.span) {
324+
if fcx.type_is_known_to_be_sized(m_expr.ty, self.span) {
319325
Ok(CastKind::PtrAddrCast)
320326
} else {
321327
Err(CastError::NeedViaPtr)
@@ -324,14 +330,14 @@ impl<'tcx> CastCheck<'tcx> {
324330

325331
fn check_ref_cast<'a>(&self,
326332
fcx: &FnCtxt<'a, 'tcx>,
327-
m_e: &'tcx ty::mt<'tcx>,
328-
m_1: &'tcx ty::mt<'tcx>)
333+
m_expr: &'tcx ty::mt<'tcx>,
334+
m_cast: &'tcx ty::mt<'tcx>)
329335
-> Result<CastKind, CastError>
330336
{
331337
// array-ptr-cast.
332338

333-
if m_e.mutbl == ast::MutImmutable && m_1.mutbl == ast::MutImmutable {
334-
if let ty::ty_vec(ety, Some(_)) = m_e.ty.sty {
339+
if m_expr.mutbl == ast::MutImmutable && m_cast.mutbl == ast::MutImmutable {
340+
if let ty::ty_vec(ety, Some(_)) = m_expr.ty.sty {
335341
// Due to the limitations of LLVM global constants,
336342
// region pointers end up pointing at copies of
337343
// vector elements instead of the original values.
@@ -340,7 +346,7 @@ impl<'tcx> CastCheck<'tcx> {
340346
// from a region pointer to a vector.
341347

342348
// this will report a type mismatch if needed
343-
demand::eqtype(fcx, self.span, ety, m_1.ty);
349+
demand::eqtype(fcx, self.span, ety, m_cast.ty);
344350
return Ok(CastKind::ArrayPtrCast);
345351
}
346352
}
@@ -350,11 +356,11 @@ impl<'tcx> CastCheck<'tcx> {
350356

351357
fn check_addr_ptr_cast<'a>(&self,
352358
fcx: &FnCtxt<'a, 'tcx>,
353-
m_1: &'tcx ty::mt<'tcx>)
359+
m_cast: &'tcx ty::mt<'tcx>)
354360
-> Result<CastKind, CastError>
355361
{
356362
// ptr-addr cast. pointer must be thin.
357-
if fcx.type_is_known_to_be_sized(m_1.ty, self.span) {
363+
if fcx.type_is_known_to_be_sized(m_cast.ty, self.span) {
358364
Ok(CastKind::AddrPtrCast)
359365
} else {
360366
Err(CastError::IllegalCast)

0 commit comments

Comments
 (0)