@@ -512,46 +512,47 @@ fn method_autoderef_steps<'tcx>(
512
512
. include_raw_pointers ( )
513
513
. silence_errors ( ) ;
514
514
let mut reached_raw_pointer = false ;
515
- let mut steps: Vec < _ > = autoderef
516
- . by_ref ( )
517
- . map ( |( ty, d) | {
515
+ let mut steps = Vec :: new ( ) ;
516
+ for ( ty, d) in & mut autoderef {
517
+ let step = CandidateStep {
518
+ self_ty : infcx. make_query_response_ignoring_pending_obligations ( inference_vars, ty) ,
519
+ autoderefs : d,
520
+ from_unsafe_deref : reached_raw_pointer,
521
+ unsize : false ,
522
+ } ;
523
+ steps. push ( step) ;
524
+ if let ty:: RawPtr ( _) = ty. kind ( ) {
525
+ // all the subsequent steps will be from_unsafe_deref
526
+ reached_raw_pointer = true ;
527
+ } else if let ty:: Array ( elem_ty, _) = ty. kind ( ) {
528
+ // Array implements Deref/DerefMut so we would always deref instead of unsizing the
529
+ // array without this check. This is fine in theory, but it is currently not possible
530
+ // to deref in a const context on stable, while unsizing is so to keep that working
531
+ // we need to still special case the autoderef step handling here.
518
532
let step = CandidateStep {
519
- self_ty : infcx. make_query_response_ignoring_pending_obligations ( inference_vars, ty) ,
533
+ self_ty : infcx. make_query_response_ignoring_pending_obligations (
534
+ inference_vars,
535
+ infcx. tcx . mk_slice ( * elem_ty) ,
536
+ ) ,
520
537
autoderefs : d,
538
+ // this could be from an unsafe deref if we had
539
+ // a *mut/const [T; N]
521
540
from_unsafe_deref : reached_raw_pointer,
522
- unsize : false ,
541
+ unsize : true ,
523
542
} ;
524
- if let ty:: RawPtr ( _) = ty. kind ( ) {
525
- // all the subsequent steps will be from_unsafe_deref
526
- reached_raw_pointer = true ;
527
- }
528
- step
529
- } )
530
- . collect ( ) ;
543
+ steps. push ( step) ;
544
+ // We just added the slice step manually, so break out early. Slices don't deref
545
+ // into anything so the final type of the autoderef is set up correctly.
546
+ break ;
547
+ }
548
+ }
531
549
532
550
let final_ty = autoderef. final_ty ( true ) ;
533
551
let opt_bad_ty = match final_ty. kind ( ) {
534
552
ty:: Infer ( ty:: TyVar ( _) ) | ty:: Error ( _) => Some ( MethodAutoderefBadTy {
535
553
reached_raw_pointer,
536
554
ty : infcx. make_query_response_ignoring_pending_obligations ( inference_vars, final_ty) ,
537
555
} ) ,
538
- ty:: Array ( elem_ty, _) => {
539
- let dereferences = steps. len ( ) - 1 ;
540
-
541
- steps. push ( CandidateStep {
542
- self_ty : infcx. make_query_response_ignoring_pending_obligations (
543
- inference_vars,
544
- infcx. tcx . mk_slice ( * elem_ty) ,
545
- ) ,
546
- autoderefs : dereferences,
547
- // this could be from an unsafe deref if we had
548
- // a *mut/const [T; N]
549
- from_unsafe_deref : reached_raw_pointer,
550
- unsize : true ,
551
- } ) ;
552
-
553
- None
554
- }
555
556
_ => None ,
556
557
} ;
557
558
0 commit comments