33use std:: sync:: Arc ;
44
55use cov_mark:: hit;
6+ use smallvec:: SmallVec ;
67use syntax:: SmolStr ;
78use tracing:: debug;
89
@@ -108,46 +109,16 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
108109 _ => self_ty_fp. as_ref ( ) . map ( std:: slice:: from_ref) . unwrap_or ( & [ ] ) ,
109110 } ;
110111
111- fn local_impls ( db : & dyn HirDatabase , module : ModuleId ) -> Option < Arc < TraitImpls > > {
112- let block = module. containing_block ( ) ?;
113- hit ! ( block_local_impls) ;
114- db. trait_impls_in_block ( block)
115- }
116-
117- // Note: Since we're using impls_for_trait, only impls where the trait
118- // can be resolved should ever reach Chalk. impl_datum relies on that
119- // and will panic if the trait can't be resolved.
120- let in_deps = self . db . trait_impls_in_deps ( self . krate ) ;
121- let in_self = self . db . trait_impls_in_crate ( self . krate ) ;
122- let trait_module = trait_. module ( self . db . upcast ( ) ) ;
123- let type_module = match self_ty_fp {
124- Some ( TyFingerprint :: Adt ( adt_id) ) => Some ( adt_id. module ( self . db . upcast ( ) ) ) ,
125- Some ( TyFingerprint :: ForeignType ( type_id) ) => {
126- Some ( from_foreign_def_id ( type_id) . module ( self . db . upcast ( ) ) )
127- }
128- Some ( TyFingerprint :: Dyn ( trait_id) ) => Some ( trait_id. module ( self . db . upcast ( ) ) ) ,
129- _ => None ,
130- } ;
131- let impl_maps = [
132- Some ( in_deps) ,
133- Some ( in_self) ,
134- local_impls ( self . db , trait_module) ,
135- type_module. and_then ( |m| local_impls ( self . db , m) ) ,
136- ] ;
112+ let impl_maps = self . get_trait_impls ( trait_, self_ty_fp) ;
137113
138114 let id_to_chalk = |id : hir_def:: ImplId | id. to_chalk ( self . db ) ;
139115
140116 let result: Vec < _ > = if fps. is_empty ( ) {
141117 debug ! ( "Unrestricted search for {:?} impls..." , trait_) ;
142- impl_maps
143- . iter ( )
144- . filter_map ( |o| o. as_ref ( ) )
145- . flat_map ( |impls| impls. for_trait ( trait_) . map ( id_to_chalk) )
146- . collect ( )
118+ impl_maps. iter ( ) . flat_map ( |impls| impls. for_trait ( trait_) . map ( id_to_chalk) ) . collect ( )
147119 } else {
148120 impl_maps
149121 . iter ( )
150- . filter_map ( |o| o. as_ref ( ) )
151122 . flat_map ( |impls| {
152123 fps. iter ( ) . flat_map ( move |fp| {
153124 impls. for_trait_and_self_ty ( trait_, * fp) . map ( id_to_chalk)
@@ -161,7 +132,58 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
161132 }
162133 fn impl_provided_for ( & self , auto_trait_id : TraitId , kind : & chalk_ir:: TyKind < Interner > ) -> bool {
163134 debug ! ( "impl_provided_for {:?}, {:?}" , auto_trait_id, kind) ;
164- false // FIXME
135+
136+ let trait_id = from_chalk_trait_id ( auto_trait_id) ;
137+ let self_ty = kind. clone ( ) . intern ( Interner ) ;
138+ // We cannot filter impls by `TyFingerprint` for the following types:
139+ let self_ty_fp = match kind {
140+ // because we need to find any impl whose Self type is a ref with the same mutability
141+ // (we don't care about the inner type).
142+ TyKind :: Ref ( ..) => None ,
143+ // because we need to find any impl whose Self type is a tuple with the same arity.
144+ TyKind :: Tuple ( ..) => None ,
145+ _ => TyFingerprint :: for_trait_impl ( & self_ty) ,
146+ } ;
147+
148+ let impl_maps = self . get_trait_impls ( trait_id, self_ty_fp) ;
149+
150+ let check_kind = |impl_id| {
151+ let impl_self_ty = self . db . impl_self_ty ( impl_id) ;
152+ // NOTE(skip_binders): it's safe to skip binders here as we don't check substitutions.
153+ let impl_self_kind = impl_self_ty. skip_binders ( ) . kind ( Interner ) ;
154+
155+ match ( kind, impl_self_kind) {
156+ ( TyKind :: Adt ( id_a, _) , TyKind :: Adt ( id_b, _) ) => id_a == id_b,
157+ ( TyKind :: AssociatedType ( id_a, _) , TyKind :: AssociatedType ( id_b, _) ) => id_a == id_b,
158+ ( TyKind :: Scalar ( scalar_a) , TyKind :: Scalar ( scalar_b) ) => scalar_a == scalar_b,
159+ ( TyKind :: Str , TyKind :: Str ) => true ,
160+ ( TyKind :: Tuple ( arity_a, _) , TyKind :: Tuple ( arity_b, _) ) => arity_a == arity_b,
161+ ( TyKind :: OpaqueType ( id_a, _) , TyKind :: OpaqueType ( id_b, _) ) => id_a == id_b,
162+ ( TyKind :: Slice ( _) , TyKind :: Slice ( _) ) => true ,
163+ ( TyKind :: FnDef ( id_a, _) , TyKind :: FnDef ( id_b, _) ) => id_a == id_b,
164+ ( TyKind :: Ref ( id_a, _, _) , TyKind :: Ref ( id_b, _, _) ) => id_a == id_b,
165+ ( TyKind :: Raw ( id_a, _) , TyKind :: Raw ( id_b, _) ) => id_a == id_b,
166+ ( TyKind :: Never , TyKind :: Never ) => true ,
167+ ( TyKind :: Array ( _, _) , TyKind :: Array ( _, _) ) => true ,
168+ ( TyKind :: Closure ( id_a, _) , TyKind :: Closure ( id_b, _) ) => id_a == id_b,
169+ ( TyKind :: Generator ( id_a, _) , TyKind :: Generator ( id_b, _) ) => id_a == id_b,
170+ ( TyKind :: GeneratorWitness ( id_a, _) , TyKind :: GeneratorWitness ( id_b, _) ) => {
171+ id_a == id_b
172+ }
173+ ( TyKind :: Foreign ( id_a) , TyKind :: Foreign ( id_b) ) => id_a == id_b,
174+ ( TyKind :: Error , TyKind :: Error ) => true ,
175+ ( _, _) => false ,
176+ }
177+ } ;
178+
179+ if let Some ( fp) = self_ty_fp {
180+ impl_maps
181+ . iter ( )
182+ . flat_map ( |impls| impls. for_trait_and_self_ty ( trait_id, fp) )
183+ . any ( check_kind)
184+ } else {
185+ impl_maps. iter ( ) . flat_map ( |impls| impls. for_trait ( trait_id) ) . any ( check_kind)
186+ }
165187 }
166188 fn associated_ty_value ( & self , id : AssociatedTyValueId ) -> Arc < AssociatedTyValue > {
167189 self . db . associated_ty_value ( self . krate , id)
@@ -390,6 +412,41 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
390412 }
391413}
392414
415+ impl < ' a > ChalkContext < ' a > {
416+ fn get_trait_impls (
417+ & self ,
418+ trait_id : hir_def:: TraitId ,
419+ self_ty_fp : Option < TyFingerprint > ,
420+ ) -> SmallVec < [ Arc < TraitImpls > ; 4 ] > {
421+ // Note: Since we're using `impls_for_trait` and `impl_provided_for`,
422+ // only impls where the trait can be resolved should ever reach Chalk.
423+ // `impl_datum` relies on that and will panic if the trait can't be resolved.
424+ let in_deps = self . db . trait_impls_in_deps ( self . krate ) ;
425+ let in_self = self . db . trait_impls_in_crate ( self . krate ) ;
426+ let trait_module = trait_id. module ( self . db . upcast ( ) ) ;
427+ let type_module = match self_ty_fp {
428+ Some ( TyFingerprint :: Adt ( adt_id) ) => Some ( adt_id. module ( self . db . upcast ( ) ) ) ,
429+ Some ( TyFingerprint :: ForeignType ( type_id) ) => {
430+ Some ( from_foreign_def_id ( type_id) . module ( self . db . upcast ( ) ) )
431+ }
432+ Some ( TyFingerprint :: Dyn ( trait_id) ) => Some ( trait_id. module ( self . db . upcast ( ) ) ) ,
433+ _ => None ,
434+ } ;
435+
436+ [ in_deps, in_self]
437+ . into_iter ( )
438+ . chain ( self . local_impls ( trait_module) )
439+ . chain ( type_module. and_then ( |m| self . local_impls ( m) ) )
440+ . collect ( )
441+ }
442+
443+ fn local_impls ( & self , module : ModuleId ) -> Option < Arc < TraitImpls > > {
444+ let block = module. containing_block ( ) ?;
445+ hit ! ( block_local_impls) ;
446+ self . db . trait_impls_in_block ( block)
447+ }
448+ }
449+
393450impl < ' a > chalk_ir:: UnificationDatabase < Interner > for & ' a dyn HirDatabase {
394451 fn fn_def_variance (
395452 & self ,
0 commit comments