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