@@ -72,6 +72,10 @@ impl AlternativeExprs {
7272 AlternativeExprs :: Many => ( ) ,
7373 }
7474 }
75+
76+ fn is_many ( & self ) -> bool {
77+ matches ! ( self , AlternativeExprs :: Many )
78+ }
7579}
7680
7781/// # Lookup table for term search
@@ -103,27 +107,36 @@ struct LookupTable {
103107
104108impl LookupTable {
105109 /// Initialize lookup table
106- fn new ( many_threshold : usize ) -> Self {
110+ fn new ( many_threshold : usize , goal : Type ) -> Self {
107111 let mut res = Self { many_threshold, ..Default :: default ( ) } ;
108112 res. new_types . insert ( NewTypesKey :: ImplMethod , Vec :: new ( ) ) ;
109113 res. new_types . insert ( NewTypesKey :: StructProjection , Vec :: new ( ) ) ;
114+ res. types_wishlist . insert ( goal) ;
110115 res
111116 }
112117
113118 /// Find all `Expr`s that unify with the `ty`
114- fn find ( & self , db : & dyn HirDatabase , ty : & Type ) -> Option < Vec < Expr > > {
115- self . data
119+ fn find ( & mut self , db : & dyn HirDatabase , ty : & Type ) -> Option < Vec < Expr > > {
120+ let res = self
121+ . data
116122 . iter ( )
117123 . find ( |( t, _) | t. could_unify_with_deeply ( db, ty) )
118- . map ( |( t, tts) | tts. exprs ( t) )
124+ . map ( |( t, tts) | tts. exprs ( t) ) ;
125+
126+ if res. is_none ( ) {
127+ self . types_wishlist . insert ( ty. clone ( ) ) ;
128+ }
129+
130+ res
119131 }
120132
121133 /// Same as find but automatically creates shared reference of types in the lookup
122134 ///
123135 /// For example if we have type `i32` in data and we query for `&i32` it map all the type
124136 /// trees we have for `i32` with `Expr::Reference` and returns them.
125- fn find_autoref ( & self , db : & dyn HirDatabase , ty : & Type ) -> Option < Vec < Expr > > {
126- self . data
137+ fn find_autoref ( & mut self , db : & dyn HirDatabase , ty : & Type ) -> Option < Vec < Expr > > {
138+ let res = self
139+ . data
127140 . iter ( )
128141 . find ( |( t, _) | t. could_unify_with_deeply ( db, ty) )
129142 . map ( |( t, it) | it. exprs ( t) )
@@ -139,7 +152,13 @@ impl LookupTable {
139152 . map ( |expr| Expr :: Reference ( Box :: new ( expr) ) )
140153 . collect ( )
141154 } )
142- } )
155+ } ) ;
156+
157+ if res. is_none ( ) {
158+ self . types_wishlist . insert ( ty. clone ( ) ) ;
159+ }
160+
161+ res
143162 }
144163
145164 /// Insert new type trees for type
@@ -149,7 +168,12 @@ impl LookupTable {
149168 /// but they clearly do not unify themselves.
150169 fn insert ( & mut self , ty : Type , exprs : impl Iterator < Item = Expr > ) {
151170 match self . data . get_mut ( & ty) {
152- Some ( it) => it. extend_with_threshold ( self . many_threshold , exprs) ,
171+ Some ( it) => {
172+ it. extend_with_threshold ( self . many_threshold , exprs) ;
173+ if it. is_many ( ) {
174+ self . types_wishlist . remove ( & ty) ;
175+ }
176+ }
153177 None => {
154178 self . data . insert ( ty. clone ( ) , AlternativeExprs :: new ( self . many_threshold , exprs) ) ;
155179 for it in self . new_types . values_mut ( ) {
@@ -206,8 +230,8 @@ impl LookupTable {
206230 }
207231
208232 /// Types queried but not found
209- fn take_types_wishlist ( & mut self ) -> FxHashSet < Type > {
210- std :: mem :: take ( & mut self . types_wishlist )
233+ fn types_wishlist ( & mut self ) -> & FxHashSet < Type > {
234+ & self . types_wishlist
211235 }
212236}
213237
@@ -272,7 +296,7 @@ pub fn term_search<DB: HirDatabase>(ctx: &TermSearchCtx<'_, DB>) -> Vec<Expr> {
272296 defs. insert ( def) ;
273297 } ) ;
274298
275- let mut lookup = LookupTable :: new ( ctx. config . many_alternatives_threshold ) ;
299+ let mut lookup = LookupTable :: new ( ctx. config . many_alternatives_threshold , ctx . goal . clone ( ) ) ;
276300
277301 // Try trivial tactic first, also populates lookup table
278302 let mut solutions: Vec < Expr > = tactics:: trivial ( ctx, & defs, & mut lookup) . collect ( ) ;
0 commit comments