@@ -139,6 +139,7 @@ pub mod demand;
139
139
pub mod method;
140
140
mod upvar;
141
141
pub mod wf;
142
+ mod cast;
142
143
mod closure;
143
144
mod callee;
144
145
mod compare_method;
@@ -185,7 +186,7 @@ pub struct Inherited<'a, 'tcx: 'a> {
185
186
// back and process them.
186
187
deferred_call_resolutions : RefCell < DefIdMap < Vec < DeferredCallResolutionHandler < ' tcx > > > > ,
187
188
188
- deferred_cast_checks : RefCell < Vec < CastCheck < ' tcx > > > ,
189
+ deferred_cast_checks : RefCell < Vec < cast :: CastCheck < ' tcx > > > ,
189
190
}
190
191
191
192
trait DeferredCallResolution < ' tcx > {
@@ -194,15 +195,6 @@ trait DeferredCallResolution<'tcx> {
194
195
195
196
type DeferredCallResolutionHandler < ' tcx > = Box < DeferredCallResolution < ' tcx > +' tcx > ;
196
197
197
- /// Reifies a cast check to be checked once we have full type information for
198
- /// a function context.
199
- struct CastCheck < ' tcx > {
200
- expr : ast:: Expr ,
201
- expr_ty : Ty < ' tcx > ,
202
- cast_ty : Ty < ' tcx > ,
203
- span : Span ,
204
- }
205
-
206
198
/// When type-checking an expression, we propagate downward
207
199
/// whatever type hint we are able in the form of an `Expectation`.
208
200
#[ derive( Copy , Clone ) ]
@@ -1071,141 +1063,6 @@ fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
1071
1063
}
1072
1064
1073
1065
1074
- fn check_cast < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > , cast : & CastCheck < ' tcx > ) {
1075
- fn cast_through_integer_err < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
1076
- span : Span ,
1077
- t_1 : Ty < ' tcx > ,
1078
- t_e : Ty < ' tcx > ) {
1079
- fcx. type_error_message ( span, |actual| {
1080
- format ! ( "illegal cast; cast through an \
1081
- integer first: `{}` as `{}`",
1082
- actual,
1083
- fcx. infcx( ) . ty_to_string( t_1) )
1084
- } , t_e, None ) ;
1085
- }
1086
-
1087
- let span = cast. span ;
1088
- let e = & cast. expr ;
1089
- let t_e = structurally_resolved_type ( fcx, span, cast. expr_ty ) ;
1090
- let t_1 = structurally_resolved_type ( fcx, span, cast. cast_ty ) ;
1091
-
1092
- // Check for trivial casts.
1093
- if !ty:: type_has_ty_infer ( t_1) {
1094
- if let Ok ( ( ) ) = coercion:: mk_assignty ( fcx, e, t_e, t_1) {
1095
- if ty:: type_is_numeric ( t_1) && ty:: type_is_numeric ( t_e) {
1096
- fcx. tcx ( ) . sess . add_lint ( lint:: builtin:: TRIVIAL_NUMERIC_CASTS ,
1097
- e. id ,
1098
- span,
1099
- format ! ( "trivial numeric cast: `{}` as `{}`. Cast can be \
1100
- replaced by coercion, this might require type \
1101
- ascription or a temporary variable",
1102
- fcx. infcx( ) . ty_to_string( t_e) ,
1103
- fcx. infcx( ) . ty_to_string( t_1) ) ) ;
1104
- } else {
1105
- fcx. tcx ( ) . sess . add_lint ( lint:: builtin:: TRIVIAL_CASTS ,
1106
- e. id ,
1107
- span,
1108
- format ! ( "trivial cast: `{}` as `{}`. Cast can be \
1109
- replaced by coercion, this might require type \
1110
- ascription or a temporary variable",
1111
- fcx. infcx( ) . ty_to_string( t_e) ,
1112
- fcx. infcx( ) . ty_to_string( t_1) ) ) ;
1113
- }
1114
- return ;
1115
- }
1116
- }
1117
-
1118
- let t_e_is_bare_fn_item = ty:: type_is_bare_fn_item ( t_e) ;
1119
- let t_e_is_scalar = ty:: type_is_scalar ( t_e) ;
1120
- let t_e_is_integral = ty:: type_is_integral ( t_e) ;
1121
- let t_e_is_float = ty:: type_is_floating_point ( t_e) ;
1122
- let t_e_is_c_enum = ty:: type_is_c_like_enum ( fcx. tcx ( ) , t_e) ;
1123
-
1124
- let t_1_is_scalar = ty:: type_is_scalar ( t_1) ;
1125
- let t_1_is_char = ty:: type_is_char ( t_1) ;
1126
- let t_1_is_bare_fn = ty:: type_is_bare_fn ( t_1) ;
1127
- let t_1_is_float = ty:: type_is_floating_point ( t_1) ;
1128
-
1129
- // casts to scalars other than `char` and `bare fn` are trivial
1130
- let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1131
-
1132
- if t_e_is_bare_fn_item && t_1_is_bare_fn {
1133
- demand:: coerce ( fcx, e. span , t_1, & e) ;
1134
- } else if t_1_is_char {
1135
- let t_e = fcx. infcx ( ) . shallow_resolve ( t_e) ;
1136
- if t_e. sty != ty:: ty_uint ( ast:: TyU8 ) {
1137
- fcx. type_error_message ( span, |actual| {
1138
- format ! ( "only `u8` can be cast as `char`, not `{}`" , actual)
1139
- } , t_e, None ) ;
1140
- }
1141
- } else if t_1. sty == ty:: ty_bool {
1142
- span_err ! ( fcx. tcx( ) . sess, span, E0054 ,
1143
- "cannot cast as `bool`, compare with zero instead" ) ;
1144
- } else if t_1_is_float && ( t_e_is_scalar || t_e_is_c_enum) && !(
1145
- t_e_is_integral || t_e_is_float || t_e. sty == ty:: ty_bool) {
1146
- // Casts to float must go through an integer or boolean
1147
- cast_through_integer_err ( fcx, span, t_1, t_e)
1148
- } else if t_e_is_c_enum && t_1_is_trivial {
1149
- if ty:: type_is_unsafe_ptr ( t_1) {
1150
- // ... and likewise with C enum -> *T
1151
- cast_through_integer_err ( fcx, span, t_1, t_e)
1152
- }
1153
- // casts from C-like enums are allowed
1154
- } else if ty:: type_is_region_ptr ( t_e) && ty:: type_is_unsafe_ptr ( t_1) {
1155
- fn types_compatible < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > , sp : Span ,
1156
- t1 : Ty < ' tcx > , t2 : Ty < ' tcx > ) -> bool {
1157
- match t1. sty {
1158
- ty:: ty_vec( _, Some ( _) ) => { }
1159
- _ => return false
1160
- }
1161
- if ty:: type_needs_infer ( t2) {
1162
- // This prevents this special case from going off when casting
1163
- // to a type that isn't fully specified; e.g. `as *_`. (Issue
1164
- // #14893.)
1165
- return false
1166
- }
1167
-
1168
- let el = ty:: sequence_element_type ( fcx. tcx ( ) , t1) ;
1169
- infer:: mk_eqty ( fcx. infcx ( ) ,
1170
- false ,
1171
- infer:: Misc ( sp) ,
1172
- el,
1173
- t2) . is_ok ( )
1174
- }
1175
-
1176
- // Due to the limitations of LLVM global constants,
1177
- // region pointers end up pointing at copies of
1178
- // vector elements instead of the original values.
1179
- // To allow unsafe pointers to work correctly, we
1180
- // need to special-case obtaining an unsafe pointer
1181
- // from a region pointer to a vector.
1182
-
1183
- /* this cast is only allowed from &[T, ..n] to *T or
1184
- &T to *T. */
1185
- match ( & t_e. sty , & t_1. sty ) {
1186
- ( & ty:: ty_rptr( _, ty:: mt { ty : mt1, mutbl : ast:: MutImmutable } ) ,
1187
- & ty:: ty_ptr( ty:: mt { ty : mt2, mutbl : ast:: MutImmutable } ) )
1188
- if types_compatible ( fcx, e. span , mt1, mt2) => {
1189
- /* this case is allowed */
1190
- }
1191
- _ => {
1192
- demand:: coerce ( fcx, e. span , t_1, & e) ;
1193
- }
1194
- }
1195
- } else if !( t_e_is_scalar && t_1_is_trivial) {
1196
- /*
1197
- If more type combinations should be supported than are
1198
- supported here, then file an enhancement issue and
1199
- record the issue number in this comment.
1200
- */
1201
- fcx. type_error_message ( span, |actual| {
1202
- format ! ( "non-scalar cast: `{}` as `{}`" ,
1203
- actual,
1204
- fcx. infcx( ) . ty_to_string( t_1) )
1205
- } , t_e, None ) ;
1206
- }
1207
- }
1208
-
1209
1066
impl < ' a , ' tcx > AstConv < ' tcx > for FnCtxt < ' a , ' tcx > {
1210
1067
fn tcx ( & self ) -> & ty:: ctxt < ' tcx > { self . ccx . tcx }
1211
1068
@@ -1925,7 +1782,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1925
1782
fn check_casts ( & self ) {
1926
1783
let mut deferred_cast_checks = self . inh . deferred_cast_checks . borrow_mut ( ) ;
1927
1784
for check in deferred_cast_checks. iter ( ) {
1928
- check_cast ( self , check) ;
1785
+ cast :: check_cast ( self , check) ;
1929
1786
}
1930
1787
1931
1788
deferred_cast_checks. clear ( ) ;
@@ -3531,12 +3388,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
3531
3388
3532
3389
// Defer other checks until we're done type checking.
3533
3390
let mut deferred_cast_checks = fcx. inh . deferred_cast_checks . borrow_mut ( ) ;
3534
- deferred_cast_checks. push ( CastCheck {
3535
- expr : ( * * e) . clone ( ) ,
3536
- expr_ty : t_e,
3537
- cast_ty : t_1,
3538
- span : expr. span ,
3539
- } ) ;
3391
+ let cast_check = cast:: CastCheck :: new ( ( * * e) . clone ( ) , t_e, t_1, expr. span ) ;
3392
+ deferred_cast_checks. push ( cast_check) ;
3540
3393
}
3541
3394
}
3542
3395
ast:: ExprVec ( ref args) => {
0 commit comments