|
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