@@ -240,65 +240,79 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
240240 context : PlaceContext ,
241241 location : Location ,
242242 ) {
243- if let ProjectionElem :: Index ( index) = elem {
244- let index_ty = self . body . local_decls [ index] . ty ;
245- if index_ty != self . tcx . types . usize {
246- self . fail ( location, format ! ( "bad index ({:?} != usize)" , index_ty) )
243+ match elem {
244+ ProjectionElem :: Index ( index) => {
245+ let index_ty = self . body . local_decls [ index] . ty ;
246+ if index_ty != self . tcx . types . usize {
247+ self . fail ( location, format ! ( "bad index ({:?} != usize)" , index_ty) )
248+ }
247249 }
248- }
249- if let ProjectionElem :: Field ( f, ty) = elem {
250- let parent = Place { local, projection : self . tcx . intern_place_elems ( proj_base) } ;
251- let parent_ty = parent. ty ( & self . body . local_decls , self . tcx ) ;
252- let fail_out_of_bounds = |this : & Self , location| {
253- this. fail ( location, format ! ( "Out of bounds field {:?} for {:?}" , f, parent_ty) ) ;
254- } ;
255- let check_equal = |this : & Self , location, f_ty| {
256- if !this. mir_assign_valid_types ( ty, f_ty) {
257- this. fail (
250+ ProjectionElem :: Deref if self . mir_phase >= MirPhase :: GeneratorsLowered => {
251+ let base_ty = Place :: ty_from ( local, proj_base, & self . body . local_decls , self . tcx ) . ty ;
252+
253+ if base_ty. is_box ( ) {
254+ self . fail (
255+ location,
256+ format ! ( "{:?} dereferenced after ElaborateBoxDerefs" , base_ty) ,
257+ )
258+ }
259+ }
260+ ProjectionElem :: Field ( f, ty) => {
261+ let parent = Place { local, projection : self . tcx . intern_place_elems ( proj_base) } ;
262+ let parent_ty = parent. ty ( & self . body . local_decls , self . tcx ) ;
263+ let fail_out_of_bounds = |this : & Self , location| {
264+ this. fail ( location, format ! ( "Out of bounds field {:?} for {:?}" , f, parent_ty) ) ;
265+ } ;
266+ let check_equal = |this : & Self , location, f_ty| {
267+ if !this. mir_assign_valid_types ( ty, f_ty) {
268+ this. fail (
258269 location,
259270 format ! (
260271 "Field projection `{:?}.{:?}` specified type `{:?}`, but actual type is {:?}" ,
261272 parent, f, ty, f_ty
262273 )
263274 )
264- }
265- } ;
266- match parent_ty. ty . kind ( ) {
267- ty:: Tuple ( fields) => {
268- let Some ( f_ty) = fields. get ( f. as_usize ( ) ) else {
269- fail_out_of_bounds ( self , location) ;
270- return ;
271- } ;
272- check_equal ( self , location, * f_ty) ;
273- }
274- ty:: Adt ( adt_def, substs) => {
275- let var = parent_ty. variant_index . unwrap_or ( VariantIdx :: from_u32 ( 0 ) ) ;
276- let Some ( field) = adt_def. variant ( var) . fields . get ( f. as_usize ( ) ) else {
277- fail_out_of_bounds ( self , location) ;
278- return ;
279- } ;
280- check_equal ( self , location, field. ty ( self . tcx , substs) ) ;
281- }
282- ty:: Closure ( _, substs) => {
283- let substs = substs. as_closure ( ) ;
284- let Some ( f_ty) = substs. upvar_tys ( ) . nth ( f. as_usize ( ) ) else {
285- fail_out_of_bounds ( self , location) ;
286- return ;
287- } ;
288- check_equal ( self , location, f_ty) ;
289- }
290- ty:: Generator ( _, substs, _) => {
291- let substs = substs. as_generator ( ) ;
292- let Some ( f_ty) = substs. upvar_tys ( ) . nth ( f. as_usize ( ) ) else {
293- fail_out_of_bounds ( self , location) ;
294- return ;
295- } ;
296- check_equal ( self , location, f_ty) ;
297- }
298- _ => {
299- self . fail ( location, format ! ( "{:?} does not have fields" , parent_ty. ty) ) ;
275+ }
276+ } ;
277+
278+ match parent_ty. ty . kind ( ) {
279+ ty:: Tuple ( fields) => {
280+ let Some ( f_ty) = fields. get ( f. as_usize ( ) ) else {
281+ fail_out_of_bounds ( self , location) ;
282+ return ;
283+ } ;
284+ check_equal ( self , location, * f_ty) ;
285+ }
286+ ty:: Adt ( adt_def, substs) => {
287+ let var = parent_ty. variant_index . unwrap_or ( VariantIdx :: from_u32 ( 0 ) ) ;
288+ let Some ( field) = adt_def. variant ( var) . fields . get ( f. as_usize ( ) ) else {
289+ fail_out_of_bounds ( self , location) ;
290+ return ;
291+ } ;
292+ check_equal ( self , location, field. ty ( self . tcx , substs) ) ;
293+ }
294+ ty:: Closure ( _, substs) => {
295+ let substs = substs. as_closure ( ) ;
296+ let Some ( f_ty) = substs. upvar_tys ( ) . nth ( f. as_usize ( ) ) else {
297+ fail_out_of_bounds ( self , location) ;
298+ return ;
299+ } ;
300+ check_equal ( self , location, f_ty) ;
301+ }
302+ ty:: Generator ( _, substs, _) => {
303+ let substs = substs. as_generator ( ) ;
304+ let Some ( f_ty) = substs. upvar_tys ( ) . nth ( f. as_usize ( ) ) else {
305+ fail_out_of_bounds ( self , location) ;
306+ return ;
307+ } ;
308+ check_equal ( self , location, f_ty) ;
309+ }
310+ _ => {
311+ self . fail ( location, format ! ( "{:?} does not have fields" , parent_ty. ty) ) ;
312+ }
300313 }
301314 }
315+ _ => { }
302316 }
303317 self . super_projection_elem ( local, proj_base, elem, context, location) ;
304318 }
0 commit comments