@@ -14,7 +14,7 @@ use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable};
1414use rustc_mir_dataflow:: impls:: MaybeStorageLive ;
1515use rustc_mir_dataflow:: storage:: AlwaysLiveLocals ;
1616use rustc_mir_dataflow:: { Analysis , ResultsCursor } ;
17- use rustc_target:: abi:: Size ;
17+ use rustc_target:: abi:: { Size , VariantIdx } ;
1818
1919#[ derive( Copy , Clone , Debug ) ]
2020enum EdgeKind {
@@ -244,6 +244,60 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
244244 self . fail ( location, format ! ( "bad index ({:?} != usize)" , index_ty) )
245245 }
246246 }
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+ }
247301 self . super_projection_elem ( local, proj_base, elem, context, location) ;
248302 }
249303
0 commit comments