Skip to content

Commit b702e4e

Browse files
committed
---
yaml --- r: 152834 b: refs/heads/try2 c: f21b295 h: refs/heads/master v: v3
1 parent 00020cc commit b702e4e

File tree

4 files changed

+132
-194
lines changed

4 files changed

+132
-194
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: 78a7676898d9f80ab540c6df5d4c9ce35bb50463
55
refs/heads/try: 519addf6277dbafccbb4159db4b710c37eaa2ec5
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: bab614f5fa725d248afc5f0530c835f37998ce8f
8+
refs/heads/try2: f21b29560c74d44b0401f208f2d0f9a7889694b1
99
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try2/src/librustc/middle/typeck/check/mod.rs

Lines changed: 129 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,164 +1060,6 @@ fn compare_impl_method(tcx: &ty::ctxt,
10601060
}
10611061
}
10621062

1063-
fn check_cast(fcx: &FnCtxt,
1064-
e: &ast::Expr,
1065-
t: &ast::Ty,
1066-
id: ast::NodeId,
1067-
span: Span) {
1068-
// Find the type of `e`. Supply hints based on the type we are casting to,
1069-
// if appropriate.
1070-
let t_1 = fcx.to_ty(t);
1071-
let t_1 = structurally_resolved_type(fcx, span, t_1);
1072-
1073-
if ty::type_is_scalar(t_1) {
1074-
// Supply the type as a hint so as to influence integer
1075-
// literals and other things that might care.
1076-
check_expr_with_hint(fcx, e, t_1)
1077-
} else {
1078-
check_expr(fcx, e)
1079-
}
1080-
1081-
let t_e = fcx.expr_ty(e);
1082-
1083-
debug!("t_1={}", fcx.infcx().ty_to_str(t_1));
1084-
debug!("t_e={}", fcx.infcx().ty_to_str(t_e));
1085-
1086-
if ty::type_is_error(t_e) {
1087-
fcx.write_error(id);
1088-
return
1089-
}
1090-
if ty::type_is_bot(t_e) {
1091-
fcx.write_bot(id);
1092-
return
1093-
}
1094-
1095-
if ty::type_is_trait(t_1) {
1096-
// This will be looked up later on.
1097-
fcx.write_ty(id, t_1);
1098-
return
1099-
}
1100-
1101-
let t_1 = structurally_resolved_type(fcx, span, t_1);
1102-
let t_e = structurally_resolved_type(fcx, span, t_e);
1103-
1104-
if ty::type_is_nil(t_e) {
1105-
fcx.type_error_message(span, |actual| {
1106-
format!("cast from nil: `{}` as `{}`",
1107-
actual,
1108-
fcx.infcx().ty_to_str(t_1))
1109-
}, t_e, None);
1110-
} else if ty::type_is_nil(t_1) {
1111-
fcx.type_error_message(span, |actual| {
1112-
format!("cast to nil: `{}` as `{}`",
1113-
actual,
1114-
fcx.infcx().ty_to_str(t_1))
1115-
}, t_e, None);
1116-
}
1117-
1118-
let t_1_is_scalar = ty::type_is_scalar(t_1);
1119-
let t_1_is_char = ty::type_is_char(t_1);
1120-
let t_1_is_bare_fn = ty::type_is_bare_fn(t_1);
1121-
let t_1_is_float = ty::type_is_floating_point(t_1);
1122-
1123-
// casts to scalars other than `char` and `bare fn` are trivial
1124-
let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1125-
if ty::type_is_c_like_enum(fcx.tcx(), t_e) && t_1_is_trivial {
1126-
if t_1_is_float {
1127-
fcx.type_error_message(span, |actual| {
1128-
format!("illegal cast; cast through an \
1129-
integer first: `{}` as `{}`",
1130-
actual,
1131-
fcx.infcx().ty_to_str(t_1))
1132-
}, t_e, None);
1133-
}
1134-
// casts from C-like enums are allowed
1135-
} else if t_1_is_char {
1136-
let t_e = fcx.infcx().resolve_type_vars_if_possible(t_e);
1137-
if ty::get(t_e).sty != ty::ty_uint(ast::TyU8) {
1138-
fcx.type_error_message(span, |actual| {
1139-
format!("only `u8` can be cast as \
1140-
`char`, not `{}`", actual)
1141-
}, t_e, None);
1142-
}
1143-
} else if ty::get(t_1).sty == ty::ty_bool {
1144-
fcx.tcx()
1145-
.sess
1146-
.span_err(span,
1147-
"cannot cast as `bool`, compare with zero instead");
1148-
} else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
1149-
fn is_vec(t: ty::t) -> bool {
1150-
match ty::get(t).sty {
1151-
ty::ty_vec(..) => true,
1152-
ty::ty_ptr(ty::mt{ty: t, ..}) |
1153-
ty::ty_rptr(_, ty::mt{ty: t, ..}) |
1154-
ty::ty_box(t) |
1155-
ty::ty_uniq(t) => {
1156-
match ty::get(t).sty {
1157-
ty::ty_vec(_, None) => true,
1158-
_ => false,
1159-
}
1160-
}
1161-
_ => false
1162-
}
1163-
}
1164-
fn types_compatible(fcx: &FnCtxt, sp: Span,
1165-
t1: ty::t, t2: ty::t) -> bool {
1166-
if !is_vec(t1) {
1167-
// If the type being casted from is not a vector, this special
1168-
// case does not apply.
1169-
return false
1170-
}
1171-
if ty::type_needs_infer(t2) {
1172-
// This prevents this special case from going off when casting
1173-
// to a type that isn't fully specified; e.g. `as *_`. (Issue
1174-
// #14893.)
1175-
return false
1176-
}
1177-
1178-
let el = ty::sequence_element_type(fcx.tcx(), t1);
1179-
infer::mk_eqty(fcx.infcx(),
1180-
false,
1181-
infer::Misc(sp),
1182-
el,
1183-
t2).is_ok()
1184-
}
1185-
1186-
// Due to the limitations of LLVM global constants,
1187-
// region pointers end up pointing at copies of
1188-
// vector elements instead of the original values.
1189-
// To allow unsafe pointers to work correctly, we
1190-
// need to special-case obtaining an unsafe pointer
1191-
// from a region pointer to a vector.
1192-
1193-
/* this cast is only allowed from &[T] to *T or
1194-
&T to *T. */
1195-
match (&ty::get(t_e).sty, &ty::get(t_1).sty) {
1196-
(&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
1197-
&ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
1198-
if types_compatible(fcx, e.span, mt1, mt2) => {
1199-
/* this case is allowed */
1200-
}
1201-
_ => {
1202-
demand::coerce(fcx, e.span, t_1, &*e);
1203-
}
1204-
}
1205-
} else if !(ty::type_is_scalar(t_e) && t_1_is_trivial) {
1206-
/*
1207-
If more type combinations should be supported than are
1208-
supported here, then file an enhancement issue and
1209-
record the issue number in this comment.
1210-
*/
1211-
fcx.type_error_message(span, |actual| {
1212-
format!("non-scalar cast: `{}` as `{}`",
1213-
actual,
1214-
fcx.infcx().ty_to_str(t_1))
1215-
}, t_e, None);
1216-
}
1217-
1218-
fcx.write_ty(id, t_1);
1219-
}
1220-
12211063
impl<'a> AstConv for FnCtxt<'a> {
12221064
fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.ccx.tcx }
12231065

@@ -3207,8 +3049,11 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
32073049
fcx.write_bot(id);
32083050
}
32093051
}
3210-
ast::ExprCast(ref e, ref t) => {
3211-
check_cast(fcx, &**e, &**t, id, expr.span);
3052+
ast::ExprCast(expr_from, t) => {
3053+
let ty_to = fcx.to_ty(t);
3054+
debug!("ExprCast ty_to={}", fcx.infcx().ty_to_str(ty_to));
3055+
check_cast(fcx, expr_from, ty_to);
3056+
fcx.write_ty(id, ty_to);
32123057
}
32133058
ast::ExprVec(ref args) => {
32143059
let t: ty::t = fcx.infcx().next_ty_var();
@@ -3403,6 +3248,130 @@ impl Repr for Expectation {
34033248
}
34043249
}
34053250

3251+
fn check_cast(fcx: &FnCtxt, expr_from: Gc<ast::Expr>, ty_to: ty::t) {
3252+
// Find the type of `expr_from`. Supply hints based on the type
3253+
// we are casting to, if appropriate.
3254+
let ty_to = structurally_resolved_type(fcx, expr_from.span, ty_to);
3255+
if ty::type_is_scalar(ty_to) {
3256+
// Supply the type as a hint so as to influence integer
3257+
// literals and other things that might care.
3258+
check_expr_with_hint(fcx, expr_from, ty_to)
3259+
} else {
3260+
check_expr(fcx, expr_from)
3261+
}
3262+
let ty_from = fcx.expr_ty(expr_from);
3263+
3264+
// Object creation is checked during the vtable phase.
3265+
if ty::type_is_trait(ty_to) {
3266+
check_expr(fcx, expr_from);
3267+
return;
3268+
}
3269+
3270+
let ty_from = fcx.infcx().resolve_type_vars_if_possible(ty_from);
3271+
3272+
if ty::type_is_nil(ty_from) {
3273+
fcx.type_error_message(expr_from.span, |actual| {
3274+
format!("cast from nil: `{}` as `{}`", actual,
3275+
fcx.infcx().ty_to_str(ty_to))
3276+
}, ty_from, None);
3277+
return;
3278+
}
3279+
3280+
if ty::type_is_nil(ty_to) {
3281+
fcx.type_error_message(expr_from.span, |actual| {
3282+
format!("cast to nil: `{}` as `{}`", actual,
3283+
fcx.infcx().ty_to_str(ty_to))
3284+
}, ty_from, None);
3285+
return;
3286+
}
3287+
3288+
let t_e = structurally_resolved_type(fcx, expr_from.span, ty_from);
3289+
let t_1 = structurally_resolved_type(fcx, expr_from.span, ty_to);
3290+
3291+
let to_is_scalar = ty::type_is_scalar(t_1);
3292+
let to_is_float = ty::type_is_floating_point(t_1);
3293+
let to_is_char = ty::type_is_char(t_1);
3294+
let to_is_bare_fn = ty::type_is_bare_fn(t_1);
3295+
3296+
// casts to scalars other than `char` and `bare fn` are trivial
3297+
let to_is_trivial = to_is_scalar &&
3298+
!to_is_char && !to_is_bare_fn;
3299+
3300+
if ty::type_is_c_like_enum(fcx.tcx(), t_e) && to_is_trivial {
3301+
if to_is_float {
3302+
fcx.type_error_message(expr_from.span, |actual| {
3303+
format!("illegal cast; cast through an integer first: `{}` \
3304+
as `{}`",
3305+
actual,
3306+
fcx.infcx().ty_to_str(t_1))
3307+
}, ty_from, None);
3308+
}
3309+
// casts from C-like enums are allowed
3310+
} else if to_is_char {
3311+
if ty::get(ty_from).sty != ty::ty_uint(ast::TyU8) {
3312+
fcx.type_error_message(expr_from.span, |actual| {
3313+
format!("only `u8` can be cast as `char`, not `{}`", actual)
3314+
}, ty_from, None);
3315+
}
3316+
} else if ty::type_is_bool(t_1) {
3317+
fcx.tcx().sess.span_err(expr_from.span,
3318+
"cannot cast as `bool`, compare with zero instead");
3319+
} else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
3320+
fn is_vec(t: ty::t) -> bool {
3321+
match ty::get(t).sty {
3322+
ty::ty_vec(..) => true,
3323+
ty::ty_ptr(ty::mt{ty: t, ..}) |
3324+
ty::ty_rptr(_, ty::mt{ty: t, ..}) |
3325+
ty::ty_box(t) |
3326+
ty::ty_uniq(t) => match ty::get(t).sty {
3327+
ty::ty_vec(_, None) => true,
3328+
_ => false,
3329+
},
3330+
_ => false
3331+
}
3332+
}
3333+
fn types_compatible(fcx: &FnCtxt, sp: Span,
3334+
t1: ty::t, t2: ty::t) -> bool {
3335+
if !is_vec(t1) {
3336+
false
3337+
} else {
3338+
let el = ty::sequence_element_type(fcx.tcx(),
3339+
t1);
3340+
infer::mk_eqty(fcx.infcx(), false,
3341+
infer::Misc(sp), el, t2).is_ok()
3342+
}
3343+
}
3344+
3345+
// Due to the limitations of LLVM global constants,
3346+
// region pointers end up pointing at copies of
3347+
// vector elements instead of the original values.
3348+
// To allow unsafe pointers to work correctly, we
3349+
// need to special-case obtaining an unsafe pointer
3350+
// from a region pointer to a vector.
3351+
3352+
/* this cast is only allowed from &[T] to *T or
3353+
&T to *T. */
3354+
match (&ty::get(t_e).sty, &ty::get(t_1).sty) {
3355+
(&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
3356+
&ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
3357+
if types_compatible(fcx, expr_from.span, mt1, mt2) => {
3358+
/* this case is allowed */
3359+
}
3360+
_ => {
3361+
demand::coerce(fcx, expr_from.span, ty_to, expr_from);
3362+
}
3363+
}
3364+
} else if !(ty::type_is_scalar(t_e) && to_is_trivial) {
3365+
// If more type combinations should be supported than are
3366+
// supported here, then file an enhancement issue and
3367+
// record the issue number in this comment.
3368+
fcx.type_error_message(expr_from.span, |actual| {
3369+
format!("non-scalar cast: `{}` as `{}`", actual,
3370+
fcx.infcx().ty_to_str(ty_to))
3371+
}, ty_from, None);
3372+
}
3373+
}
3374+
34063375
pub fn require_uint(fcx: &FnCtxt, sp: Span, t: ty::t) {
34073376
if !type_is_uint(fcx, sp, t) {
34083377
fcx.type_error_message(sp, |actual| {

branches/try2/src/libstd/fmt.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ format!("{a:s} {c:d} {b:?}", a="a", b=(), c=3i); // => "a 3 ()"
101101
```
102102
103103
It is illegal to put positional parameters (those without names) after arguments
104-
which have names. Like positional parameters, it is illegal to provided named
105-
parameters that are unused by the format string.
104+
which have names. Like with positional parameters, it is illegal to provide
105+
named parameters that are unused by the format string.
106106
107107
### Argument types
108108

branches/try2/src/test/compile-fail/vector-cast-weirdness.rs

Lines changed: 0 additions & 31 deletions
This file was deleted.

0 commit comments

Comments
 (0)