33use std:: ops:: ControlFlow ;
44
55use crate :: ty:: {
6- visit:: TypeVisitable , AliasTy , Const , ConstKind , DefIdTree , InferConst , InferTy , Opaque ,
7- PolyTraitPredicate , Projection , Ty , TyCtxt , TypeSuperVisitable , TypeVisitor ,
6+ visit:: TypeVisitable , AliasTy , Const , ConstKind , DefIdTree , FallibleTypeFolder , InferConst ,
7+ InferTy , Opaque , PolyTraitPredicate , Projection , Ty , TyCtxt , TypeFoldable , TypeSuperFoldable ,
8+ TypeSuperVisitable , TypeVisitor ,
89} ;
910
1011use rustc_data_structures:: fx:: FxHashMap ;
@@ -76,7 +77,7 @@ impl<'tcx> Ty<'tcx> {
7677 }
7778}
7879
79- pub trait IsSuggestable < ' tcx > {
80+ pub trait IsSuggestable < ' tcx > : Sized {
8081 /// Whether this makes sense to suggest in a diagnostic.
8182 ///
8283 /// We filter out certain types and constants since they don't provide
@@ -87,15 +88,21 @@ pub trait IsSuggestable<'tcx> {
8788 /// Only if `infer_suggestable` is true, we consider type and const
8889 /// inference variables to be suggestable.
8990 fn is_suggestable ( self , tcx : TyCtxt < ' tcx > , infer_suggestable : bool ) -> bool ;
91+
92+ fn make_suggestable ( self , tcx : TyCtxt < ' tcx > , infer_suggestable : bool ) -> Option < Self > ;
9093}
9194
9295impl < ' tcx , T > IsSuggestable < ' tcx > for T
9396where
94- T : TypeVisitable < ' tcx > ,
97+ T : TypeVisitable < ' tcx > + TypeFoldable < ' tcx > ,
9598{
9699 fn is_suggestable ( self , tcx : TyCtxt < ' tcx > , infer_suggestable : bool ) -> bool {
97100 self . visit_with ( & mut IsSuggestableVisitor { tcx, infer_suggestable } ) . is_continue ( )
98101 }
102+
103+ fn make_suggestable ( self , tcx : TyCtxt < ' tcx > , infer_suggestable : bool ) -> Option < T > {
104+ self . try_fold_with ( & mut MakeSuggestableFolder { tcx, infer_suggestable } ) . ok ( )
105+ }
99106}
100107
101108pub fn suggest_arbitrary_trait_bound < ' tcx > (
@@ -509,3 +516,83 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
509516 c. super_visit_with ( self )
510517 }
511518}
519+
520+ pub struct MakeSuggestableFolder < ' tcx > {
521+ tcx : TyCtxt < ' tcx > ,
522+ infer_suggestable : bool ,
523+ }
524+
525+ impl < ' tcx > FallibleTypeFolder < ' tcx > for MakeSuggestableFolder < ' tcx > {
526+ type Error = ( ) ;
527+
528+ fn tcx ( & self ) -> TyCtxt < ' tcx > {
529+ self . tcx
530+ }
531+
532+ fn try_fold_ty ( & mut self , t : Ty < ' tcx > ) -> Result < Ty < ' tcx > , Self :: Error > {
533+ let t = match * t. kind ( ) {
534+ Infer ( InferTy :: TyVar ( _) ) if self . infer_suggestable => t,
535+
536+ FnDef ( def_id, substs) => {
537+ self . tcx . mk_fn_ptr ( self . tcx . fn_sig ( def_id) . subst ( self . tcx , substs) )
538+ }
539+
540+ // FIXME(compiler-errors): We could replace these with infer, I guess.
541+ Closure ( ..)
542+ | Infer ( ..)
543+ | Generator ( ..)
544+ | GeneratorWitness ( ..)
545+ | Bound ( _, _)
546+ | Placeholder ( _)
547+ | Error ( _) => {
548+ return Err ( ( ) ) ;
549+ }
550+
551+ Alias ( Opaque , AliasTy { def_id, .. } ) => {
552+ let parent = self . tcx . parent ( def_id) ;
553+ if let hir:: def:: DefKind :: TyAlias | hir:: def:: DefKind :: AssocTy = self . tcx . def_kind ( parent)
554+ && let Alias ( Opaque , AliasTy { def_id : parent_opaque_def_id, .. } ) = * self . tcx . type_of ( parent) . kind ( )
555+ && parent_opaque_def_id == def_id
556+ {
557+ t
558+ } else {
559+ return Err ( ( ) ) ;
560+ }
561+ }
562+
563+ Param ( param) => {
564+ // FIXME: It would be nice to make this not use string manipulation,
565+ // but it's pretty hard to do this, since `ty::ParamTy` is missing
566+ // sufficient info to determine if it is synthetic, and we don't
567+ // always have a convenient way of getting `ty::Generics` at the call
568+ // sites we invoke `IsSuggestable::is_suggestable`.
569+ if param. name . as_str ( ) . starts_with ( "impl " ) {
570+ return Err ( ( ) ) ;
571+ }
572+
573+ t
574+ }
575+
576+ _ => t,
577+ } ;
578+
579+ t. try_super_fold_with ( self )
580+ }
581+
582+ fn try_fold_const ( & mut self , c : Const < ' tcx > ) -> Result < Const < ' tcx > , ( ) > {
583+ let c = match c. kind ( ) {
584+ ConstKind :: Infer ( InferConst :: Var ( _) ) if self . infer_suggestable => c,
585+
586+ ConstKind :: Infer ( ..)
587+ | ConstKind :: Bound ( ..)
588+ | ConstKind :: Placeholder ( ..)
589+ | ConstKind :: Error ( ..) => {
590+ return Err ( ( ) ) ;
591+ }
592+
593+ _ => c,
594+ } ;
595+
596+ c. try_super_fold_with ( self )
597+ }
598+ }
0 commit comments