@@ -565,6 +565,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
565565 Some ( self . root_var ( self . shallow_resolve ( ty) . ty_vid ( ) ?) )
566566 }
567567
568+ /// Given a set of diverging vids and coercions, walk the HIR to gather a
569+ /// set of suggestions which can be applied to preserve fallback to unit.
568570 fn try_to_suggest_annotations (
569571 & self ,
570572 diverging_vids : & [ ty:: TyVid ] ,
@@ -574,26 +576,34 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
574576 self . tcx . hir ( ) . maybe_body_owned_by ( self . body_id ) . expect ( "body id must have an owner" ) ;
575577 // For each diverging var, look through the HIR for a place to give it
576578 // a type annotation. We do this per var because we only really need one
577- // per var.
579+ // suggestion to influence a var to be `()` .
578580 let suggestions = diverging_vids
579581 . iter ( )
580582 . copied ( )
581583 . filter_map ( |vid| {
582584 let reachable_vids =
583585 graph:: depth_first_search_as_undirected ( coercions, vid) . collect ( ) ;
584- VidVisitor { reachable_vids, fcx : self } . visit_expr ( body. value ) . break_value ( )
586+ AnnotateUnitFallbackVisitor { reachable_vids, fcx : self }
587+ . visit_expr ( body. value )
588+ . break_value ( )
585589 } )
586590 . collect ( ) ;
587591 errors:: SuggestAnnotations { suggestions }
588592 }
589593}
590594
591- /// Try to collect a useful suggestion to preserve fallback to `()`.
592- struct VidVisitor < ' a , ' tcx > {
595+ /// Try to walk the HIR to find a place to insert a useful suggestion
596+ /// to preserve fallback to `()` in 2024.
597+ struct AnnotateUnitFallbackVisitor < ' a , ' tcx > {
593598 reachable_vids : FxHashSet < ty:: TyVid > ,
594599 fcx : & ' a FnCtxt < ' a , ' tcx > ,
595600}
596- impl < ' tcx > VidVisitor < ' _ , ' tcx > {
601+ impl < ' tcx > AnnotateUnitFallbackVisitor < ' _ , ' tcx > {
602+ // For a given path segment, if it's missing a turbofish, try to suggest adding
603+ // one so we can constrain an argument to `()`. To keep the suggestion simple,
604+ // we want to simply suggest `_` for all the other args. This (for now) only
605+ // works when there are only type variables (and region variables, since we can
606+ // elide them)...
597607 fn suggest_for_segment (
598608 & self ,
599609 arg_segment : & ' tcx hir:: PathSegment < ' tcx > ,
@@ -627,7 +637,7 @@ impl<'tcx> VidVisitor<'_, 'tcx> {
627637 ControlFlow :: Continue ( ( ) )
628638 }
629639}
630- impl < ' tcx > Visitor < ' tcx > for VidVisitor < ' _ , ' tcx > {
640+ impl < ' tcx > Visitor < ' tcx > for AnnotateUnitFallbackVisitor < ' _ , ' tcx > {
631641 type Result = ControlFlow < errors:: SuggestAnnotation > ;
632642
633643 fn visit_ty ( & mut self , hir_ty : & ' tcx hir:: Ty < ' tcx > ) -> Self :: Result {
@@ -657,9 +667,7 @@ impl<'tcx> Visitor<'tcx> for VidVisitor<'_, 'tcx> {
657667 return hir:: intravisit:: walk_qpath ( self , qpath, id) ;
658668 }
659669 } ;
660- // Alternatively, try to turbofish `::<_, (), _>` (ignoring lifetimes,
661- // since we don't need to turbofish those; they'll be inferred).
662- // FIXME: Same logic could work for types...
670+ // Alternatively, try to turbofish `::<_, (), _>`.
663671 if let Some ( def_id) = self . fcx . typeck_results . borrow ( ) . qpath_res ( qpath, id) . opt_def_id ( ) {
664672 self . suggest_for_segment ( arg_segment, def_id, id) ?;
665673 }
@@ -668,6 +676,7 @@ impl<'tcx> Visitor<'tcx> for VidVisitor<'_, 'tcx> {
668676
669677 fn visit_expr ( & mut self , expr : & ' tcx hir:: Expr < ' tcx > ) -> Self :: Result {
670678 // Try to suggest adding an explicit qself `()` to a trait method path.
679+ // i.e. changing `Default::default()` to `<() as Default>::default()`.
671680 if let hir:: ExprKind :: Path ( hir:: QPath :: Resolved ( None , path) ) = expr. kind
672681 && let Res :: Def ( DefKind :: AssocFn , def_id) = path. res
673682 && self . fcx . tcx . trait_of_item ( def_id) . is_some ( )
@@ -679,7 +688,7 @@ impl<'tcx> Visitor<'tcx> for VidVisitor<'_, 'tcx> {
679688 let span = path. span . shrink_to_lo ( ) . to ( trait_segment. ident . span ) ;
680689 return ControlFlow :: Break ( errors:: SuggestAnnotation :: Path ( span) ) ;
681690 }
682- // Or else turbofishing the method
691+ // Or else, try suggesting turbofishing the method args.
683692 if let hir:: ExprKind :: MethodCall ( segment, ..) = expr. kind
684693 && let Some ( def_id) =
685694 self . fcx . typeck_results . borrow ( ) . type_dependent_def_id ( expr. hir_id )
@@ -690,6 +699,7 @@ impl<'tcx> Visitor<'tcx> for VidVisitor<'_, 'tcx> {
690699 }
691700
692701 fn visit_local ( & mut self , local : & ' tcx hir:: LetStmt < ' tcx > ) -> Self :: Result {
702+ // For a local, try suggest annotating the type if it's missing.
693703 if let None = local. ty
694704 && let ty = self . fcx . typeck_results . borrow ( ) . node_type ( local. hir_id )
695705 && let Some ( vid) = self . fcx . root_vid ( ty)
0 commit comments