|
2 | 2 | //! For details about how this works in rustc, see the method lookup page in the
|
3 | 3 | //! [rustc guide](https://rust-lang.github.io/rustc-guide/method-lookup.html)
|
4 | 4 | //! and the corresponding code mostly in rustc_hir_analysis/check/method/probe.rs.
|
5 |
| -use std::{iter, ops::ControlFlow, sync::Arc}; |
| 5 | +use std::{ops::ControlFlow, sync::Arc}; |
6 | 6 |
|
7 |
| -use arrayvec::ArrayVec; |
8 | 7 | use base_db::{CrateId, Edition};
|
9 | 8 | use chalk_ir::{cast::Cast, Mutability, UniverseIndex};
|
10 | 9 | use hir_def::{
|
11 | 10 | data::ImplData, item_scope::ItemScope, nameres::DefMap, AssocItemId, BlockId, ConstId,
|
12 |
| - FunctionId, GenericDefId, HasModule, ImplId, ItemContainerId, Lookup, ModuleDefId, ModuleId, |
13 |
| - TraitId, |
| 11 | + FunctionId, HasModule, ImplId, ItemContainerId, Lookup, ModuleDefId, ModuleId, TraitId, |
14 | 12 | };
|
15 | 13 | use hir_expand::name::Name;
|
16 | 14 | use rustc_hash::{FxHashMap, FxHashSet};
|
| 15 | +use smallvec::{smallvec, SmallVec}; |
17 | 16 | use stdx::never;
|
18 | 17 |
|
19 | 18 | use crate::{
|
@@ -336,21 +335,18 @@ impl InherentImpls {
|
336 | 335 | }
|
337 | 336 | }
|
338 | 337 |
|
339 |
| -pub(crate) fn inherent_impl_crates_query( |
| 338 | +pub(crate) fn incoherent_inherent_impl_crates( |
340 | 339 | db: &dyn HirDatabase,
|
341 | 340 | krate: CrateId,
|
342 | 341 | fp: TyFingerprint,
|
343 |
| -) -> ArrayVec<CrateId, 2> { |
| 342 | +) -> SmallVec<[CrateId; 2]> { |
344 | 343 | let _p = profile::span("inherent_impl_crates_query");
|
345 |
| - let mut res = ArrayVec::new(); |
| 344 | + let mut res = SmallVec::new(); |
346 | 345 | let crate_graph = db.crate_graph();
|
347 | 346 |
|
| 347 | + // should pass crate for finger print and do reverse deps |
| 348 | + |
348 | 349 | for krate in crate_graph.transitive_deps(krate) {
|
349 |
| - if res.is_full() { |
350 |
| - // we don't currently look for or store more than two crates here, |
351 |
| - // so don't needlessly look at more crates than necessary. |
352 |
| - break; |
353 |
| - } |
354 | 350 | let impls = db.inherent_impls_in_crate(krate);
|
355 | 351 | if impls.map.get(&fp).map_or(false, |v| !v.is_empty()) {
|
356 | 352 | res.push(krate);
|
@@ -392,30 +388,52 @@ pub fn def_crates(
|
392 | 388 | db: &dyn HirDatabase,
|
393 | 389 | ty: &Ty,
|
394 | 390 | cur_crate: CrateId,
|
395 |
| -) -> Option<ArrayVec<CrateId, 2>> { |
396 |
| - let mod_to_crate_ids = |module: ModuleId| Some(iter::once(module.krate()).collect()); |
397 |
| - |
398 |
| - let fp = TyFingerprint::for_inherent_impl(ty); |
399 |
| - |
| 391 | +) -> Option<SmallVec<[CrateId; 2]>> { |
400 | 392 | match ty.kind(Interner) {
|
401 |
| - TyKind::Adt(AdtId(def_id), _) => mod_to_crate_ids(def_id.module(db.upcast())), |
402 |
| - TyKind::Foreign(id) => { |
403 |
| - mod_to_crate_ids(from_foreign_def_id(*id).lookup(db.upcast()).module(db.upcast())) |
| 393 | + &TyKind::Adt(AdtId(def_id), _) => { |
| 394 | + let rustc_has_incoherent_inherent_impls = match def_id { |
| 395 | + hir_def::AdtId::StructId(id) => { |
| 396 | + db.struct_data(id).rustc_has_incoherent_inherent_impls |
| 397 | + } |
| 398 | + hir_def::AdtId::UnionId(id) => { |
| 399 | + db.union_data(id).rustc_has_incoherent_inherent_impls |
| 400 | + } |
| 401 | + hir_def::AdtId::EnumId(id) => db.enum_data(id).rustc_has_incoherent_inherent_impls, |
| 402 | + }; |
| 403 | + Some(if rustc_has_incoherent_inherent_impls { |
| 404 | + db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::Adt(def_id)) |
| 405 | + } else { |
| 406 | + smallvec![def_id.module(db.upcast()).krate()] |
| 407 | + }) |
| 408 | + } |
| 409 | + &TyKind::Foreign(id) => { |
| 410 | + let alias = from_foreign_def_id(id); |
| 411 | + Some(if db.type_alias_data(alias).rustc_has_incoherent_inherent_impls { |
| 412 | + db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::ForeignType(id)) |
| 413 | + } else { |
| 414 | + smallvec![alias.module(db.upcast()).krate()] |
| 415 | + }) |
| 416 | + } |
| 417 | + TyKind::Dyn(_) => { |
| 418 | + let trait_id = ty.dyn_trait()?; |
| 419 | + Some(if db.trait_data(trait_id).rustc_has_incoherent_inherent_impls { |
| 420 | + db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::Dyn(trait_id)) |
| 421 | + } else { |
| 422 | + smallvec![trait_id.module(db.upcast()).krate()] |
| 423 | + }) |
404 | 424 | }
|
405 |
| - TyKind::Dyn(_) => ty |
406 |
| - .dyn_trait() |
407 |
| - .and_then(|trait_| mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast()))), |
408 | 425 | // for primitives, there may be impls in various places (core and alloc
|
409 | 426 | // mostly). We just check the whole crate graph for crates with impls
|
410 | 427 | // (cached behind a query).
|
411 | 428 | TyKind::Scalar(_)
|
412 | 429 | | TyKind::Str
|
413 | 430 | | TyKind::Slice(_)
|
414 | 431 | | TyKind::Array(..)
|
415 |
| - | TyKind::Raw(..) => { |
416 |
| - Some(db.inherent_impl_crates(cur_crate, fp.expect("fingerprint for primitive"))) |
417 |
| - } |
418 |
| - _ => return None, |
| 432 | + | TyKind::Raw(..) => Some(db.incoherent_inherent_impl_crates( |
| 433 | + cur_crate, |
| 434 | + TyFingerprint::for_inherent_impl(ty).expect("fingerprint for primitive"), |
| 435 | + )), |
| 436 | + _ => None, |
419 | 437 | }
|
420 | 438 | }
|
421 | 439 |
|
|
0 commit comments