@@ -990,86 +990,65 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
990990 }
991991}
992992
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" ) ;
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) ;
10421016 }
10431017 }
1044- fcx. write_error ( id) ;
1045- return
1046- }
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
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+ }
10531025 }
1026+ fcx. write_error ( id) ;
1027+ }
10541028
1055- let t_1 = structurally_resolved_type ( fcx, span, t_1) ;
1056- let t_e = structurally_resolved_type ( fcx, span, t_e) ;
10571029
1058- if ty:: type_is_nil ( t_e) {
1059- fcx. type_error_message ( span, |actual| {
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) {
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 > ) {
10651039 fcx. type_error_message ( span, |actual| {
1066- format ! ( "cast to nil: `{}` as `{}`" ,
1040+ format ! ( "illegal cast; cast through an \
1041+ integer first: `{}` as `{}`",
10671042 actual,
10681043 fcx. infcx( ) . ty_to_string( t_1) )
10691044 } , t_e, None ) ;
10701045 }
10711046
10721047 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) ;
10731052
10741053 let t_1_is_scalar = ty:: type_is_scalar ( t_1) ;
10751054 let t_1_is_char = ty:: type_is_char ( t_1) ;
@@ -1078,18 +1057,9 @@ fn check_cast(fcx: &FnCtxt,
10781057
10791058 // casts to scalars other than `char` and `bare fn` are trivial
10801059 let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
1060+
10811061 if t_e_is_bare_fn_item && t_1_is_bare_fn {
10821062 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
10931063 } else if t_1_is_char {
10941064 let t_e = fcx. infcx ( ) . shallow_resolve ( t_e) ;
10951065 if t_e. sty != ty:: ty_uint ( ast:: TyU8 ) {
@@ -1101,6 +1071,16 @@ fn check_cast(fcx: &FnCtxt,
11011071 } else if t_1. sty == ty:: ty_bool {
11021072 span_err ! ( fcx. tcx( ) . sess, span, E0054 ,
11031073 "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
11041084 } else if ty:: type_is_region_ptr ( t_e) && ty:: type_is_unsafe_ptr ( t_1) {
11051085 fn types_compatible < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > , sp : Span ,
11061086 t1 : Ty < ' tcx > , t2 : Ty < ' tcx > ) -> bool {
@@ -1142,7 +1122,7 @@ fn check_cast(fcx: &FnCtxt,
11421122 demand:: coerce ( fcx, e. span , t_1, & * e) ;
11431123 }
11441124 }
1145- } else if !( ty :: type_is_scalar ( t_e ) && t_1_is_trivial) {
1125+ } else if !( t_e_is_scalar && t_1_is_trivial) {
11461126 /*
11471127 If more type combinations should be supported than are
11481128 supported here, then file an enhancement issue and
@@ -1153,15 +1133,49 @@ fn check_cast(fcx: &FnCtxt,
11531133 actual,
11541134 fcx. infcx( ) . ty_to_string( t_1) )
11551135 } , 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 ) ;
11631136 }
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) ;
11641177
1178+ check_cast_inner ( fcx, span, t_1, t_e, e) ;
11651179 fcx. write_ty ( id, t_1) ;
11661180}
11671181
0 commit comments