3
3
use std:: ops:: ControlFlow ;
4
4
5
5
use 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 ,
8
9
} ;
9
10
10
11
use rustc_data_structures:: fx:: FxHashMap ;
@@ -76,7 +77,7 @@ impl<'tcx> Ty<'tcx> {
76
77
}
77
78
}
78
79
79
- pub trait IsSuggestable < ' tcx > {
80
+ pub trait IsSuggestable < ' tcx > : Sized {
80
81
/// Whether this makes sense to suggest in a diagnostic.
81
82
///
82
83
/// We filter out certain types and constants since they don't provide
@@ -87,15 +88,21 @@ pub trait IsSuggestable<'tcx> {
87
88
/// Only if `infer_suggestable` is true, we consider type and const
88
89
/// inference variables to be suggestable.
89
90
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 > ;
90
93
}
91
94
92
95
impl < ' tcx , T > IsSuggestable < ' tcx > for T
93
96
where
94
- T : TypeVisitable < ' tcx > ,
97
+ T : TypeVisitable < ' tcx > + TypeFoldable < ' tcx > ,
95
98
{
96
99
fn is_suggestable ( self , tcx : TyCtxt < ' tcx > , infer_suggestable : bool ) -> bool {
97
100
self . visit_with ( & mut IsSuggestableVisitor { tcx, infer_suggestable } ) . is_continue ( )
98
101
}
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
+ }
99
106
}
100
107
101
108
pub fn suggest_arbitrary_trait_bound < ' tcx > (
@@ -509,3 +516,83 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
509
516
c. super_visit_with ( self )
510
517
}
511
518
}
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