@@ -14,7 +14,7 @@ use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable};
14
14
use rustc_mir_dataflow:: impls:: MaybeStorageLive ;
15
15
use rustc_mir_dataflow:: storage:: AlwaysLiveLocals ;
16
16
use rustc_mir_dataflow:: { Analysis , ResultsCursor } ;
17
- use rustc_target:: abi:: Size ;
17
+ use rustc_target:: abi:: { Size , VariantIdx } ;
18
18
19
19
#[ derive( Copy , Clone , Debug ) ]
20
20
enum EdgeKind {
@@ -244,6 +244,60 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
244
244
self . fail ( location, format ! ( "bad index ({:?} != usize)" , index_ty) )
245
245
}
246
246
}
247
+ if let ProjectionElem :: Field ( f, ty) = elem {
248
+ let parent = Place { local, projection : self . tcx . intern_place_elems ( proj_base) } ;
249
+ let parent_ty = parent. ty ( & self . body . local_decls , self . tcx ) ;
250
+ let fail_out_of_bounds = |this : & Self , location| {
251
+ this. fail ( location, format ! ( "Out of bounds field {:?} for {:?}" , f, parent_ty) ) ;
252
+ } ;
253
+ let check_equal = |this : & Self , location, f_ty| {
254
+ if !this. mir_assign_valid_types ( ty, f_ty) {
255
+ this. fail (
256
+ location,
257
+ format ! (
258
+ "Field projection `{:?}.{:?}` specified type `{:?}`, but actual type is {:?}" ,
259
+ parent, f, ty, f_ty
260
+ )
261
+ )
262
+ }
263
+ } ;
264
+ match parent_ty. ty . kind ( ) {
265
+ ty:: Tuple ( fields) => {
266
+ let Some ( f_ty) = fields. get ( f. as_usize ( ) ) else {
267
+ fail_out_of_bounds ( self , location) ;
268
+ return ;
269
+ } ;
270
+ check_equal ( self , location, * f_ty) ;
271
+ }
272
+ ty:: Adt ( adt_def, substs) => {
273
+ let var = parent_ty. variant_index . unwrap_or ( VariantIdx :: from_u32 ( 0 ) ) ;
274
+ let Some ( field) = adt_def. variant ( var) . fields . get ( f. as_usize ( ) ) else {
275
+ fail_out_of_bounds ( self , location) ;
276
+ return ;
277
+ } ;
278
+ check_equal ( self , location, field. ty ( self . tcx , substs) ) ;
279
+ }
280
+ ty:: Closure ( _, substs) => {
281
+ let substs = substs. as_closure ( ) ;
282
+ let Some ( f_ty) = substs. upvar_tys ( ) . nth ( f. as_usize ( ) ) else {
283
+ fail_out_of_bounds ( self , location) ;
284
+ return ;
285
+ } ;
286
+ check_equal ( self , location, f_ty) ;
287
+ }
288
+ ty:: Generator ( _, substs, _) => {
289
+ let substs = substs. as_generator ( ) ;
290
+ let Some ( f_ty) = substs. upvar_tys ( ) . nth ( f. as_usize ( ) ) else {
291
+ fail_out_of_bounds ( self , location) ;
292
+ return ;
293
+ } ;
294
+ check_equal ( self , location, f_ty) ;
295
+ }
296
+ _ => {
297
+ self . fail ( location, format ! ( "{:?} does not have fields" , parent_ty. ty) ) ;
298
+ }
299
+ }
300
+ }
247
301
self . super_projection_elem ( local, proj_base, elem, context, location) ;
248
302
}
249
303
0 commit comments