@@ -1060,164 +1060,6 @@ fn compare_impl_method(tcx: &ty::ctxt,
1060
1060
}
1061
1061
}
1062
1062
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
-
1221
1063
impl < ' a > AstConv for FnCtxt < ' a > {
1222
1064
fn tcx < ' a > ( & ' a self ) -> & ' a ty:: ctxt { self . ccx . tcx }
1223
1065
@@ -3207,8 +3049,11 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
3207
3049
fcx. write_bot ( id) ;
3208
3050
}
3209
3051
}
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) ;
3212
3057
}
3213
3058
ast:: ExprVec ( ref args) => {
3214
3059
let t: ty:: t = fcx. infcx ( ) . next_ty_var ( ) ;
@@ -3403,6 +3248,130 @@ impl Repr for Expectation {
3403
3248
}
3404
3249
}
3405
3250
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
+
3406
3375
pub fn require_uint ( fcx : & FnCtxt , sp : Span , t : ty:: t ) {
3407
3376
if !type_is_uint ( fcx, sp, t) {
3408
3377
fcx. type_error_message ( sp, |actual| {
0 commit comments