@@ -17,11 +17,11 @@ use itertools::Itertools;
1717use rustc_hash:: FxHashSet ;
1818
1919use crate :: {
20- Adt , AssocItem , Enum , GenericDef , GenericParam , HasVisibility , Impl , ModuleDef , ScopeDef , Type ,
21- TypeParam , Variant ,
20+ Adt , AssocItem , GenericDef , GenericParam , HasVisibility , Impl , ModuleDef , ScopeDef , Type ,
21+ TypeParam ,
2222} ;
2323
24- use crate :: term_search:: { Expr , TermSearchConfig } ;
24+ use crate :: term_search:: Expr ;
2525
2626use super :: { LookupTable , NewTypesKey , TermSearchCtx } ;
2727
@@ -151,212 +151,101 @@ pub(super) fn assoc_const<'a, DB: HirDatabase>(
151151/// * `should_continue` - Function that indicates when to stop iterating
152152pub ( super ) fn data_constructor < ' a , DB : HirDatabase > (
153153 ctx : & ' a TermSearchCtx < ' a , DB > ,
154- defs : & ' a FxHashSet < ScopeDef > ,
154+ _defs : & ' a FxHashSet < ScopeDef > ,
155155 lookup : & ' a mut LookupTable ,
156156 should_continue : & ' a dyn std:: ops:: Fn ( ) -> bool ,
157157) -> impl Iterator < Item = Expr > + ' a {
158158 let db = ctx. sema . db ;
159159 let module = ctx. scope . module ( ) ;
160- fn variant_helper (
161- db : & dyn HirDatabase ,
162- lookup : & mut LookupTable ,
163- should_continue : & dyn std:: ops:: Fn ( ) -> bool ,
164- parent_enum : Enum ,
165- variant : Variant ,
166- config : & TermSearchConfig ,
167- ) -> Vec < ( Type , Vec < Expr > ) > {
168- // Ignore unstable
169- if variant. is_unstable ( db) {
170- return Vec :: new ( ) ;
171- }
172-
173- let generics = GenericDef :: from ( variant. parent_enum ( db) ) ;
174- let Some ( type_params) = generics
175- . type_or_const_params ( db)
176- . into_iter ( )
177- . map ( |it| it. as_type_param ( db) )
178- . collect :: < Option < Vec < TypeParam > > > ( )
179- else {
180- // Ignore enums with const generics
181- return Vec :: new ( ) ;
182- } ;
183-
184- // We currently do not check lifetime bounds so ignore all types that have something to do
185- // with them
186- if !generics. lifetime_params ( db) . is_empty ( ) {
187- return Vec :: new ( ) ;
188- }
160+ lookup
161+ . types_wishlist ( )
162+ . clone ( )
163+ . into_iter ( )
164+ . chain ( iter:: once ( ctx. goal . clone ( ) ) )
165+ . filter_map ( |ty| ty. as_adt ( ) . map ( |adt| ( adt, ty) ) )
166+ . filter ( |_| should_continue ( ) )
167+ . filter_map ( move |( adt, ty) | match adt {
168+ Adt :: Struct ( strukt) => {
169+ // Ignore unstable or not visible
170+ if strukt. is_unstable ( db) || !strukt. is_visible_from ( db, module) {
171+ return None ;
172+ }
189173
190- // Only account for stable type parameters for now, unstable params can be default
191- // tho, for example in `Box<T, #[unstable] A: Allocator>`
192- if type_params. iter ( ) . any ( |it| it. is_unstable ( db) && it. default ( db) . is_none ( ) ) {
193- return Vec :: new ( ) ;
194- }
174+ let generics = GenericDef :: from ( strukt) ;
195175
196- let non_default_type_params_len =
197- type_params. iter ( ) . filter ( |it| it. default ( db) . is_none ( ) ) . count ( ) ;
198-
199- let enum_ty_shallow = Adt :: from ( parent_enum) . ty ( db) ;
200- let generic_params = lookup
201- . types_wishlist ( )
202- . clone ( )
203- . into_iter ( )
204- . filter ( |ty| ty. could_unify_with ( db, & enum_ty_shallow) )
205- . map ( |it| it. type_arguments ( ) . collect :: < Vec < Type > > ( ) )
206- . chain ( ( non_default_type_params_len == 0 ) . then_some ( Vec :: new ( ) ) ) ;
207-
208- generic_params
209- . filter ( |_| should_continue ( ) )
210- . filter_map ( move |generics| {
211- // Insert default type params
212- let mut g = generics. into_iter ( ) ;
213- let generics: Vec < _ > = type_params
214- . iter ( )
215- . map ( |it| it. default ( db) . or_else ( || g. next ( ) ) )
216- . collect :: < Option < _ > > ( ) ?;
176+ // We currently do not check lifetime bounds so ignore all types that have something to do
177+ // with them
178+ if !generics. lifetime_params ( db) . is_empty ( ) {
179+ return None ;
180+ }
217181
218- let enum_ty = Adt :: from ( parent_enum) . ty_with_args ( db, generics. iter ( ) . cloned ( ) ) ;
182+ if ty. contains_unknown ( ) {
183+ return None ;
184+ }
219185
220186 // Ignore types that have something to do with lifetimes
221- if config. enable_borrowcheck && enum_ty . contains_reference ( db) {
187+ if ctx . config . enable_borrowcheck && ty . contains_reference ( db) {
222188 return None ;
223189 }
190+ let fields = strukt. fields ( db) ;
191+ // Check if all fields are visible, otherwise we cannot fill them
192+ if fields. iter ( ) . any ( |it| !it. is_visible_from ( db, module) ) {
193+ return None ;
194+ }
195+
196+ let generics: Vec < _ > = ty. type_arguments ( ) . collect ( ) ;
224197
225198 // Early exit if some param cannot be filled from lookup
226- let param_exprs: Vec < Vec < Expr > > = variant
227- . fields ( db)
199+ let param_exprs: Vec < Vec < Expr > > = fields
228200 . into_iter ( )
229201 . map ( |field| lookup. find ( db, & field. ty_with_args ( db, generics. iter ( ) . cloned ( ) ) ) )
230202 . collect :: < Option < _ > > ( ) ?;
231203
232204 // Note that we need special case for 0 param constructors because of multi cartesian
233205 // product
234- let variant_exprs : Vec < Expr > = if param_exprs. is_empty ( ) {
235- vec ! [ Expr :: Variant { variant , generics, params: Vec :: new( ) } ]
206+ let exprs : Vec < Expr > = if param_exprs. is_empty ( ) {
207+ vec ! [ Expr :: Struct { strukt , generics, params: Vec :: new( ) } ]
236208 } else {
237209 param_exprs
238210 . into_iter ( )
239211 . multi_cartesian_product ( )
240- . map ( |params| Expr :: Variant { variant , generics : generics. clone ( ) , params } )
212+ . map ( |params| Expr :: Struct { strukt , generics : generics. clone ( ) , params } )
241213 . collect ( )
242214 } ;
243- lookup. insert ( enum_ty. clone ( ) , variant_exprs. iter ( ) . cloned ( ) ) ;
244-
245- Some ( ( enum_ty, variant_exprs) )
246- } )
247- . collect ( )
248- }
249- defs. iter ( )
250- . filter_map ( move |def| match def {
251- ScopeDef :: ModuleDef ( ModuleDef :: Variant ( it) ) => {
252- let variant_exprs = variant_helper (
253- db,
254- lookup,
255- should_continue,
256- it. parent_enum ( db) ,
257- * it,
258- & ctx. config ,
259- ) ;
260- if variant_exprs. is_empty ( ) {
261- return None ;
262- }
263- if GenericDef :: from ( it. parent_enum ( db) )
264- . type_or_const_params ( db)
265- . into_iter ( )
266- . filter_map ( |it| it. as_type_param ( db) )
267- . all ( |it| it. default ( db) . is_some ( ) )
268- {
269- lookup. mark_fulfilled ( ScopeDef :: ModuleDef ( ModuleDef :: Variant ( * it) ) ) ;
270- }
271- Some ( variant_exprs)
272- }
273- ScopeDef :: ModuleDef ( ModuleDef :: Adt ( Adt :: Enum ( enum_) ) ) => {
274- let exprs: Vec < ( Type , Vec < Expr > ) > = enum_
275- . variants ( db)
276- . into_iter ( )
277- . flat_map ( |it| {
278- variant_helper ( db, lookup, should_continue, * enum_, it, & ctx. config )
279- } )
280- . collect ( ) ;
281-
282- if exprs. is_empty ( ) {
283- return None ;
284- }
285-
286- if GenericDef :: from ( * enum_)
287- . type_or_const_params ( db)
288- . into_iter ( )
289- . filter_map ( |it| it. as_type_param ( db) )
290- . all ( |it| it. default ( db) . is_some ( ) )
291- {
292- lookup. mark_fulfilled ( ScopeDef :: ModuleDef ( ModuleDef :: Adt ( Adt :: Enum ( * enum_) ) ) ) ;
293- }
294215
295- Some ( exprs)
216+ lookup. insert ( ty. clone ( ) , exprs. iter ( ) . cloned ( ) ) ;
217+ Some ( ( ty, exprs) )
296218 }
297- ScopeDef :: ModuleDef ( ModuleDef :: Adt ( Adt :: Struct ( it ) ) ) => {
298- // Ignore unstable and not visible
299- if it . is_unstable ( db) || !it . is_visible_from ( db, module) {
219+ Adt :: Enum ( enum_ ) => {
220+ // Ignore unstable or not visible
221+ if enum_ . is_unstable ( db) || !enum_ . is_visible_from ( db, module) {
300222 return None ;
301223 }
302224
303- let generics = GenericDef :: from ( * it) ;
304-
305- // Ignore const params for now
306- let type_params = generics
307- . type_or_const_params ( db)
308- . into_iter ( )
309- . map ( |it| it. as_type_param ( db) )
310- . collect :: < Option < Vec < TypeParam > > > ( ) ?;
311-
225+ let generics = GenericDef :: from ( enum_) ;
312226 // We currently do not check lifetime bounds so ignore all types that have something to do
313227 // with them
314228 if !generics. lifetime_params ( db) . is_empty ( ) {
315229 return None ;
316230 }
317231
318- // Only account for stable type parameters for now, unstable params can be default
319- // tho, for example in `Box<T, #[unstable] A: Allocator>`
320- if type_params. iter ( ) . any ( |it| it. is_unstable ( db) && it. default ( db) . is_none ( ) ) {
232+ if ty. contains_unknown ( ) {
321233 return None ;
322234 }
323235
324- let non_default_type_params_len =
325- type_params. iter ( ) . filter ( |it| it. default ( db) . is_none ( ) ) . count ( ) ;
236+ // Ignore types that have something to do with lifetimes
237+ if ctx. config . enable_borrowcheck && ty. contains_reference ( db) {
238+ return None ;
239+ }
326240
327- let struct_ty_shallow = Adt :: from ( * it) . ty ( db) ;
328- let generic_params = lookup
329- . types_wishlist ( )
330- . clone ( )
241+ let generics: Vec < _ > = ty. type_arguments ( ) . collect ( ) ;
242+ let exprs = enum_
243+ . variants ( db)
331244 . into_iter ( )
332- . filter ( |ty| ty. could_unify_with ( db, & struct_ty_shallow) )
333- . map ( |it| it. type_arguments ( ) . collect :: < Vec < Type > > ( ) )
334- . chain ( ( non_default_type_params_len == 0 ) . then_some ( Vec :: new ( ) ) ) ;
335-
336- let exprs = generic_params
337- . filter ( |_| should_continue ( ) )
338- . filter_map ( |generics| {
339- // Insert default type params
340- let mut g = generics. into_iter ( ) ;
341- let generics: Vec < _ > = type_params
342- . iter ( )
343- . map ( |it| it. default ( db) . or_else ( || g. next ( ) ) )
344- . collect :: < Option < _ > > ( ) ?;
345-
346- let struct_ty = Adt :: from ( * it) . ty_with_args ( db, generics. iter ( ) . cloned ( ) ) ;
347-
348- // Ignore types that have something to do with lifetimes
349- if ctx. config . enable_borrowcheck && struct_ty. contains_reference ( db) {
350- return None ;
351- }
352- let fields = it. fields ( db) ;
353- // Check if all fields are visible, otherwise we cannot fill them
354- if fields. iter ( ) . any ( |it| !it. is_visible_from ( db, module) ) {
355- return None ;
356- }
357-
245+ . filter_map ( |variant| {
358246 // Early exit if some param cannot be filled from lookup
359- let param_exprs: Vec < Vec < Expr > > = fields
247+ let param_exprs: Vec < Vec < Expr > > = variant
248+ . fields ( db)
360249 . into_iter ( )
361250 . map ( |field| {
362251 lookup. find ( db, & field. ty_with_args ( db, generics. iter ( ) . cloned ( ) ) )
@@ -365,36 +254,33 @@ pub(super) fn data_constructor<'a, DB: HirDatabase>(
365254
366255 // Note that we need special case for 0 param constructors because of multi cartesian
367256 // product
368- let struct_exprs: Vec < Expr > = if param_exprs. is_empty ( ) {
369- vec ! [ Expr :: Struct { strukt: * it, generics, params: Vec :: new( ) } ]
257+ let variant_exprs: Vec < Expr > = if param_exprs. is_empty ( ) {
258+ vec ! [ Expr :: Variant {
259+ variant,
260+ generics: generics. clone( ) ,
261+ params: Vec :: new( ) ,
262+ } ]
370263 } else {
371264 param_exprs
372265 . into_iter ( )
373266 . multi_cartesian_product ( )
374- . map ( |params| Expr :: Struct {
375- strukt : * it ,
267+ . map ( |params| Expr :: Variant {
268+ variant ,
376269 generics : generics. clone ( ) ,
377270 params,
378271 } )
379272 . collect ( )
380273 } ;
381-
382- if non_default_type_params_len == 0 {
383- // Fulfilled only if there are no generic parameters
384- lookup. mark_fulfilled ( ScopeDef :: ModuleDef ( ModuleDef :: Adt (
385- Adt :: Struct ( * it) ,
386- ) ) ) ;
387- }
388- lookup. insert ( struct_ty. clone ( ) , struct_exprs. iter ( ) . cloned ( ) ) ;
389-
390- Some ( ( struct_ty, struct_exprs) )
274+ lookup. insert ( ty. clone ( ) , variant_exprs. iter ( ) . cloned ( ) ) ;
275+ Some ( variant_exprs)
391276 } )
277+ . flatten ( )
392278 . collect ( ) ;
393- Some ( exprs)
279+
280+ Some ( ( ty, exprs) )
394281 }
395- _ => None ,
282+ Adt :: Union ( _ ) => None ,
396283 } )
397- . flatten ( )
398284 . filter_map ( |( ty, exprs) | ty. could_unify_with_deeply ( db, & ctx. goal ) . then_some ( exprs) )
399285 . flatten ( )
400286}
0 commit comments