3
3
use std:: sync:: Arc ;
4
4
5
5
use cov_mark:: hit;
6
+ use smallvec:: SmallVec ;
6
7
use syntax:: SmolStr ;
7
8
use tracing:: debug;
8
9
@@ -108,46 +109,16 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
108
109
_ => self_ty_fp. as_ref ( ) . map ( std:: slice:: from_ref) . unwrap_or ( & [ ] ) ,
109
110
} ;
110
111
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) ;
137
113
138
114
let id_to_chalk = |id : hir_def:: ImplId | id. to_chalk ( self . db ) ;
139
115
140
116
let result: Vec < _ > = if fps. is_empty ( ) {
141
117
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 ( )
147
119
} else {
148
120
impl_maps
149
121
. iter ( )
150
- . filter_map ( |o| o. as_ref ( ) )
151
122
. flat_map ( |impls| {
152
123
fps. iter ( ) . flat_map ( move |fp| {
153
124
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> {
161
132
}
162
133
fn impl_provided_for ( & self , auto_trait_id : TraitId , kind : & chalk_ir:: TyKind < Interner > ) -> bool {
163
134
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
+ }
165
187
}
166
188
fn associated_ty_value ( & self , id : AssociatedTyValueId ) -> Arc < AssociatedTyValue > {
167
189
self . db . associated_ty_value ( self . krate , id)
@@ -390,6 +412,41 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
390
412
}
391
413
}
392
414
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
+
393
450
impl < ' a > chalk_ir:: UnificationDatabase < Interner > for & ' a dyn HirDatabase {
394
451
fn fn_def_variance (
395
452
& self ,
0 commit comments