@@ -990,65 +990,86 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
990
990
}
991
991
}
992
992
993
- fn report_cast_to_unsized_type < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
994
- span : Span ,
995
- t_span : Span ,
996
- e_span : Span ,
997
- t_1 : Ty < ' tcx > ,
998
- t_e : Ty < ' tcx > ,
999
- id : ast:: NodeId ) {
1000
- let tstr = fcx. infcx ( ) . ty_to_string ( t_1) ;
1001
- fcx. type_error_message ( span, |actual| {
1002
- format ! ( "cast to unsized type: `{}` as `{}`" , actual, tstr)
1003
- } , t_e, None ) ;
1004
- match t_e. sty {
1005
- ty:: ty_rptr( _, ty:: mt { mutbl : mt, .. } ) => {
1006
- let mtstr = match mt {
1007
- ast:: MutMutable => "mut " ,
1008
- ast:: MutImmutable => ""
1009
- } ;
1010
- if ty:: type_is_trait ( t_1) {
1011
- span_help ! ( fcx. tcx( ) . sess, t_span, "did you mean `&{}{}`?" , mtstr, tstr) ;
1012
- } else {
1013
- span_help ! ( fcx. tcx( ) . sess, span,
1014
- "consider using an implicit coercion to `&{}{}` instead" ,
1015
- mtstr, tstr) ;
993
+ fn check_cast ( fcx : & FnCtxt ,
994
+ cast_expr : & ast:: Expr ,
995
+ e : & ast:: Expr ,
996
+ t : & ast:: Ty ) {
997
+ let id = cast_expr. id ;
998
+ let span = cast_expr. span ;
999
+
1000
+ // Find the type of `e`. Supply hints based on the type we are casting to,
1001
+ // if appropriate.
1002
+ let t_1 = fcx. to_ty ( t) ;
1003
+ let t_1 = structurally_resolved_type ( fcx, span, t_1) ;
1004
+
1005
+ check_expr_with_expectation ( fcx, e, ExpectCastableToType ( t_1) ) ;
1006
+
1007
+ let t_e = fcx. expr_ty ( e) ;
1008
+
1009
+ debug ! ( "t_1={}" , fcx. infcx( ) . ty_to_string( t_1) ) ;
1010
+ debug ! ( "t_e={}" , fcx. infcx( ) . ty_to_string( t_e) ) ;
1011
+
1012
+ if ty:: type_is_error ( t_e) {
1013
+ fcx. write_error ( id) ;
1014
+ return
1015
+ }
1016
+
1017
+ if !fcx. type_is_known_to_be_sized ( t_1, cast_expr. span ) {
1018
+ let tstr = fcx. infcx ( ) . ty_to_string ( t_1) ;
1019
+ fcx. type_error_message ( span, |actual| {
1020
+ format ! ( "cast to unsized type: `{}` as `{}`" , actual, tstr)
1021
+ } , t_e, None ) ;
1022
+ match t_e. sty {
1023
+ ty:: ty_rptr( _, ty:: mt { mutbl : mt, .. } ) => {
1024
+ let mtstr = match mt {
1025
+ ast:: MutMutable => "mut " ,
1026
+ ast:: MutImmutable => ""
1027
+ } ;
1028
+ if ty:: type_is_trait ( t_1) {
1029
+ span_help ! ( fcx. tcx( ) . sess, t. span, "did you mean `&{}{}`?" , mtstr, tstr) ;
1030
+ } else {
1031
+ span_help ! ( fcx. tcx( ) . sess, span,
1032
+ "consider using an implicit coercion to `&{}{}` instead" ,
1033
+ mtstr, tstr) ;
1034
+ }
1035
+ }
1036
+ ty:: ty_uniq( ..) => {
1037
+ span_help ! ( fcx. tcx( ) . sess, t. span, "did you mean `Box<{}>`?" , tstr) ;
1038
+ }
1039
+ _ => {
1040
+ span_help ! ( fcx. tcx( ) . sess, e. span,
1041
+ "consider using a box or reference as appropriate" ) ;
1016
1042
}
1017
1043
}
1018
- ty:: ty_uniq( ..) => {
1019
- span_help ! ( fcx. tcx( ) . sess, t_span, "did you mean `Box<{}>`?" , tstr) ;
1020
- }
1021
- _ => {
1022
- span_help ! ( fcx. tcx( ) . sess, e_span,
1023
- "consider using a box or reference as appropriate" ) ;
1024
- }
1044
+ fcx. write_error ( id) ;
1045
+ return
1025
1046
}
1026
- fcx. write_error ( id) ;
1027
- }
1028
1047
1048
+ if ty:: type_is_trait ( t_1) {
1049
+ // This will be looked up later on.
1050
+ vtable:: check_object_cast ( fcx, cast_expr, e, t_1) ;
1051
+ fcx. write_ty ( id, t_1) ;
1052
+ return
1053
+ }
1029
1054
1030
- fn check_cast_inner < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
1031
- span : Span ,
1032
- t_1 : Ty < ' tcx > ,
1033
- t_e : Ty < ' tcx > ,
1034
- e : & ast:: Expr ) {
1035
- fn cast_through_integer_err < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
1036
- span : Span ,
1037
- t_1 : Ty < ' tcx > ,
1038
- t_e : Ty < ' tcx > ) {
1055
+ let t_1 = structurally_resolved_type ( fcx, span, t_1) ;
1056
+ let t_e = structurally_resolved_type ( fcx, span, t_e) ;
1057
+
1058
+ if ty:: type_is_nil ( t_e) {
1039
1059
fcx. type_error_message ( span, |actual| {
1040
- format ! ( "illegal cast; cast through an \
1041
- integer first: `{}` as `{}`",
1060
+ format ! ( "cast from nil: `{}` as `{}`" ,
1061
+ actual,
1062
+ fcx. infcx( ) . ty_to_string( t_1) )
1063
+ } , t_e, None ) ;
1064
+ } else if ty:: type_is_nil ( t_1) {
1065
+ fcx. type_error_message ( span, |actual| {
1066
+ format ! ( "cast to nil: `{}` as `{}`" ,
1042
1067
actual,
1043
1068
fcx. infcx( ) . ty_to_string( t_1) )
1044
1069
} , t_e, None ) ;
1045
1070
}
1046
1071
1047
1072
let t_e_is_bare_fn_item = ty:: type_is_bare_fn_item ( t_e) ;
1048
- let t_e_is_scalar = ty:: type_is_scalar ( t_e) ;
1049
- let t_e_is_integral = ty:: type_is_integral ( t_e) ;
1050
- let t_e_is_float = ty:: type_is_floating_point ( t_e) ;
1051
- let t_e_is_c_enum = ty:: type_is_c_like_enum ( fcx. tcx ( ) , t_e) ;
1052
1073
1053
1074
let t_1_is_scalar = ty:: type_is_scalar ( t_1) ;
1054
1075
let t_1_is_char = ty:: type_is_char ( t_1) ;
@@ -1057,9 +1078,18 @@ fn check_cast_inner<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1057
1078
1058
1079
// casts to scalars other than `char` and `bare fn` are trivial
1059
1080
let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1060
-
1061
1081
if t_e_is_bare_fn_item && t_1_is_bare_fn {
1062
1082
demand:: coerce ( fcx, e. span , t_1, & * e) ;
1083
+ } else if ty:: type_is_c_like_enum ( fcx. tcx ( ) , t_e) && t_1_is_trivial {
1084
+ if t_1_is_float || ty:: type_is_unsafe_ptr ( t_1) {
1085
+ fcx. type_error_message ( span, |actual| {
1086
+ format ! ( "illegal cast; cast through an \
1087
+ integer first: `{}` as `{}`",
1088
+ actual,
1089
+ fcx. infcx( ) . ty_to_string( t_1) )
1090
+ } , t_e, None ) ;
1091
+ }
1092
+ // casts from C-like enums are allowed
1063
1093
} else if t_1_is_char {
1064
1094
let t_e = fcx. infcx ( ) . shallow_resolve ( t_e) ;
1065
1095
if t_e. sty != ty:: ty_uint ( ast:: TyU8 ) {
@@ -1071,16 +1101,6 @@ fn check_cast_inner<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1071
1101
} else if t_1. sty == ty:: ty_bool {
1072
1102
span_err ! ( fcx. tcx( ) . sess, span, E0054 ,
1073
1103
"cannot cast as `bool`, compare with zero instead" ) ;
1074
- } else if t_1_is_float && ( t_e_is_scalar || t_e_is_c_enum) && !(
1075
- t_e_is_integral || t_e_is_float || t_e. sty == ty:: ty_bool) {
1076
- // Casts to float must go through an integer or boolean
1077
- cast_through_integer_err ( fcx, span, t_1, t_e)
1078
- } else if t_e_is_c_enum && t_1_is_trivial {
1079
- if ty:: type_is_unsafe_ptr ( t_1) {
1080
- // ... and likewise with C enum -> *T
1081
- cast_through_integer_err ( fcx, span, t_1, t_e)
1082
- }
1083
- // casts from C-like enums are allowed
1084
1104
} else if ty:: type_is_region_ptr ( t_e) && ty:: type_is_unsafe_ptr ( t_1) {
1085
1105
fn types_compatible < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > , sp : Span ,
1086
1106
t1 : Ty < ' tcx > , t2 : Ty < ' tcx > ) -> bool {
@@ -1122,7 +1142,7 @@ fn check_cast_inner<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1122
1142
demand:: coerce ( fcx, e. span , t_1, & * e) ;
1123
1143
}
1124
1144
}
1125
- } else if !( t_e_is_scalar && t_1_is_trivial) {
1145
+ } else if !( ty :: type_is_scalar ( t_e ) && t_1_is_trivial) {
1126
1146
/*
1127
1147
If more type combinations should be supported than are
1128
1148
supported here, then file an enhancement issue and
@@ -1133,49 +1153,15 @@ fn check_cast_inner<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1133
1153
actual,
1134
1154
fcx. infcx( ) . ty_to_string( t_1) )
1135
1155
} , t_e, None ) ;
1156
+ } else if ty:: type_is_unsafe_ptr ( t_e) && t_1_is_float {
1157
+ fcx. type_error_message ( span, |actual| {
1158
+ format ! ( "cannot cast from pointer to float directly: `{}` as `{}`; cast through an \
1159
+ integer first",
1160
+ actual,
1161
+ fcx. infcx( ) . ty_to_string( t_1) )
1162
+ } , t_e, None ) ;
1136
1163
}
1137
- }
1138
-
1139
- fn check_cast ( fcx : & FnCtxt ,
1140
- cast_expr : & ast:: Expr ,
1141
- e : & ast:: Expr ,
1142
- t : & ast:: Ty ) {
1143
- let id = cast_expr. id ;
1144
- let span = cast_expr. span ;
1145
-
1146
- // Find the type of `e`. Supply hints based on the type we are casting to,
1147
- // if appropriate.
1148
- let t_1 = fcx. to_ty ( t) ;
1149
- let t_1 = structurally_resolved_type ( fcx, span, t_1) ;
1150
-
1151
- check_expr_with_expectation ( fcx, e, ExpectCastableToType ( t_1) ) ;
1152
-
1153
- let t_e = fcx. expr_ty ( e) ;
1154
-
1155
- debug ! ( "t_1={}" , fcx. infcx( ) . ty_to_string( t_1) ) ;
1156
- debug ! ( "t_e={}" , fcx. infcx( ) . ty_to_string( t_e) ) ;
1157
-
1158
- if ty:: type_is_error ( t_e) {
1159
- fcx. write_error ( id) ;
1160
- return
1161
- }
1162
-
1163
- if !fcx. type_is_known_to_be_sized ( t_1, cast_expr. span ) {
1164
- report_cast_to_unsized_type ( fcx, span, t. span , e. span , t_1, t_e, id) ;
1165
- return
1166
- }
1167
-
1168
- if ty:: type_is_trait ( t_1) {
1169
- // This will be looked up later on.
1170
- vtable:: check_object_cast ( fcx, cast_expr, e, t_1) ;
1171
- fcx. write_ty ( id, t_1) ;
1172
- return
1173
- }
1174
-
1175
- let t_1 = structurally_resolved_type ( fcx, span, t_1) ;
1176
- let t_e = structurally_resolved_type ( fcx, span, t_e) ;
1177
1164
1178
- check_cast_inner ( fcx, span, t_1, t_e, e) ;
1179
1165
fcx. write_ty ( id, t_1) ;
1180
1166
}
1181
1167
0 commit comments