@@ -549,6 +549,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
549
549
terr
550
550
) ;
551
551
}
552
+ self . check_rvalue ( mir, rv, location) ;
552
553
}
553
554
StatementKind :: SetDiscriminant {
554
555
ref lvalue,
@@ -1011,6 +1012,91 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
1011
1012
}
1012
1013
}
1013
1014
1015
+ fn aggregate_field_ty ( & mut self , ak : & Box < AggregateKind < ' tcx > > , field : usize , location : Location )
1016
+ -> Result < Ty < ' tcx > , FieldAccessError >
1017
+ {
1018
+ let tcx = self . tcx ( ) ;
1019
+
1020
+ let ( variant, substs) = match * * ak {
1021
+ AggregateKind :: Adt ( def, variant, substs, _) => { // handle unions?
1022
+ ( & def. variants [ variant] , substs)
1023
+ } ,
1024
+ AggregateKind :: Closure ( def_id, substs) => {
1025
+ return match substs. upvar_tys ( def_id, tcx) . nth ( field) {
1026
+ Some ( ty) => Ok ( ty) ,
1027
+ None => Err ( FieldAccessError :: OutOfRange {
1028
+ field_count : substs. upvar_tys ( def_id, tcx) . count ( )
1029
+ } ) ,
1030
+ }
1031
+ } ,
1032
+ AggregateKind :: Generator ( def_id, substs, _) => {
1033
+ if let Some ( ty) = substs. upvar_tys ( def_id, tcx) . nth ( field) {
1034
+ return Ok ( ty) ;
1035
+ }
1036
+
1037
+ return match substs. field_tys ( def_id, tcx) . nth ( field) {
1038
+ Some ( ty) => Ok ( ty) ,
1039
+ None => Err ( FieldAccessError :: OutOfRange {
1040
+ field_count : substs. field_tys ( def_id, tcx) . count ( ) + 1
1041
+ } ) ,
1042
+ }
1043
+ } ,
1044
+ AggregateKind :: Array ( ty) => {
1045
+ return Ok ( ty) ;
1046
+ } ,
1047
+ AggregateKind :: Tuple => {
1048
+ unreachable ! ( "This should have been covered in check_rvalues" ) ;
1049
+ } ,
1050
+ } ;
1051
+
1052
+ if let Some ( field) = variant. fields . get ( field) {
1053
+ Ok ( self . normalize ( & field. ty ( tcx, substs) , location) )
1054
+ } else {
1055
+ Err ( FieldAccessError :: OutOfRange { field_count : variant. fields . len ( ) } )
1056
+ }
1057
+ }
1058
+
1059
+ #[ allow( dead_code) ]
1060
+ fn check_rvalue ( & mut self , mir : & Mir < ' tcx > , rv : & Rvalue < ' tcx > , location : Location ) {
1061
+ let tcx = self . tcx ( ) ;
1062
+ match rv {
1063
+ Rvalue :: Aggregate ( ref ak, ref ops) => {
1064
+ match * * ak {
1065
+ // tuple rvalue field type is always the type of the op. Nothing to check here.
1066
+ AggregateKind :: Tuple => { } ,
1067
+ _ => {
1068
+ for ( i, op) in ops. iter ( ) . enumerate ( ) {
1069
+ let field_ty = if let Ok ( field_ty) = self . aggregate_field_ty ( ak, i, location) {
1070
+ field_ty
1071
+ } else {
1072
+ // TODO(nashenas88) log span_mirbug terr??
1073
+ continue ;
1074
+ } ;
1075
+ let op_ty = match op {
1076
+ Operand :: Consume ( lv) => lv. ty ( mir, tcx) . to_ty ( tcx) ,
1077
+ Operand :: Constant ( c) => c. ty ,
1078
+ } ;
1079
+ if let Err ( _terr) = self . sub_types ( op_ty, field_ty, location. at_successor_within_block ( ) ) {
1080
+ // TODO(nashenas88) log span_mirbug terr??
1081
+ }
1082
+ }
1083
+ } ,
1084
+ }
1085
+ } ,
1086
+ // FIXME: These other cases have to be implemented in future PRs
1087
+ Rvalue :: Use ( ..) |
1088
+ Rvalue :: Repeat ( ..) |
1089
+ Rvalue :: Ref ( ..) |
1090
+ Rvalue :: Len ( ..) |
1091
+ Rvalue :: Cast ( ..) |
1092
+ Rvalue :: BinaryOp ( ..) |
1093
+ Rvalue :: CheckedBinaryOp ( ..) |
1094
+ Rvalue :: UnaryOp ( ..) |
1095
+ Rvalue :: Discriminant ( ..) |
1096
+ Rvalue :: NullaryOp ( ..) => { }
1097
+ }
1098
+ }
1099
+
1014
1100
fn typeck_mir ( & mut self , mir : & Mir < ' tcx > ) {
1015
1101
self . last_span = mir. span ;
1016
1102
debug ! ( "run_on_mir: {:?}" , mir. span) ;
0 commit comments