1use std::ops::ControlFlow;
6
7use arrayvec::ArrayVec;
8use base_db::Crate;
9use chalk_ir::{UniverseIndex, WithKind, cast::Cast};
10use hir_def::{
11 AssocItemId, BlockId, ConstId, FunctionId, HasModule, ImplId, ItemContainerId, Lookup,
12 ModuleId, TraitId,
13 nameres::{DefMap, assoc::ImplItems, block_def_map, crate_def_map},
14 signatures::{ConstFlags, EnumFlags, FnFlags, StructFlags, TraitFlags, TypeAliasFlags},
15};
16use hir_expand::name::Name;
17use intern::sym;
18use rustc_hash::{FxHashMap, FxHashSet};
19use rustc_type_ir::inherent::{IntoKind, SliceLike};
20use smallvec::{SmallVec, smallvec};
21use stdx::never;
22use triomphe::Arc;
23
24use crate::{
25 AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, GenericArgData,
26 Goal, InEnvironment, Interner, Mutability, Scalar, Substitution, TraitEnvironment, TraitRef,
27 TraitRefExt, Ty, TyBuilder, TyExt, TyKind, TyVariableKind, VariableKind, WhereClause,
28 autoderef::{self, AutoderefKind},
29 db::HirDatabase,
30 error_lifetime, from_chalk_trait_id, from_foreign_def_id,
31 infer::{Adjust, Adjustment, OverloadedDeref, PointerCast, unify::InferenceTable},
32 lang_items::is_box,
33 next_solver::SolverDefId,
34 primitive::{FloatTy, IntTy, UintTy},
35 to_chalk_trait_id,
36 traits::NextTraitSolveResult,
37 utils::all_super_traits,
38};
39
40#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
42pub enum TyFingerprint {
43 Str,
45 Slice,
46 Array,
47 Never,
48 Ref(Mutability),
49 RawPtr(Mutability),
50 Scalar(Scalar),
51 Adt(hir_def::AdtId),
53 Dyn(TraitId),
54 ForeignType(ForeignDefId),
55 Unit,
57 Unnameable,
58 Function(u32),
59}
60
61impl TyFingerprint {
62 pub fn for_inherent_impl(ty: &Ty) -> Option<TyFingerprint> {
67 let fp = match ty.kind(Interner) {
68 TyKind::Str => TyFingerprint::Str,
69 TyKind::Never => TyFingerprint::Never,
70 TyKind::Slice(..) => TyFingerprint::Slice,
71 TyKind::Array(..) => TyFingerprint::Array,
72 TyKind::Scalar(scalar) => TyFingerprint::Scalar(*scalar),
73 TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(*adt),
74 TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(*mutability),
75 TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(*alias_id),
76 TyKind::Dyn(_) => ty.dyn_trait().map(TyFingerprint::Dyn)?,
77 _ => return None,
78 };
79 Some(fp)
80 }
81
82 pub fn for_trait_impl(ty: &Ty) -> Option<TyFingerprint> {
84 let fp = match ty.kind(Interner) {
85 TyKind::Str => TyFingerprint::Str,
86 TyKind::Never => TyFingerprint::Never,
87 TyKind::Slice(..) => TyFingerprint::Slice,
88 TyKind::Array(..) => TyFingerprint::Array,
89 TyKind::Scalar(scalar) => TyFingerprint::Scalar(*scalar),
90 TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(*adt),
91 TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(*mutability),
92 TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(*alias_id),
93 TyKind::Dyn(_) => ty.dyn_trait().map(TyFingerprint::Dyn)?,
94 TyKind::Ref(mutability, _, _) => TyFingerprint::Ref(*mutability),
95 TyKind::Tuple(_, subst) => {
96 let first_ty = subst.interned().first().map(|arg| arg.assert_ty_ref(Interner));
97 match first_ty {
98 Some(ty) => return TyFingerprint::for_trait_impl(ty),
99 None => TyFingerprint::Unit,
100 }
101 }
102 TyKind::AssociatedType(_, _)
103 | TyKind::OpaqueType(_, _)
104 | TyKind::FnDef(_, _)
105 | TyKind::Closure(_, _)
106 | TyKind::Coroutine(..)
107 | TyKind::CoroutineWitness(..) => TyFingerprint::Unnameable,
108 TyKind::Function(fn_ptr) => {
109 TyFingerprint::Function(fn_ptr.substitution.0.len(Interner) as u32)
110 }
111 TyKind::Alias(_)
112 | TyKind::Placeholder(_)
113 | TyKind::BoundVar(_)
114 | TyKind::InferenceVar(_, _)
115 | TyKind::Error => return None,
116 };
117 Some(fp)
118 }
119
120 pub fn for_trait_impl_ns<'db>(ty: &crate::next_solver::Ty<'db>) -> Option<TyFingerprint> {
122 use rustc_type_ir::TyKind;
123 let fp = match (*ty).kind() {
124 TyKind::Str => TyFingerprint::Str,
125 TyKind::Never => TyFingerprint::Never,
126 TyKind::Slice(..) => TyFingerprint::Slice,
127 TyKind::Array(..) => TyFingerprint::Array,
128 TyKind::Int(int) => TyFingerprint::Scalar(Scalar::Int(match int {
129 rustc_type_ir::IntTy::Isize => IntTy::Isize,
130 rustc_type_ir::IntTy::I8 => IntTy::I8,
131 rustc_type_ir::IntTy::I16 => IntTy::I16,
132 rustc_type_ir::IntTy::I32 => IntTy::I32,
133 rustc_type_ir::IntTy::I64 => IntTy::I64,
134 rustc_type_ir::IntTy::I128 => IntTy::I128,
135 })),
136 TyKind::Uint(uint) => TyFingerprint::Scalar(Scalar::Uint(match uint {
137 rustc_type_ir::UintTy::Usize => UintTy::Usize,
138 rustc_type_ir::UintTy::U8 => UintTy::U8,
139 rustc_type_ir::UintTy::U16 => UintTy::U16,
140 rustc_type_ir::UintTy::U32 => UintTy::U32,
141 rustc_type_ir::UintTy::U64 => UintTy::U64,
142 rustc_type_ir::UintTy::U128 => UintTy::U128,
143 })),
144 TyKind::Float(float) => TyFingerprint::Scalar(Scalar::Float(match float {
145 rustc_type_ir::FloatTy::F16 => FloatTy::F16,
146 rustc_type_ir::FloatTy::F32 => FloatTy::F32,
147 rustc_type_ir::FloatTy::F64 => FloatTy::F64,
148 rustc_type_ir::FloatTy::F128 => FloatTy::F128,
149 })),
150 TyKind::Bool => TyFingerprint::Scalar(Scalar::Bool),
151 TyKind::Char => TyFingerprint::Scalar(Scalar::Char),
152 TyKind::Adt(def, _) => TyFingerprint::Adt(def.inner().id),
153 TyKind::RawPtr(.., mutability) => match mutability {
154 rustc_ast_ir::Mutability::Mut => TyFingerprint::RawPtr(Mutability::Mut),
155 rustc_ast_ir::Mutability::Not => TyFingerprint::RawPtr(Mutability::Not),
156 },
157 TyKind::Foreign(def) => {
158 let SolverDefId::TypeAliasId(def) = def else { unreachable!() };
159 TyFingerprint::ForeignType(crate::to_foreign_def_id(def))
160 }
161 TyKind::Dynamic(bounds, _, _) => {
162 let trait_ref = bounds
163 .as_slice()
164 .iter()
165 .map(|b| (*b).skip_binder())
166 .filter_map(|b| match b {
167 rustc_type_ir::ExistentialPredicate::Trait(t) => Some(t.def_id),
168 _ => None,
169 })
170 .next()?;
171 let trait_id = match trait_ref {
172 SolverDefId::TraitId(id) => id,
173 _ => panic!("Bad GenericDefId in trait ref"),
174 };
175 TyFingerprint::Dyn(trait_id)
176 }
177 TyKind::Ref(_, _, mutability) => match mutability {
178 rustc_ast_ir::Mutability::Mut => TyFingerprint::Ref(Mutability::Mut),
179 rustc_ast_ir::Mutability::Not => TyFingerprint::Ref(Mutability::Not),
180 },
181 TyKind::Tuple(tys) => {
182 let first_ty = tys.as_slice().iter().next();
183 match first_ty {
184 Some(ty) => return TyFingerprint::for_trait_impl_ns(ty),
185 None => TyFingerprint::Unit,
186 }
187 }
188 TyKind::FnDef(_, _)
189 | TyKind::Closure(_, _)
190 | TyKind::Coroutine(..)
191 | TyKind::CoroutineWitness(..)
192 | TyKind::Pat(..)
193 | TyKind::CoroutineClosure(..) => TyFingerprint::Unnameable,
194 TyKind::FnPtr(sig, _) => {
195 TyFingerprint::Function(sig.inputs().skip_binder().len() as u32)
196 }
197 TyKind::Alias(..)
198 | TyKind::Placeholder(_)
199 | TyKind::Bound(..)
200 | TyKind::Infer(_)
201 | TyKind::Error(_)
202 | TyKind::Param(..)
203 | TyKind::UnsafeBinder(..) => return None,
204 };
205 Some(fp)
206 }
207}
208
209pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [
210 TyFingerprint::Scalar(Scalar::Int(IntTy::I8)),
211 TyFingerprint::Scalar(Scalar::Int(IntTy::I16)),
212 TyFingerprint::Scalar(Scalar::Int(IntTy::I32)),
213 TyFingerprint::Scalar(Scalar::Int(IntTy::I64)),
214 TyFingerprint::Scalar(Scalar::Int(IntTy::I128)),
215 TyFingerprint::Scalar(Scalar::Int(IntTy::Isize)),
216 TyFingerprint::Scalar(Scalar::Uint(UintTy::U8)),
217 TyFingerprint::Scalar(Scalar::Uint(UintTy::U16)),
218 TyFingerprint::Scalar(Scalar::Uint(UintTy::U32)),
219 TyFingerprint::Scalar(Scalar::Uint(UintTy::U64)),
220 TyFingerprint::Scalar(Scalar::Uint(UintTy::U128)),
221 TyFingerprint::Scalar(Scalar::Uint(UintTy::Usize)),
222];
223
224pub(crate) const ALL_FLOAT_FPS: [TyFingerprint; 4] = [
225 TyFingerprint::Scalar(Scalar::Float(FloatTy::F16)),
226 TyFingerprint::Scalar(Scalar::Float(FloatTy::F32)),
227 TyFingerprint::Scalar(Scalar::Float(FloatTy::F64)),
228 TyFingerprint::Scalar(Scalar::Float(FloatTy::F128)),
229];
230
231type TraitFpMap = FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Box<[ImplId]>>>;
232type TraitFpMapCollector = FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Vec<ImplId>>>;
233
234#[derive(Debug, Eq, PartialEq)]
236pub struct TraitImpls {
237 map: TraitFpMap,
239}
240
241impl TraitImpls {
242 pub(crate) fn trait_impls_in_crate_query(db: &dyn HirDatabase, krate: Crate) -> Arc<Self> {
243 let _p = tracing::info_span!("trait_impls_in_crate_query", ?krate).entered();
244 let mut impls = FxHashMap::default();
245
246 Self::collect_def_map(db, &mut impls, crate_def_map(db, krate));
247
248 Arc::new(Self::finish(impls))
249 }
250
251 pub(crate) fn trait_impls_in_block_query(
252 db: &dyn HirDatabase,
253 block: BlockId,
254 ) -> Option<Arc<Self>> {
255 let _p = tracing::info_span!("trait_impls_in_block_query").entered();
256 let mut impls = FxHashMap::default();
257
258 Self::collect_def_map(db, &mut impls, block_def_map(db, block));
259
260 if impls.is_empty() { None } else { Some(Arc::new(Self::finish(impls))) }
261 }
262
263 pub(crate) fn trait_impls_in_deps_query(
264 db: &dyn HirDatabase,
265 krate: Crate,
266 ) -> Arc<[Arc<Self>]> {
267 let _p = tracing::info_span!("trait_impls_in_deps_query", ?krate).entered();
268 Arc::from_iter(
269 db.transitive_deps(krate).into_iter().map(|krate| db.trait_impls_in_crate(krate)),
270 )
271 }
272
273 fn finish(map: TraitFpMapCollector) -> TraitImpls {
274 TraitImpls {
275 map: map
276 .into_iter()
277 .map(|(k, v)| (k, v.into_iter().map(|(k, v)| (k, v.into_boxed_slice())).collect()))
278 .collect(),
279 }
280 }
281
282 fn collect_def_map(db: &dyn HirDatabase, map: &mut TraitFpMapCollector, def_map: &DefMap) {
283 for (_module_id, module_data) in def_map.modules() {
284 for impl_id in module_data.scope.impls() {
285 if db.attrs(impl_id.into()).by_key(sym::rustc_reservation_impl).exists() {
292 continue;
293 }
294 let target_trait = match db.impl_trait(impl_id) {
295 Some(tr) => tr.skip_binders().hir_trait_id(),
296 None => continue,
297 };
298 let self_ty = db.impl_self_ty(impl_id);
299 let self_ty_fp = TyFingerprint::for_trait_impl(self_ty.skip_binders());
300 map.entry(target_trait).or_default().entry(self_ty_fp).or_default().push(impl_id);
301 }
302
303 for konst in module_data.scope.unnamed_consts() {
306 let body = db.body(konst.into());
307 for (_, block_def_map) in body.blocks(db) {
308 Self::collect_def_map(db, map, block_def_map);
309 }
310 }
311 }
312 }
313
314 pub fn for_self_ty_without_blanket_impls(
316 &self,
317 fp: TyFingerprint,
318 ) -> impl Iterator<Item = ImplId> + '_ {
319 self.map
320 .values()
321 .flat_map(move |impls| impls.get(&Some(fp)).into_iter())
322 .flat_map(|it| it.iter().copied())
323 }
324
325 pub fn for_trait(&self, trait_: TraitId) -> impl Iterator<Item = ImplId> + '_ {
327 self.map
328 .get(&trait_)
329 .into_iter()
330 .flat_map(|map| map.values().flat_map(|v| v.iter().copied()))
331 }
332
333 pub fn for_trait_and_self_ty(
335 &self,
336 trait_: TraitId,
337 self_ty: TyFingerprint,
338 ) -> impl Iterator<Item = ImplId> + '_ {
339 self.map
340 .get(&trait_)
341 .into_iter()
342 .flat_map(move |map| map.get(&Some(self_ty)).into_iter().chain(map.get(&None)))
343 .flat_map(|v| v.iter().copied())
344 }
345
346 pub fn has_impls_for_trait_and_self_ty(&self, trait_: TraitId, self_ty: TyFingerprint) -> bool {
348 self.for_trait_and_self_ty(trait_, self_ty).next().is_some()
349 }
350
351 pub fn all_impls(&self) -> impl Iterator<Item = ImplId> + '_ {
352 self.map.values().flat_map(|map| map.values().flat_map(|v| v.iter().copied()))
353 }
354}
355
356#[derive(Debug, Eq, PartialEq)]
364pub struct InherentImpls {
365 map: FxHashMap<TyFingerprint, Vec<ImplId>>,
366 invalid_impls: Vec<ImplId>,
367}
368
369impl InherentImpls {
370 pub(crate) fn inherent_impls_in_crate_query(db: &dyn HirDatabase, krate: Crate) -> Arc<Self> {
371 let _p = tracing::info_span!("inherent_impls_in_crate_query", ?krate).entered();
372 let mut impls = Self { map: FxHashMap::default(), invalid_impls: Vec::default() };
373
374 let crate_def_map = crate_def_map(db, krate);
375 impls.collect_def_map(db, crate_def_map);
376 impls.shrink_to_fit();
377
378 Arc::new(impls)
379 }
380
381 pub(crate) fn inherent_impls_in_block_query(
382 db: &dyn HirDatabase,
383 block: BlockId,
384 ) -> Option<Arc<Self>> {
385 let _p = tracing::info_span!("inherent_impls_in_block_query").entered();
386 let mut impls = Self { map: FxHashMap::default(), invalid_impls: Vec::default() };
387
388 let block_def_map = block_def_map(db, block);
389 impls.collect_def_map(db, block_def_map);
390 impls.shrink_to_fit();
391
392 if impls.map.is_empty() && impls.invalid_impls.is_empty() {
393 None
394 } else {
395 Some(Arc::new(impls))
396 }
397 }
398
399 fn shrink_to_fit(&mut self) {
400 self.map.values_mut().for_each(Vec::shrink_to_fit);
401 self.map.shrink_to_fit();
402 }
403
404 fn collect_def_map(&mut self, db: &dyn HirDatabase, def_map: &DefMap) {
405 for (_module_id, module_data) in def_map.modules() {
406 for impl_id in module_data.scope.impls() {
407 let data = db.impl_signature(impl_id);
408 if data.target_trait.is_some() {
409 continue;
410 }
411
412 let self_ty = db.impl_self_ty(impl_id);
413 let self_ty = self_ty.skip_binders();
414
415 match is_inherent_impl_coherent(db, def_map, impl_id, self_ty) {
416 true => {
417 if let Some(fp) = TyFingerprint::for_inherent_impl(self_ty) {
419 self.map.entry(fp).or_default().push(impl_id);
420 }
421 }
422 false => self.invalid_impls.push(impl_id),
423 }
424 }
425
426 for konst in module_data.scope.unnamed_consts() {
429 let body = db.body(konst.into());
430 for (_, block_def_map) in body.blocks(db) {
431 self.collect_def_map(db, block_def_map);
432 }
433 }
434 }
435 }
436
437 pub fn for_self_ty(&self, self_ty: &Ty) -> &[ImplId] {
438 match TyFingerprint::for_inherent_impl(self_ty) {
439 Some(fp) => self.map.get(&fp).map(|vec| vec.as_ref()).unwrap_or(&[]),
440 None => &[],
441 }
442 }
443
444 pub fn all_impls(&self) -> impl Iterator<Item = ImplId> + '_ {
445 self.map.values().flat_map(|v| v.iter().copied())
446 }
447
448 pub fn invalid_impls(&self) -> &[ImplId] {
449 &self.invalid_impls
450 }
451}
452
453pub(crate) fn incoherent_inherent_impl_crates(
454 db: &dyn HirDatabase,
455 krate: Crate,
456 fp: TyFingerprint,
457) -> SmallVec<[Crate; 2]> {
458 let _p = tracing::info_span!("incoherent_inherent_impl_crates").entered();
459 let mut res = SmallVec::new();
460
461 for krate in db.transitive_deps(krate) {
464 let impls = db.inherent_impls_in_crate(krate);
465 if impls.map.get(&fp).is_some_and(|v| !v.is_empty()) {
466 res.push(krate);
467 }
468 }
469
470 res
471}
472
473pub fn def_crates(db: &dyn HirDatabase, ty: &Ty, cur_crate: Crate) -> Option<SmallVec<[Crate; 2]>> {
474 match ty.kind(Interner) {
475 &TyKind::Adt(AdtId(def_id), _) => {
476 let rustc_has_incoherent_inherent_impls = match def_id {
477 hir_def::AdtId::StructId(id) => db
478 .struct_signature(id)
479 .flags
480 .contains(StructFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS),
481 hir_def::AdtId::UnionId(id) => db
482 .union_signature(id)
483 .flags
484 .contains(StructFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS),
485 hir_def::AdtId::EnumId(id) => db
486 .enum_signature(id)
487 .flags
488 .contains(EnumFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS),
489 };
490 Some(if rustc_has_incoherent_inherent_impls {
491 db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::Adt(def_id))
492 } else {
493 smallvec![def_id.module(db).krate()]
494 })
495 }
496 &TyKind::Foreign(id) => {
497 let alias = from_foreign_def_id(id);
498 Some(
499 if db
500 .type_alias_signature(alias)
501 .flags
502 .contains(TypeAliasFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPL)
503 {
504 db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::ForeignType(id))
505 } else {
506 smallvec![alias.module(db).krate()]
507 },
508 )
509 }
510 TyKind::Dyn(_) => {
511 let trait_id = ty.dyn_trait()?;
512 Some(
513 if db
514 .trait_signature(trait_id)
515 .flags
516 .contains(TraitFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS)
517 {
518 db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::Dyn(trait_id))
519 } else {
520 smallvec![trait_id.module(db).krate()]
521 },
522 )
523 }
524 TyKind::Scalar(_)
528 | TyKind::Str
529 | TyKind::Slice(_)
530 | TyKind::Array(..)
531 | TyKind::Raw(..) => Some(db.incoherent_inherent_impl_crates(
532 cur_crate,
533 TyFingerprint::for_inherent_impl(ty).expect("fingerprint for primitive"),
534 )),
535 _ => None,
536 }
537}
538
539pub(crate) fn lookup_method(
541 db: &dyn HirDatabase,
542 ty: &Canonical<Ty>,
543 env: Arc<TraitEnvironment>,
544 traits_in_scope: &FxHashSet<TraitId>,
545 visible_from_module: VisibleFromModule,
546 name: &Name,
547) -> Option<(ReceiverAdjustments, FunctionId, bool)> {
548 let mut not_visible = None;
549 let res = iterate_method_candidates(
550 ty,
551 db,
552 env,
553 traits_in_scope,
554 visible_from_module,
555 Some(name),
556 LookupMode::MethodCall,
557 |adjustments, f, visible| match f {
558 AssocItemId::FunctionId(f) if visible => Some((adjustments, f, true)),
559 AssocItemId::FunctionId(f) if not_visible.is_none() => {
560 not_visible = Some((adjustments, f, false));
561 None
562 }
563 _ => None,
564 },
565 );
566 res.or(not_visible)
567}
568
569#[derive(Copy, Clone, Debug, PartialEq, Eq)]
572pub enum LookupMode {
573 MethodCall,
576 Path,
579}
580
581#[derive(Clone, Copy)]
582pub enum VisibleFromModule {
583 Filter(ModuleId),
585 IncludeBlock(BlockId),
587 None,
589}
590
591impl From<Option<ModuleId>> for VisibleFromModule {
592 fn from(module: Option<ModuleId>) -> Self {
593 match module {
594 Some(module) => Self::Filter(module),
595 None => Self::None,
596 }
597 }
598}
599
600impl From<Option<BlockId>> for VisibleFromModule {
601 fn from(block: Option<BlockId>) -> Self {
602 match block {
603 Some(block) => Self::IncludeBlock(block),
604 None => Self::None,
605 }
606 }
607}
608
609#[derive(Debug, Clone)]
610pub enum AutorefOrPtrAdjustment {
611 Autoref(Mutability),
612 ToConstPtr,
613}
614
615#[derive(Debug, Clone, Default)]
616pub struct ReceiverAdjustments {
617 autoref: Option<AutorefOrPtrAdjustment>,
618 autoderefs: usize,
619 unsize_array: bool,
620}
621
622impl ReceiverAdjustments {
623 pub(crate) fn apply(&self, table: &mut InferenceTable<'_>, ty: Ty) -> (Ty, Vec<Adjustment>) {
624 let mut ty = table.resolve_ty_shallow(&ty);
625 let mut adjust = Vec::new();
626 for _ in 0..self.autoderefs {
627 match autoderef::autoderef_step(table, ty.clone(), true, false) {
628 None => {
629 never!("autoderef not possible for {:?}", ty);
630 ty = TyKind::Error.intern(Interner);
631 break;
632 }
633 Some((kind, new_ty)) => {
634 ty = new_ty.clone();
635 let mutbl = match self.autoref {
636 Some(AutorefOrPtrAdjustment::Autoref(m)) => Some(m),
637 Some(AutorefOrPtrAdjustment::ToConstPtr) => Some(Mutability::Not),
638 None => None,
640 };
641 adjust.push(Adjustment {
642 kind: Adjust::Deref(match kind {
643 AutoderefKind::Overloaded => Some(OverloadedDeref(mutbl)),
644 AutoderefKind::Builtin => None,
645 }),
646 target: new_ty,
647 });
648 }
649 }
650 }
651 if let Some(autoref) = &self.autoref {
652 let lt = table.new_lifetime_var();
653 match autoref {
654 AutorefOrPtrAdjustment::Autoref(m) => {
655 let a = Adjustment::borrow(*m, ty, lt);
656 ty = a.target.clone();
657 adjust.push(a);
658 }
659 AutorefOrPtrAdjustment::ToConstPtr => {
660 if let TyKind::Raw(Mutability::Mut, pointee) = ty.kind(Interner) {
661 let a = Adjustment {
662 kind: Adjust::Pointer(PointerCast::MutToConstPointer),
663 target: TyKind::Raw(Mutability::Not, pointee.clone()).intern(Interner),
664 };
665 ty = a.target.clone();
666 adjust.push(a);
667 } else {
668 never!("`ToConstPtr` target is not a raw mutable pointer");
669 }
670 }
671 };
672 }
673 if self.unsize_array {
674 ty = 'it: {
675 if let TyKind::Ref(m, l, inner) = ty.kind(Interner)
676 && let TyKind::Array(inner, _) = inner.kind(Interner)
677 {
678 break 'it TyKind::Ref(
679 *m,
680 l.clone(),
681 TyKind::Slice(inner.clone()).intern(Interner),
682 )
683 .intern(Interner);
684 }
685 ty
687 };
688 adjust.push(Adjustment {
689 kind: Adjust::Pointer(PointerCast::Unsize),
690 target: ty.clone(),
691 });
692 }
693 (ty, adjust)
694 }
695
696 fn with_autoref(&self, a: AutorefOrPtrAdjustment) -> ReceiverAdjustments {
697 Self { autoref: Some(a), ..*self }
698 }
699}
700
701pub(crate) fn iterate_method_candidates<T>(
705 ty: &Canonical<Ty>,
706 db: &dyn HirDatabase,
707 env: Arc<TraitEnvironment>,
708 traits_in_scope: &FxHashSet<TraitId>,
709 visible_from_module: VisibleFromModule,
710 name: Option<&Name>,
711 mode: LookupMode,
712 mut callback: impl FnMut(ReceiverAdjustments, AssocItemId, bool) -> Option<T>,
713) -> Option<T> {
714 let mut slot = None;
715 _ = iterate_method_candidates_dyn(
716 ty,
717 db,
718 env,
719 traits_in_scope,
720 visible_from_module,
721 name,
722 mode,
723 &mut |adj, item, visible| {
724 assert!(slot.is_none());
725 if let Some(it) = callback(adj, item, visible) {
726 slot = Some(it);
727 return ControlFlow::Break(());
728 }
729 ControlFlow::Continue(())
730 },
731 );
732 slot
733}
734
735pub fn lookup_impl_const(
736 db: &dyn HirDatabase,
737 env: Arc<TraitEnvironment>,
738 const_id: ConstId,
739 subs: Substitution,
740) -> (ConstId, Substitution) {
741 let trait_id = match const_id.lookup(db).container {
742 ItemContainerId::TraitId(id) => id,
743 _ => return (const_id, subs),
744 };
745 let substitution = Substitution::from_iter(Interner, subs.iter(Interner));
746 let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution };
747
748 let const_signature = db.const_signature(const_id);
749 let name = match const_signature.name.as_ref() {
750 Some(name) => name,
751 None => return (const_id, subs),
752 };
753
754 lookup_impl_assoc_item_for_trait_ref(trait_ref, db, env, name)
755 .and_then(
756 |assoc| if let (AssocItemId::ConstId(id), s) = assoc { Some((id, s)) } else { None },
757 )
758 .unwrap_or((const_id, subs))
759}
760
761pub fn is_dyn_method(
764 db: &dyn HirDatabase,
765 _env: Arc<TraitEnvironment>,
766 func: FunctionId,
767 fn_subst: Substitution,
768) -> Option<usize> {
769 let ItemContainerId::TraitId(trait_id) = func.lookup(db).container else {
770 return None;
771 };
772 let trait_params = db.generic_params(trait_id.into()).len();
773 let fn_params = fn_subst.len(Interner) - trait_params;
774 let trait_ref = TraitRef {
775 trait_id: to_chalk_trait_id(trait_id),
776 substitution: Substitution::from_iter(Interner, fn_subst.iter(Interner).take(trait_params)),
777 };
778 let self_ty = trait_ref.self_type_parameter(Interner);
779 if let TyKind::Dyn(d) = self_ty.kind(Interner) {
780 let is_my_trait_in_bounds = d
781 .bounds
782 .skip_binders()
783 .as_slice(Interner)
784 .iter()
785 .map(|it| it.skip_binders())
786 .flat_map(|it| match it {
787 WhereClause::Implemented(tr) => {
788 all_super_traits(db, from_chalk_trait_id(tr.trait_id))
789 }
790 _ => smallvec![],
791 })
792 .any(|x| x == trait_id);
795 if is_my_trait_in_bounds {
796 return Some(fn_params);
797 }
798 }
799 None
800}
801
802pub(crate) fn lookup_impl_method_query(
806 db: &dyn HirDatabase,
807 env: Arc<TraitEnvironment>,
808 func: FunctionId,
809 fn_subst: Substitution,
810) -> (FunctionId, Substitution) {
811 let ItemContainerId::TraitId(trait_id) = func.lookup(db).container else {
812 return (func, fn_subst);
813 };
814 let trait_params = db.generic_params(trait_id.into()).len();
815 let trait_ref = TraitRef {
816 trait_id: to_chalk_trait_id(trait_id),
817 substitution: Substitution::from_iter(Interner, fn_subst.iter(Interner).take(trait_params)),
818 };
819
820 let name = &db.function_signature(func).name;
821 let Some((impl_fn, impl_subst)) =
822 lookup_impl_assoc_item_for_trait_ref(trait_ref, db, env, name).and_then(|assoc| {
823 if let (AssocItemId::FunctionId(id), subst) = assoc { Some((id, subst)) } else { None }
824 })
825 else {
826 return (func, fn_subst);
827 };
828
829 (
830 impl_fn,
831 Substitution::from_iter(
832 Interner,
833 impl_subst.iter(Interner).chain(fn_subst.iter(Interner).skip(trait_params)),
834 ),
835 )
836}
837
838fn lookup_impl_assoc_item_for_trait_ref(
839 trait_ref: TraitRef,
840 db: &dyn HirDatabase,
841 env: Arc<TraitEnvironment>,
842 name: &Name,
843) -> Option<(AssocItemId, Substitution)> {
844 let hir_trait_id = trait_ref.hir_trait_id();
845 let self_ty = trait_ref.self_type_parameter(Interner);
846 let self_ty_fp = TyFingerprint::for_trait_impl(&self_ty)?;
847 let impls = db.trait_impls_in_deps(env.krate);
848
849 let trait_module = hir_trait_id.module(db);
850 let type_module = match self_ty_fp {
851 TyFingerprint::Adt(adt_id) => Some(adt_id.module(db)),
852 TyFingerprint::ForeignType(type_id) => Some(from_foreign_def_id(type_id).module(db)),
853 TyFingerprint::Dyn(trait_id) => Some(trait_id.module(db)),
854 _ => None,
855 };
856
857 let def_blocks: ArrayVec<_, 2> =
858 [trait_module.containing_block(), type_module.and_then(|it| it.containing_block())]
859 .into_iter()
860 .flatten()
861 .filter_map(|block_id| db.trait_impls_in_block(block_id))
862 .collect();
863
864 let impls = impls
865 .iter()
866 .chain(&def_blocks)
867 .flat_map(|impls| impls.for_trait_and_self_ty(hir_trait_id, self_ty_fp));
868
869 let table = InferenceTable::new(db, env);
870
871 let (impl_data, impl_subst) = find_matching_impl(impls, table, trait_ref)?;
872 let item = impl_data.items.iter().find_map(|(n, it)| match *it {
873 AssocItemId::FunctionId(f) => (n == name).then_some(AssocItemId::FunctionId(f)),
874 AssocItemId::ConstId(c) => (n == name).then_some(AssocItemId::ConstId(c)),
875 AssocItemId::TypeAliasId(_) => None,
876 })?;
877 Some((item, impl_subst))
878}
879
880fn find_matching_impl(
881 mut impls: impl Iterator<Item = ImplId>,
882 mut table: InferenceTable<'_>,
883 actual_trait_ref: TraitRef,
884) -> Option<(&ImplItems, Substitution)> {
885 let db = table.db;
886 impls.find_map(|impl_| {
887 table.run_in_snapshot(|table| {
888 let impl_substs =
889 TyBuilder::subst_for_def(db, impl_, None).fill_with_inference_vars(table).build();
890 let trait_ref = db
891 .impl_trait(impl_)
892 .expect("non-trait method in find_matching_impl")
893 .substitute(Interner, &impl_substs);
894
895 if !table.unify(&trait_ref, &actual_trait_ref) {
896 return None;
897 }
898
899 let wcs = crate::chalk_db::convert_where_clauses(db, impl_.into(), &impl_substs)
900 .into_iter()
901 .map(|b| -> Goal { b.cast(Interner) });
902 for goal in wcs {
903 if table.try_obligation(goal.clone()).no_solution() {
904 return None;
905 }
906 table.register_obligation(goal);
907 }
908 Some((impl_.impl_items(db), table.resolve_completely(impl_substs)))
909 })
910 })
911}
912
913fn is_inherent_impl_coherent(
914 db: &dyn HirDatabase,
915 def_map: &DefMap,
916 impl_id: ImplId,
917 self_ty: &Ty,
918) -> bool {
919 let self_ty = self_ty.kind(Interner);
920 let impl_allowed = match self_ty {
921 TyKind::Tuple(_, _)
922 | TyKind::FnDef(_, _)
923 | TyKind::Array(_, _)
924 | TyKind::Never
925 | TyKind::Raw(_, _)
926 | TyKind::Ref(_, _, _)
927 | TyKind::Slice(_)
928 | TyKind::Str
929 | TyKind::Scalar(_) => def_map.is_rustc_coherence_is_core(),
930
931 &TyKind::Adt(AdtId(adt), _) => adt.module(db).krate() == def_map.krate(),
932 TyKind::Dyn(it) => it.principal_id().is_some_and(|trait_id| {
933 from_chalk_trait_id(trait_id).module(db).krate() == def_map.krate()
934 }),
935
936 _ => true,
937 };
938 impl_allowed || {
939 let rustc_has_incoherent_inherent_impls = match self_ty {
940 TyKind::Tuple(_, _)
941 | TyKind::FnDef(_, _)
942 | TyKind::Array(_, _)
943 | TyKind::Never
944 | TyKind::Raw(_, _)
945 | TyKind::Ref(_, _, _)
946 | TyKind::Slice(_)
947 | TyKind::Str
948 | TyKind::Scalar(_) => true,
949
950 &TyKind::Adt(AdtId(adt), _) => match adt {
951 hir_def::AdtId::StructId(id) => db
952 .struct_signature(id)
953 .flags
954 .contains(StructFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS),
955 hir_def::AdtId::UnionId(id) => db
956 .union_signature(id)
957 .flags
958 .contains(StructFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS),
959 hir_def::AdtId::EnumId(it) => db
960 .enum_signature(it)
961 .flags
962 .contains(EnumFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS),
963 },
964 TyKind::Dyn(it) => it.principal_id().is_some_and(|trait_id| {
965 db.trait_signature(from_chalk_trait_id(trait_id))
966 .flags
967 .contains(TraitFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS)
968 }),
969
970 _ => false,
971 };
972 let items = impl_id.impl_items(db);
973 rustc_has_incoherent_inherent_impls
974 && !items.items.is_empty()
975 && items.items.iter().all(|&(_, assoc)| match assoc {
976 AssocItemId::FunctionId(it) => {
977 db.function_signature(it).flags.contains(FnFlags::RUSTC_ALLOW_INCOHERENT_IMPL)
978 }
979 AssocItemId::ConstId(it) => {
980 db.const_signature(it).flags.contains(ConstFlags::RUSTC_ALLOW_INCOHERENT_IMPL)
981 }
982 AssocItemId::TypeAliasId(it) => db
983 .type_alias_signature(it)
984 .flags
985 .contains(TypeAliasFlags::RUSTC_ALLOW_INCOHERENT_IMPL),
986 })
987 }
988}
989
990pub fn check_orphan_rules(db: &dyn HirDatabase, impl_: ImplId) -> bool {
998 let substs = TyBuilder::placeholder_subst(db, impl_);
999 let Some(impl_trait) = db.impl_trait(impl_) else {
1000 return true;
1002 };
1003
1004 let local_crate = impl_.lookup(db).container.krate();
1005 let is_local = |tgt_crate| tgt_crate == local_crate;
1006
1007 let trait_ref = impl_trait.substitute(Interner, &substs);
1008 let trait_id = from_chalk_trait_id(trait_ref.trait_id);
1009 if is_local(trait_id.module(db).krate()) {
1010 return true;
1012 }
1013
1014 let unwrap_fundamental = |mut ty: Ty| {
1015 loop {
1017 match ty.kind(Interner) {
1018 TyKind::Ref(_, _, referenced) => ty = referenced.clone(),
1019 &TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), ref subs) => {
1020 let struct_signature = db.struct_signature(s);
1021 if struct_signature.flags.contains(StructFlags::FUNDAMENTAL) {
1022 let next = subs.type_parameters(Interner).next();
1023 match next {
1024 Some(it) => ty = it,
1025 None => break ty,
1026 }
1027 } else {
1028 break ty;
1029 }
1030 }
1031 _ => break ty,
1032 }
1033 }
1034 };
1035 let is_not_orphan = trait_ref.substitution.type_parameters(Interner).any(|ty| {
1040 match unwrap_fundamental(ty).kind(Interner) {
1041 &TyKind::Adt(AdtId(id), _) => is_local(id.module(db).krate()),
1042 TyKind::Error => true,
1043 TyKind::Dyn(it) => it
1044 .principal_id()
1045 .is_some_and(|trait_id| is_local(from_chalk_trait_id(trait_id).module(db).krate())),
1046 _ => false,
1047 }
1048 });
1049 #[allow(clippy::let_and_return)]
1050 is_not_orphan
1051}
1052
1053pub fn iterate_path_candidates(
1054 ty: &Canonical<Ty>,
1055 db: &dyn HirDatabase,
1056 env: Arc<TraitEnvironment>,
1057 traits_in_scope: &FxHashSet<TraitId>,
1058 visible_from_module: VisibleFromModule,
1059 name: Option<&Name>,
1060 callback: &mut dyn MethodCandidateCallback,
1061) -> ControlFlow<()> {
1062 iterate_method_candidates_dyn(
1063 ty,
1064 db,
1065 env,
1066 traits_in_scope,
1067 visible_from_module,
1068 name,
1069 LookupMode::Path,
1070 callback,
1072 )
1073}
1074
1075pub fn iterate_method_candidates_dyn(
1076 ty: &Canonical<Ty>,
1077 db: &dyn HirDatabase,
1078 env: Arc<TraitEnvironment>,
1079 traits_in_scope: &FxHashSet<TraitId>,
1080 visible_from_module: VisibleFromModule,
1081 name: Option<&Name>,
1082 mode: LookupMode,
1083 callback: &mut dyn MethodCandidateCallback,
1084) -> ControlFlow<()> {
1085 let _p = tracing::info_span!(
1086 "iterate_method_candidates_dyn",
1087 ?mode,
1088 ?name,
1089 traits_in_scope_len = traits_in_scope.len()
1090 )
1091 .entered();
1092
1093 match mode {
1094 LookupMode::MethodCall => {
1095 let mut table = InferenceTable::new(db, env);
1115 let ty = table.instantiate_canonical(ty.clone());
1116 let deref_chain = autoderef_method_receiver(&mut table, ty);
1117
1118 deref_chain.into_iter().try_for_each(|(receiver_ty, adj)| {
1119 iterate_method_candidates_with_autoref(
1120 &mut table,
1121 receiver_ty,
1122 adj,
1123 traits_in_scope,
1124 visible_from_module,
1125 name,
1126 callback,
1127 )
1128 })
1129 }
1130 LookupMode::Path => {
1131 iterate_method_candidates_for_self_ty(
1133 ty,
1134 db,
1135 env,
1136 traits_in_scope,
1137 visible_from_module,
1138 name,
1139 callback,
1140 )
1141 }
1142 }
1143}
1144
1145#[tracing::instrument(skip_all, fields(name = ?name))]
1146fn iterate_method_candidates_with_autoref(
1147 table: &mut InferenceTable<'_>,
1148 receiver_ty: Canonical<Ty>,
1149 first_adjustment: ReceiverAdjustments,
1150 traits_in_scope: &FxHashSet<TraitId>,
1151 visible_from_module: VisibleFromModule,
1152 name: Option<&Name>,
1153 callback: &mut dyn MethodCandidateCallback,
1154) -> ControlFlow<()> {
1155 if receiver_ty.value.is_general_var(Interner, &receiver_ty.binders) {
1156 return ControlFlow::Continue(());
1158 }
1159
1160 let mut iterate_method_candidates_by_receiver = move |receiver_ty, first_adjustment| {
1161 iterate_method_candidates_by_receiver(
1162 table,
1163 receiver_ty,
1164 first_adjustment,
1165 traits_in_scope,
1166 visible_from_module,
1167 name,
1168 callback,
1169 )
1170 };
1171
1172 let mut maybe_reborrowed = first_adjustment.clone();
1173 if let Some((_, _, m)) = receiver_ty.value.as_reference() {
1174 maybe_reborrowed.autoref = Some(AutorefOrPtrAdjustment::Autoref(m));
1176 maybe_reborrowed.autoderefs += 1;
1177 }
1178
1179 iterate_method_candidates_by_receiver(receiver_ty.clone(), maybe_reborrowed)?;
1180
1181 let refed = Canonical {
1182 value: TyKind::Ref(Mutability::Not, error_lifetime(), receiver_ty.value.clone())
1183 .intern(Interner),
1184 binders: receiver_ty.binders.clone(),
1185 };
1186
1187 iterate_method_candidates_by_receiver(
1188 refed,
1189 first_adjustment.with_autoref(AutorefOrPtrAdjustment::Autoref(Mutability::Not)),
1190 )?;
1191
1192 let ref_muted = Canonical {
1193 value: TyKind::Ref(Mutability::Mut, error_lifetime(), receiver_ty.value.clone())
1194 .intern(Interner),
1195 binders: receiver_ty.binders.clone(),
1196 };
1197
1198 iterate_method_candidates_by_receiver(
1199 ref_muted,
1200 first_adjustment.with_autoref(AutorefOrPtrAdjustment::Autoref(Mutability::Mut)),
1201 )?;
1202
1203 if let Some((ty, Mutability::Mut)) = receiver_ty.value.as_raw_ptr() {
1204 let const_ptr_ty = Canonical {
1205 value: TyKind::Raw(Mutability::Not, ty.clone()).intern(Interner),
1206 binders: receiver_ty.binders,
1207 };
1208 iterate_method_candidates_by_receiver(
1209 const_ptr_ty,
1210 first_adjustment.with_autoref(AutorefOrPtrAdjustment::ToConstPtr),
1211 )?;
1212 }
1213
1214 ControlFlow::Continue(())
1215}
1216
1217pub trait MethodCandidateCallback {
1218 fn on_inherent_method(
1219 &mut self,
1220 adjustments: ReceiverAdjustments,
1221 item: AssocItemId,
1222 is_visible: bool,
1223 ) -> ControlFlow<()>;
1224
1225 fn on_trait_method(
1226 &mut self,
1227 adjustments: ReceiverAdjustments,
1228 item: AssocItemId,
1229 is_visible: bool,
1230 ) -> ControlFlow<()>;
1231}
1232
1233impl<F> MethodCandidateCallback for F
1234where
1235 F: FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
1236{
1237 fn on_inherent_method(
1238 &mut self,
1239 adjustments: ReceiverAdjustments,
1240 item: AssocItemId,
1241 is_visible: bool,
1242 ) -> ControlFlow<()> {
1243 self(adjustments, item, is_visible)
1244 }
1245
1246 fn on_trait_method(
1247 &mut self,
1248 adjustments: ReceiverAdjustments,
1249 item: AssocItemId,
1250 is_visible: bool,
1251 ) -> ControlFlow<()> {
1252 self(adjustments, item, is_visible)
1253 }
1254}
1255
1256#[tracing::instrument(skip_all, fields(name = ?name))]
1257fn iterate_method_candidates_by_receiver(
1258 table: &mut InferenceTable<'_>,
1259 receiver_ty: Canonical<Ty>,
1260 receiver_adjustments: ReceiverAdjustments,
1261 traits_in_scope: &FxHashSet<TraitId>,
1262 visible_from_module: VisibleFromModule,
1263 name: Option<&Name>,
1264 callback: &mut dyn MethodCandidateCallback,
1265) -> ControlFlow<()> {
1266 let receiver_ty = table.instantiate_canonical(receiver_ty);
1267 table.run_in_snapshot(|table| {
1271 let mut autoderef =
1272 autoderef::Autoderef::new_no_tracking(table, receiver_ty.clone(), true, true);
1273 while let Some((self_ty, _)) = autoderef.next() {
1274 iterate_inherent_methods(
1275 &self_ty,
1276 autoderef.table,
1277 name,
1278 Some(&receiver_ty),
1279 Some(receiver_adjustments.clone()),
1280 visible_from_module,
1281 &mut |adjustments, item, is_visible| {
1282 callback.on_inherent_method(adjustments, item, is_visible)
1283 },
1284 )?
1285 }
1286 ControlFlow::Continue(())
1287 })?;
1288 table.run_in_snapshot(|table| {
1289 let mut autoderef =
1290 autoderef::Autoderef::new_no_tracking(table, receiver_ty.clone(), true, true);
1291 while let Some((self_ty, _)) = autoderef.next() {
1292 if matches!(self_ty.kind(Interner), TyKind::InferenceVar(_, TyVariableKind::General)) {
1293 return ControlFlow::Continue(());
1295 }
1296
1297 iterate_trait_method_candidates(
1298 &self_ty,
1299 autoderef.table,
1300 traits_in_scope,
1301 name,
1302 Some(&receiver_ty),
1303 Some(receiver_adjustments.clone()),
1304 &mut |adjustments, item, is_visible| {
1305 callback.on_trait_method(adjustments, item, is_visible)
1306 },
1307 )?
1308 }
1309 ControlFlow::Continue(())
1310 })
1311}
1312
1313#[tracing::instrument(skip_all, fields(name = ?name))]
1314fn iterate_method_candidates_for_self_ty(
1315 self_ty: &Canonical<Ty>,
1316 db: &dyn HirDatabase,
1317 env: Arc<TraitEnvironment>,
1318 traits_in_scope: &FxHashSet<TraitId>,
1319 visible_from_module: VisibleFromModule,
1320 name: Option<&Name>,
1321 callback: &mut dyn MethodCandidateCallback,
1322) -> ControlFlow<()> {
1323 let mut table = InferenceTable::new(db, env);
1324 let self_ty = table.instantiate_canonical(self_ty.clone());
1325 iterate_inherent_methods(
1326 &self_ty,
1327 &mut table,
1328 name,
1329 None,
1330 None,
1331 visible_from_module,
1332 &mut |adjustments, item, is_visible| {
1333 callback.on_inherent_method(adjustments, item, is_visible)
1334 },
1335 )?;
1336 iterate_trait_method_candidates(
1337 &self_ty,
1338 &mut table,
1339 traits_in_scope,
1340 name,
1341 None,
1342 None,
1343 &mut |adjustments, item, is_visible| {
1344 callback.on_trait_method(adjustments, item, is_visible)
1345 },
1346 )
1347}
1348
1349#[tracing::instrument(skip_all, fields(name = ?name, visible_from_module, receiver_ty))]
1350fn iterate_trait_method_candidates(
1351 self_ty: &Ty,
1352 table: &mut InferenceTable<'_>,
1353 traits_in_scope: &FxHashSet<TraitId>,
1354 name: Option<&Name>,
1355 receiver_ty: Option<&Ty>,
1356 receiver_adjustments: Option<ReceiverAdjustments>,
1357 callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
1358) -> ControlFlow<()> {
1359 let db = table.db;
1360
1361 let canonical_self_ty = table.canonicalize(self_ty.clone());
1362 let TraitEnvironment { krate, block, .. } = *table.trait_env;
1363
1364 'traits: for &t in traits_in_scope {
1365 let data = db.trait_signature(t);
1366
1367 if data.flags.contains(TraitFlags::SKIP_ARRAY_DURING_METHOD_DISPATCH)
1373 && matches!(self_ty.kind(Interner), TyKind::Array(..))
1374 {
1375 if !krate.data(db).edition.at_least_2021() {
1378 continue;
1379 }
1380 }
1381 if data.flags.contains(TraitFlags::SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH)
1382 && matches!(
1383 self_ty.kind(Interner), TyKind::Adt(AdtId(def), subst)
1384 if is_box(table.db, *def)
1385 && matches!(subst.at(Interner, 0).assert_ty_ref(Interner).kind(Interner), TyKind::Slice(..))
1386 )
1387 {
1388 if !krate.data(db).edition.at_least_2024() {
1391 continue;
1392 }
1393 }
1394
1395 let mut known_implemented = false;
1399 for &(_, item) in t.trait_items(db).items.iter() {
1400 let visible =
1403 match is_valid_trait_method_candidate(table, t, name, receiver_ty, item, self_ty) {
1404 IsValidCandidate::Yes => true,
1405 IsValidCandidate::NotVisible => false,
1406 IsValidCandidate::No => continue,
1407 };
1408 if !known_implemented {
1409 let goal = generic_implements_goal(db, &table.trait_env, t, &canonical_self_ty);
1410 if db.trait_solve(krate, block, goal.cast(Interner)).no_solution() {
1411 continue 'traits;
1412 }
1413 }
1414 known_implemented = true;
1415 callback(receiver_adjustments.clone().unwrap_or_default(), item, visible)?;
1416 }
1417 }
1418 ControlFlow::Continue(())
1419}
1420
1421#[tracing::instrument(skip_all, fields(name = ?name, visible_from_module, receiver_ty))]
1422fn iterate_inherent_methods(
1423 self_ty: &Ty,
1424 table: &mut InferenceTable<'_>,
1425 name: Option<&Name>,
1426 receiver_ty: Option<&Ty>,
1427 receiver_adjustments: Option<ReceiverAdjustments>,
1428 visible_from_module: VisibleFromModule,
1429 callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
1430) -> ControlFlow<()> {
1431 let db = table.db;
1432 let env = table.trait_env.clone();
1433
1434 match self_ty.kind(Interner) {
1439 TyKind::Placeholder(_) => {
1440 let env = table.trait_env.clone();
1441 let traits = env
1442 .traits_in_scope_from_clauses(self_ty.clone())
1443 .flat_map(|t| all_super_traits(db, t));
1444 iterate_inherent_trait_methods(
1445 self_ty,
1446 table,
1447 name,
1448 receiver_ty,
1449 receiver_adjustments.clone(),
1450 callback,
1451 traits,
1452 )?;
1453 }
1454 TyKind::Dyn(_) => {
1455 if let Some(principal_trait) = self_ty.dyn_trait() {
1456 let traits = all_super_traits(db, principal_trait);
1457 iterate_inherent_trait_methods(
1458 self_ty,
1459 table,
1460 name,
1461 receiver_ty,
1462 receiver_adjustments.clone(),
1463 callback,
1464 traits.into_iter(),
1465 )?;
1466 }
1467 }
1468 _ => {}
1469 }
1470
1471 let def_crates = match def_crates(db, self_ty, env.krate) {
1472 Some(k) => k,
1473 None => return ControlFlow::Continue(()),
1474 };
1475
1476 let (module, mut block) = match visible_from_module {
1477 VisibleFromModule::Filter(module) => (Some(module), module.containing_block()),
1478 VisibleFromModule::IncludeBlock(block) => (None, Some(block)),
1479 VisibleFromModule::None => (None, None),
1480 };
1481
1482 while let Some(block_id) = block {
1483 if let Some(impls) = db.inherent_impls_in_block(block_id) {
1484 impls_for_self_ty(
1485 &impls,
1486 self_ty,
1487 table,
1488 name,
1489 receiver_ty,
1490 receiver_adjustments.clone(),
1491 module,
1492 callback,
1493 )?;
1494 }
1495
1496 block = block_def_map(db, block_id).parent().and_then(|module| module.containing_block());
1497 }
1498
1499 for krate in def_crates {
1500 let impls = db.inherent_impls_in_crate(krate);
1501 impls_for_self_ty(
1502 &impls,
1503 self_ty,
1504 table,
1505 name,
1506 receiver_ty,
1507 receiver_adjustments.clone(),
1508 module,
1509 callback,
1510 )?;
1511 }
1512 return ControlFlow::Continue(());
1513
1514 #[tracing::instrument(skip_all, fields(name = ?name, visible_from_module, receiver_ty))]
1515 fn iterate_inherent_trait_methods(
1516 self_ty: &Ty,
1517 table: &mut InferenceTable<'_>,
1518 name: Option<&Name>,
1519 receiver_ty: Option<&Ty>,
1520 receiver_adjustments: Option<ReceiverAdjustments>,
1521 callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
1522 traits: impl Iterator<Item = TraitId>,
1523 ) -> ControlFlow<()> {
1524 let db = table.db;
1525 for t in traits {
1526 let data = t.trait_items(db);
1527 for &(_, item) in data.items.iter() {
1528 let visible = match is_valid_trait_method_candidate(
1530 table,
1531 t,
1532 name,
1533 receiver_ty,
1534 item,
1535 self_ty,
1536 ) {
1537 IsValidCandidate::Yes => true,
1538 IsValidCandidate::NotVisible => false,
1539 IsValidCandidate::No => continue,
1540 };
1541 callback(receiver_adjustments.clone().unwrap_or_default(), item, visible)?;
1542 }
1543 }
1544 ControlFlow::Continue(())
1545 }
1546
1547 #[tracing::instrument(skip_all, fields(name = ?name, visible_from_module, receiver_ty))]
1548 fn impls_for_self_ty(
1549 impls: &InherentImpls,
1550 self_ty: &Ty,
1551 table: &mut InferenceTable<'_>,
1552 name: Option<&Name>,
1553 receiver_ty: Option<&Ty>,
1554 receiver_adjustments: Option<ReceiverAdjustments>,
1555 visible_from_module: Option<ModuleId>,
1556 callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
1557 ) -> ControlFlow<()> {
1558 for &impl_id in impls.for_self_ty(self_ty) {
1559 for &(ref item_name, item) in impl_id.impl_items(table.db).items.iter() {
1560 let visible = match is_valid_impl_method_candidate(
1561 table,
1562 self_ty,
1563 receiver_ty,
1564 visible_from_module,
1565 name,
1566 impl_id,
1567 item,
1568 item_name,
1569 ) {
1570 IsValidCandidate::Yes => true,
1571 IsValidCandidate::NotVisible => false,
1572 IsValidCandidate::No => continue,
1573 };
1574 callback(receiver_adjustments.clone().unwrap_or_default(), item, visible)?;
1575 }
1576 }
1577 ControlFlow::Continue(())
1578 }
1579}
1580
1581pub(crate) fn resolve_indexing_op(
1583 db: &dyn HirDatabase,
1584 env: Arc<TraitEnvironment>,
1585 ty: Canonical<Ty>,
1586 index_trait: TraitId,
1587) -> Option<ReceiverAdjustments> {
1588 let mut table = InferenceTable::new(db, env);
1589 let ty = table.instantiate_canonical(ty);
1590 let deref_chain = autoderef_method_receiver(&mut table, ty);
1591 for (ty, adj) in deref_chain {
1592 let goal = generic_implements_goal(db, &table.trait_env, index_trait, &ty);
1593 if !db
1594 .trait_solve(table.trait_env.krate, table.trait_env.block, goal.cast(Interner))
1595 .no_solution()
1596 {
1597 return Some(adj);
1598 }
1599 }
1600 None
1601}
1602
1603macro_rules! check_that {
1605 ($cond:expr) => {
1606 if !$cond {
1607 return IsValidCandidate::No;
1608 }
1609 };
1610}
1611
1612#[derive(Debug)]
1613enum IsValidCandidate {
1614 Yes,
1615 No,
1616 NotVisible,
1617}
1618
1619#[tracing::instrument(skip_all, fields(name))]
1620fn is_valid_impl_method_candidate(
1621 table: &mut InferenceTable<'_>,
1622 self_ty: &Ty,
1623 receiver_ty: Option<&Ty>,
1624 visible_from_module: Option<ModuleId>,
1625 name: Option<&Name>,
1626 impl_id: ImplId,
1627 item: AssocItemId,
1628 item_name: &Name,
1629) -> IsValidCandidate {
1630 match item {
1631 AssocItemId::FunctionId(f) => is_valid_impl_fn_candidate(
1632 table,
1633 impl_id,
1634 f,
1635 name,
1636 receiver_ty,
1637 self_ty,
1638 visible_from_module,
1639 item_name,
1640 ),
1641 AssocItemId::ConstId(c) => {
1642 let db = table.db;
1643 check_that!(receiver_ty.is_none());
1644 check_that!(name.is_none_or(|n| n == item_name));
1645
1646 if let Some(from_module) = visible_from_module
1647 && !db.assoc_visibility(c.into()).is_visible_from(db, from_module)
1648 {
1649 cov_mark::hit!(const_candidate_not_visible);
1650 return IsValidCandidate::NotVisible;
1651 }
1652 let self_ty_matches = table.run_in_snapshot(|table| {
1653 let expected_self_ty =
1654 TyBuilder::impl_self_ty(db, impl_id).fill_with_inference_vars(table).build();
1655 table.unify(&expected_self_ty, self_ty)
1656 });
1657 if !self_ty_matches {
1658 cov_mark::hit!(const_candidate_self_type_mismatch);
1659 return IsValidCandidate::No;
1660 }
1661 IsValidCandidate::Yes
1662 }
1663 _ => IsValidCandidate::No,
1664 }
1665}
1666
1667#[tracing::instrument(skip_all, fields(name))]
1669fn is_valid_trait_method_candidate(
1670 table: &mut InferenceTable<'_>,
1671 trait_id: TraitId,
1672 name: Option<&Name>,
1673 receiver_ty: Option<&Ty>,
1674 item: AssocItemId,
1675 self_ty: &Ty,
1676) -> IsValidCandidate {
1677 let db = table.db;
1678 match item {
1679 AssocItemId::FunctionId(fn_id) => {
1680 let data = db.function_signature(fn_id);
1681
1682 check_that!(name.is_none_or(|n| n == &data.name));
1683
1684 table.run_in_snapshot(|table| {
1685 let impl_subst = TyBuilder::subst_for_def(db, trait_id, None)
1686 .fill_with_inference_vars(table)
1687 .build();
1688 let expect_self_ty = impl_subst.at(Interner, 0).assert_ty_ref(Interner).clone();
1689
1690 check_that!(table.unify(&expect_self_ty, self_ty));
1691
1692 if let Some(receiver_ty) = receiver_ty {
1693 check_that!(data.has_self_param());
1694
1695 let fn_subst = TyBuilder::subst_for_def(db, fn_id, Some(impl_subst))
1696 .fill_with_inference_vars(table)
1697 .build();
1698
1699 let sig = db.callable_item_signature(fn_id.into());
1700 let expected_receiver =
1701 sig.map(|s| s.params()[0].clone()).substitute(Interner, &fn_subst);
1702
1703 check_that!(table.unify(receiver_ty, &expected_receiver));
1704 }
1705
1706 IsValidCandidate::Yes
1707 })
1708 }
1709 AssocItemId::ConstId(c) => {
1710 check_that!(receiver_ty.is_none());
1711 check_that!(name.is_none_or(|n| db.const_signature(c).name.as_ref() == Some(n)));
1712
1713 IsValidCandidate::Yes
1714 }
1715 _ => IsValidCandidate::No,
1716 }
1717}
1718
1719#[tracing::instrument(skip_all, fields(name))]
1720fn is_valid_impl_fn_candidate(
1721 table: &mut InferenceTable<'_>,
1722 impl_id: ImplId,
1723 fn_id: FunctionId,
1724 name: Option<&Name>,
1725 receiver_ty: Option<&Ty>,
1726 self_ty: &Ty,
1727 visible_from_module: Option<ModuleId>,
1728 item_name: &Name,
1729) -> IsValidCandidate {
1730 check_that!(name.is_none_or(|n| n == item_name));
1731
1732 let db = table.db;
1733 let data = db.function_signature(fn_id);
1734
1735 if let Some(from_module) = visible_from_module
1736 && !db.assoc_visibility(fn_id.into()).is_visible_from(db, from_module)
1737 {
1738 cov_mark::hit!(autoderef_candidate_not_visible);
1739 return IsValidCandidate::NotVisible;
1740 }
1741 table.run_in_snapshot(|table| {
1742 let _p = tracing::info_span!("subst_for_def").entered();
1743 let impl_subst =
1744 TyBuilder::subst_for_def(db, impl_id, None).fill_with_inference_vars(table).build();
1745 let expect_self_ty = db.impl_self_ty(impl_id).substitute(Interner, &impl_subst);
1746
1747 check_that!(table.unify(&expect_self_ty, self_ty));
1748
1749 if let Some(receiver_ty) = receiver_ty {
1750 let _p = tracing::info_span!("check_receiver_ty").entered();
1751 check_that!(data.has_self_param());
1752
1753 let fn_subst = TyBuilder::subst_for_def(db, fn_id, Some(impl_subst.clone()))
1754 .fill_with_inference_vars(table)
1755 .build();
1756
1757 let sig = db.callable_item_signature(fn_id.into());
1758 let expected_receiver =
1759 sig.map(|s| s.params()[0].clone()).substitute(Interner, &fn_subst);
1760
1761 check_that!(table.unify(receiver_ty, &expected_receiver));
1762 }
1763
1764 let predicates = db.generic_predicates(impl_id.into());
1767 let goals = predicates.iter().map(|p| {
1768 let (p, b) = p
1769 .clone()
1770 .substitute(Interner, &impl_subst)
1771 .into_value_and_skipped_binders();
1774 stdx::always!(b.len(Interner) == 0);
1775
1776 p.cast::<Goal>(Interner)
1777 });
1778
1779 for goal in goals.clone() {
1780 let in_env = InEnvironment::new(&table.trait_env.env, goal);
1781 let canonicalized = table.canonicalize_with_free_vars(in_env);
1782 let solution = table.db.trait_solve(
1783 table.trait_env.krate,
1784 table.trait_env.block,
1785 canonicalized.value.clone(),
1786 );
1787
1788 match solution {
1789 NextTraitSolveResult::Certain(canonical_subst) => {
1790 canonicalized.apply_solution(
1791 table,
1792 Canonical {
1793 binders: canonical_subst.binders,
1794 value: canonical_subst.value.subst,
1795 },
1796 );
1797 }
1798 NextTraitSolveResult::Uncertain(..) => {}
1799 NextTraitSolveResult::NoSolution => return IsValidCandidate::No,
1800 }
1801 }
1802
1803 for goal in goals {
1804 if table.try_obligation(goal).no_solution() {
1805 return IsValidCandidate::No;
1806 }
1807 }
1808
1809 IsValidCandidate::Yes
1810 })
1811}
1812
1813pub fn implements_trait(
1814 ty: &Canonical<Ty>,
1815 db: &dyn HirDatabase,
1816 env: &TraitEnvironment,
1817 trait_: TraitId,
1818) -> bool {
1819 let goal = generic_implements_goal(db, env, trait_, ty);
1820 !db.trait_solve(env.krate, env.block, goal.cast(Interner)).no_solution()
1821}
1822
1823pub fn implements_trait_unique(
1824 ty: &Canonical<Ty>,
1825 db: &dyn HirDatabase,
1826 env: &TraitEnvironment,
1827 trait_: TraitId,
1828) -> bool {
1829 let goal = generic_implements_goal(db, env, trait_, ty);
1830 db.trait_solve(env.krate, env.block, goal.cast(Interner)).certain()
1831}
1832
1833#[tracing::instrument(skip_all)]
1836fn generic_implements_goal(
1837 db: &dyn HirDatabase,
1838 env: &TraitEnvironment,
1839 trait_: TraitId,
1840 self_ty: &Canonical<Ty>,
1841) -> Canonical<InEnvironment<super::DomainGoal>> {
1842 let binders = self_ty.binders.interned();
1843 let trait_ref = TyBuilder::trait_ref(db, trait_)
1844 .push(self_ty.value.clone())
1845 .fill_with_bound_vars(DebruijnIndex::INNERMOST, binders.len())
1846 .build();
1847
1848 let kinds =
1849 binders.iter().cloned().chain(trait_ref.substitution.iter(Interner).skip(1).map(|it| {
1850 let vk = match it.data(Interner) {
1851 GenericArgData::Ty(_) => VariableKind::Ty(chalk_ir::TyVariableKind::General),
1852 GenericArgData::Lifetime(_) => VariableKind::Lifetime,
1853 GenericArgData::Const(c) => VariableKind::Const(c.data(Interner).ty.clone()),
1854 };
1855 WithKind::new(vk, UniverseIndex::ROOT)
1856 }));
1857 let binders = CanonicalVarKinds::from_iter(Interner, kinds);
1858
1859 let obligation = trait_ref.cast(Interner);
1860 let value = InEnvironment::new(&env.env, obligation);
1861 Canonical { binders, value }
1862}
1863
1864fn autoderef_method_receiver(
1865 table: &mut InferenceTable<'_>,
1866 ty: Ty,
1867) -> Vec<(Canonical<Ty>, ReceiverAdjustments)> {
1868 let mut deref_chain: Vec<_> = Vec::new();
1869 let mut autoderef = autoderef::Autoderef::new_no_tracking(table, ty, false, true);
1870 while let Some((ty, derefs)) = autoderef.next() {
1871 deref_chain.push((
1872 autoderef.table.canonicalize(ty),
1873 ReceiverAdjustments { autoref: None, autoderefs: derefs, unsize_array: false },
1874 ));
1875 }
1876 if let Some((TyKind::Array(parameters, _), binders, adj)) =
1878 deref_chain.last().map(|(ty, adj)| (ty.value.kind(Interner), ty.binders.clone(), adj))
1879 {
1880 let unsized_ty = TyKind::Slice(parameters.clone()).intern(Interner);
1881 deref_chain.push((
1882 Canonical { value: unsized_ty, binders },
1883 ReceiverAdjustments { unsize_array: true, ..adj.clone() },
1884 ));
1885 }
1886 deref_chain
1887}