|
1 | 1 | //! The implementation of `RustIrDatabase` for Chalk, which provides information |
2 | 2 | //! about the code that Chalk needs. |
3 | 3 | use core::ops; |
4 | | -use std::{iter, sync::Arc}; |
| 4 | +use std::{iter,ops::ControlFlow,sync::Arc}; |
5 | 5 |
|
6 | 6 | use tracing::debug; |
7 | 7 |
|
@@ -136,81 +136,91 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> { |
136 | 136 | _ => self_ty_fp.as_ref().map(std::slice::from_ref).unwrap_or(&[]), |
137 | 137 | }; |
138 | 138 |
|
139 | | -let trait_module = trait_.module(self.db.upcast()); |
140 | | -let type_module = match self_ty_fp { |
141 | | -Some(TyFingerprint::Adt(adt_id)) => Some(adt_id.module(self.db.upcast())), |
142 | | -Some(TyFingerprint::ForeignType(type_id)) => { |
143 | | -Some(from_foreign_def_id(type_id).module(self.db.upcast())) |
144 | | -} |
145 | | -Some(TyFingerprint::Dyn(trait_id)) => Some(trait_id.module(self.db.upcast())), |
146 | | - _ => None, |
147 | | -}; |
148 | | - |
149 | | -letmut def_blocks = |
150 | | -[trait_module.containing_block(), type_module.and_then(|it| it.containing_block())]; |
151 | | - |
152 | | -// Note: Since we're using impls_for_trait, only impls where the trait |
153 | | -// can be resolved should ever reach Chalk. impl_datum relies on that |
154 | | -// and will panic if the trait can't be resolved. |
155 | | -let in_deps = self.db.trait_impls_in_deps(self.krate); |
156 | | -let in_self = self.db.trait_impls_in_crate(self.krate); |
157 | | - |
158 | | -let block_impls = iter::successors(self.block, |&block_id| { |
159 | | - cov_mark::hit!(block_local_impls); |
160 | | -self.db.block_def_map(block_id).parent().and_then(|module| module.containing_block()) |
161 | | -}) |
162 | | -.inspect(|&block_id| { |
163 | | -// make sure we don't search the same block twice |
164 | | - def_blocks.iter_mut().for_each(|block| { |
165 | | -if*block == Some(block_id){ |
166 | | -*block = None; |
167 | | -} |
168 | | -}); |
169 | | -}) |
170 | | -.filter_map(|block_id| self.db.trait_impls_in_block(block_id)); |
171 | | - |
172 | 139 | let id_to_chalk = |id: hir_def::ImplId| id.to_chalk(self.db); |
| 140 | + |
173 | 141 | letmut result = vec![]; |
174 | | -match fps { |
175 | | -[] => { |
176 | | -debug!("Unrestricted search for {:?} impls...", trait_); |
177 | | -letmut f = |impls:&TraitImpls| { |
178 | | - result.extend(impls.for_trait(trait_).map(id_to_chalk)); |
179 | | -}; |
180 | | -f(&in_self); |
181 | | - in_deps.iter().map(ops::Deref::deref).for_each(&mut f); |
182 | | - block_impls.for_each(|it| f(&it)); |
183 | | - def_blocks |
184 | | -.into_iter() |
185 | | -.flatten() |
186 | | -.filter_map(|it| self.db.trait_impls_in_block(it)) |
187 | | -.for_each(|it| f(&it)); |
188 | | -} |
189 | | - fps => { |
190 | | -letmut f = |
191 | | - |impls:&TraitImpls| { |
192 | | - result.extend(fps.iter().flat_map(|fp| { |
193 | | - impls.for_trait_and_self_ty(trait_,*fp).map(id_to_chalk) |
194 | | -})); |
195 | | -}; |
196 | | -f(&in_self); |
197 | | - in_deps.iter().map(ops::Deref::deref).for_each(&mut f); |
198 | | - block_impls.for_each(|it| f(&it)); |
199 | | - def_blocks |
200 | | -.into_iter() |
201 | | -.flatten() |
202 | | -.filter_map(|it| self.db.trait_impls_in_block(it)) |
203 | | -.for_each(|it| f(&it)); |
204 | | -} |
205 | | -} |
| 142 | +if fps.is_empty(){ |
| 143 | +debug!("Unrestricted search for {:?} impls...", trait_); |
| 144 | +self.for_trait_impls(trait_, self_ty_fp, |impls| { |
| 145 | + result.extend(impls.for_trait(trait_).map(id_to_chalk)); |
| 146 | +ControlFlow::Continue(()) |
| 147 | +}) |
| 148 | +}else{ |
| 149 | +self.for_trait_impls(trait_, self_ty_fp, |impls| { |
| 150 | + result.extend( |
| 151 | + fps.iter().flat_map(move |fp| { |
| 152 | + impls.for_trait_and_self_ty(trait_,*fp).map(id_to_chalk) |
| 153 | +}), |
| 154 | +); |
| 155 | +ControlFlow::Continue(()) |
| 156 | +}) |
| 157 | +}; |
206 | 158 |
|
207 | 159 | debug!("impls_for_trait returned {} impls", result.len()); |
208 | 160 | result |
209 | 161 | } |
210 | 162 | fnimpl_provided_for(&self,auto_trait_id:TraitId,kind:&chalk_ir::TyKind<Interner>) -> bool{ |
211 | 163 | debug!("impl_provided_for {:?}, {:?}", auto_trait_id, kind); |
212 | | -false// FIXME |
| 164 | + |
| 165 | +let trait_id = from_chalk_trait_id(auto_trait_id); |
| 166 | +let self_ty = kind.clone().intern(Interner); |
| 167 | +// We cannot filter impls by `TyFingerprint` for the following types: |
| 168 | +let self_ty_fp = match kind { |
| 169 | +// because we need to find any impl whose Self type is a ref with the same mutability |
| 170 | +// (we don't care about the inner type). |
| 171 | +TyKind::Ref(..) => None, |
| 172 | +// because we need to find any impl whose Self type is a tuple with the same arity. |
| 173 | +TyKind::Tuple(..) => None, |
| 174 | + _ => TyFingerprint::for_trait_impl(&self_ty), |
| 175 | +}; |
| 176 | + |
| 177 | +let check_kind = |impl_id| { |
| 178 | +let impl_self_ty = self.db.impl_self_ty(impl_id); |
| 179 | +// NOTE(skip_binders): it's safe to skip binders here as we don't check substitutions. |
| 180 | +let impl_self_kind = impl_self_ty.skip_binders().kind(Interner); |
| 181 | + |
| 182 | +match(kind, impl_self_kind){ |
| 183 | +(TyKind::Adt(id_a, _),TyKind::Adt(id_b, _)) => id_a == id_b, |
| 184 | +(TyKind::AssociatedType(id_a, _),TyKind::AssociatedType(id_b, _)) => id_a == id_b, |
| 185 | +(TyKind::Scalar(scalar_a),TyKind::Scalar(scalar_b)) => scalar_a == scalar_b, |
| 186 | +(TyKind::Str,TyKind::Str) => true, |
| 187 | +(TyKind::Tuple(arity_a, _),TyKind::Tuple(arity_b, _)) => arity_a == arity_b, |
| 188 | +(TyKind::OpaqueType(id_a, _),TyKind::OpaqueType(id_b, _)) => id_a == id_b, |
| 189 | +(TyKind::Slice(_),TyKind::Slice(_)) => true, |
| 190 | +(TyKind::FnDef(id_a, _),TyKind::FnDef(id_b, _)) => id_a == id_b, |
| 191 | +(TyKind::Ref(id_a, _, _),TyKind::Ref(id_b, _, _)) => id_a == id_b, |
| 192 | +(TyKind::Raw(id_a, _),TyKind::Raw(id_b, _)) => id_a == id_b, |
| 193 | +(TyKind::Never,TyKind::Never) => true, |
| 194 | +(TyKind::Array(_, _),TyKind::Array(_, _)) => true, |
| 195 | +(TyKind::Closure(id_a, _),TyKind::Closure(id_b, _)) => id_a == id_b, |
| 196 | +(TyKind::Coroutine(id_a, _),TyKind::Coroutine(id_b, _)) => id_a == id_b, |
| 197 | +(TyKind::CoroutineWitness(id_a, _),TyKind::CoroutineWitness(id_b, _)) => { |
| 198 | + id_a == id_b |
| 199 | +} |
| 200 | +(TyKind::Foreign(id_a),TyKind::Foreign(id_b)) => id_a == id_b, |
| 201 | +(TyKind::Error,TyKind::Error) => true, |
| 202 | +(_, _) => false, |
| 203 | +} |
| 204 | +}; |
| 205 | + |
| 206 | +ifletSome(fp) = self_ty_fp { |
| 207 | +self.for_trait_impls(trait_id, self_ty_fp, |impls| { |
| 208 | +match impls.for_trait_and_self_ty(trait_id, fp).any(check_kind){ |
| 209 | +true => ControlFlow::Break(()), |
| 210 | +false => ControlFlow::Continue(()), |
| 211 | +} |
| 212 | +}) |
| 213 | +}else{ |
| 214 | +self.for_trait_impls(trait_id, self_ty_fp, |impls| { |
| 215 | +match impls.for_trait(trait_id).any(check_kind){ |
| 216 | +true => ControlFlow::Break(()), |
| 217 | +false => ControlFlow::Continue(()), |
| 218 | +} |
| 219 | +}) |
| 220 | +} |
| 221 | +.is_break() |
213 | 222 | } |
| 223 | + |
214 | 224 | fnassociated_ty_value(&self,id:AssociatedTyValueId) -> Arc<AssociatedTyValue>{ |
215 | 225 | self.db.associated_ty_value(self.krate, id) |
216 | 226 | } |
@@ -489,6 +499,59 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> { |
489 | 499 | } |
490 | 500 | } |
491 | 501 |
|
| 502 | +impl<'a>ChalkContext<'a>{ |
| 503 | +fnfor_trait_impls( |
| 504 | +&self, |
| 505 | +trait_id: hir_def::TraitId, |
| 506 | +self_ty_fp:Option<TyFingerprint>, |
| 507 | +mutf:implFnMut(&TraitImpls) -> ControlFlow<()>, |
| 508 | +) -> ControlFlow<()>{ |
| 509 | +// Note: Since we're using `impls_for_trait` and `impl_provided_for`, |
| 510 | +// only impls where the trait can be resolved should ever reach Chalk. |
| 511 | +// `impl_datum` relies on that and will panic if the trait can't be resolved. |
| 512 | +let in_deps = self.db.trait_impls_in_deps(self.krate); |
| 513 | +let in_self = self.db.trait_impls_in_crate(self.krate); |
| 514 | +let trait_module = trait_id.module(self.db.upcast()); |
| 515 | +let type_module = match self_ty_fp { |
| 516 | +Some(TyFingerprint::Adt(adt_id)) => Some(adt_id.module(self.db.upcast())), |
| 517 | +Some(TyFingerprint::ForeignType(type_id)) => { |
| 518 | +Some(from_foreign_def_id(type_id).module(self.db.upcast())) |
| 519 | +} |
| 520 | +Some(TyFingerprint::Dyn(trait_id)) => Some(trait_id.module(self.db.upcast())), |
| 521 | + _ => None, |
| 522 | +}; |
| 523 | + |
| 524 | +letmut def_blocks = |
| 525 | +[trait_module.containing_block(), type_module.and_then(|it| it.containing_block())]; |
| 526 | + |
| 527 | +let block_impls = iter::successors(self.block, |&block_id| { |
| 528 | + cov_mark::hit!(block_local_impls); |
| 529 | +self.db.block_def_map(block_id).parent().and_then(|module| module.containing_block()) |
| 530 | +}) |
| 531 | +.inspect(|&block_id| { |
| 532 | +// make sure we don't search the same block twice |
| 533 | + def_blocks.iter_mut().for_each(|block| { |
| 534 | +if*block == Some(block_id){ |
| 535 | +*block = None; |
| 536 | +} |
| 537 | +}); |
| 538 | +}) |
| 539 | +.filter_map(|block_id| self.db.trait_impls_in_block(block_id)); |
| 540 | +f(&in_self)?; |
| 541 | +for it in in_deps.iter().map(ops::Deref::deref){ |
| 542 | +f(it)?; |
| 543 | +} |
| 544 | +for it in block_impls { |
| 545 | +f(&it)?; |
| 546 | +} |
| 547 | +for it in def_blocks.into_iter().flatten().filter_map(|it| self.db.trait_impls_in_block(it)) |
| 548 | +{ |
| 549 | +f(&it)?; |
| 550 | +} |
| 551 | +ControlFlow::Continue(()) |
| 552 | +} |
| 553 | +} |
| 554 | + |
492 | 555 | impl chalk_ir::UnificationDatabase<Interner>for&dynHirDatabase{ |
493 | 556 | fnfn_def_variance( |
494 | 557 | &self, |
|
0 commit comments