1 //! This module is concerned with finding methods that a given type provides.
2 //! For details about how this works in rustc, see the method lookup page in the
3 //! [rustc guide](https://rust-lang.github.io/rustc-guide/method-lookup.html)
4 //! and the corresponding code mostly in rustc_hir_analysis/check/method/probe.rs.
5 use std::ops::ControlFlow;
6
7 use base_db::{CrateId, Edition};
8 use chalk_ir::{cast::Cast, Mutability, TyKind, UniverseIndex, WhereClause};
9 use hir_def::{
10 data::{adt::StructFlags, ImplData},
11 item_scope::ItemScope,
12 nameres::DefMap,
13 AssocItemId, BlockId, ConstId, FunctionId, HasModule, ImplId, ItemContainerId, Lookup,
14 ModuleDefId, ModuleId, TraitId,
15 };
16 use hir_expand::name::Name;
17 use rustc_hash::{FxHashMap, FxHashSet};
18 use smallvec::{smallvec, SmallVec};
19 use stdx::never;
20 use triomphe::Arc;
21
22 use crate::{
23 autoderef::{self, AutoderefKind},
24 db::HirDatabase,
25 from_chalk_trait_id, from_foreign_def_id,
26 infer::{unify::InferenceTable, Adjust, Adjustment, OverloadedDeref, PointerCast},
27 primitive::{FloatTy, IntTy, UintTy},
28 static_lifetime, to_chalk_trait_id,
29 utils::all_super_traits,
30 AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, InEnvironment,
31 Interner, Scalar, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt,
32 };
33
34 /// This is used as a key for indexing impls.
35 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
36 pub enum TyFingerprint {
37 // These are lang item impls:
38 Str,
39 Slice,
40 Array,
41 Never,
42 RawPtr(Mutability),
43 Scalar(Scalar),
44 // These can have user-defined impls:
45 Adt(hir_def::AdtId),
46 Dyn(TraitId),
47 ForeignType(ForeignDefId),
48 // These only exist for trait impls
49 Unit,
50 Unnameable,
51 Function(u32),
52 }
53
54 impl TyFingerprint {
55 /// Creates a TyFingerprint for looking up an inherent impl. Only certain
56 /// types can have inherent impls: if we have some `struct S`, we can have
57 /// an `impl S`, but not `impl &S`. Hence, this will return `None` for
58 /// reference types and such.
for_inherent_impl(ty: &Ty) -> Option<TyFingerprint>59 pub fn for_inherent_impl(ty: &Ty) -> Option<TyFingerprint> {
60 let fp = match ty.kind(Interner) {
61 TyKind::Str => TyFingerprint::Str,
62 TyKind::Never => TyFingerprint::Never,
63 TyKind::Slice(..) => TyFingerprint::Slice,
64 TyKind::Array(..) => TyFingerprint::Array,
65 TyKind::Scalar(scalar) => TyFingerprint::Scalar(*scalar),
66 TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(*adt),
67 TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(*mutability),
68 TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(*alias_id),
69 TyKind::Dyn(_) => ty.dyn_trait().map(TyFingerprint::Dyn)?,
70 _ => return None,
71 };
72 Some(fp)
73 }
74
75 /// Creates a TyFingerprint for looking up a trait impl.
for_trait_impl(ty: &Ty) -> Option<TyFingerprint>76 pub fn for_trait_impl(ty: &Ty) -> Option<TyFingerprint> {
77 let fp = match ty.kind(Interner) {
78 TyKind::Str => TyFingerprint::Str,
79 TyKind::Never => TyFingerprint::Never,
80 TyKind::Slice(..) => TyFingerprint::Slice,
81 TyKind::Array(..) => TyFingerprint::Array,
82 TyKind::Scalar(scalar) => TyFingerprint::Scalar(*scalar),
83 TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(*adt),
84 TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(*mutability),
85 TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(*alias_id),
86 TyKind::Dyn(_) => ty.dyn_trait().map(TyFingerprint::Dyn)?,
87 TyKind::Ref(_, _, ty) => return TyFingerprint::for_trait_impl(ty),
88 TyKind::Tuple(_, subst) => {
89 let first_ty = subst.interned().get(0).map(|arg| arg.assert_ty_ref(Interner));
90 match first_ty {
91 Some(ty) => return TyFingerprint::for_trait_impl(ty),
92 None => TyFingerprint::Unit,
93 }
94 }
95 TyKind::AssociatedType(_, _)
96 | TyKind::OpaqueType(_, _)
97 | TyKind::FnDef(_, _)
98 | TyKind::Closure(_, _)
99 | TyKind::Generator(..)
100 | TyKind::GeneratorWitness(..) => TyFingerprint::Unnameable,
101 TyKind::Function(fn_ptr) => {
102 TyFingerprint::Function(fn_ptr.substitution.0.len(Interner) as u32)
103 }
104 TyKind::Alias(_)
105 | TyKind::Placeholder(_)
106 | TyKind::BoundVar(_)
107 | TyKind::InferenceVar(_, _)
108 | TyKind::Error => return None,
109 };
110 Some(fp)
111 }
112 }
113
114 pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [
115 TyFingerprint::Scalar(Scalar::Int(IntTy::I8)),
116 TyFingerprint::Scalar(Scalar::Int(IntTy::I16)),
117 TyFingerprint::Scalar(Scalar::Int(IntTy::I32)),
118 TyFingerprint::Scalar(Scalar::Int(IntTy::I64)),
119 TyFingerprint::Scalar(Scalar::Int(IntTy::I128)),
120 TyFingerprint::Scalar(Scalar::Int(IntTy::Isize)),
121 TyFingerprint::Scalar(Scalar::Uint(UintTy::U8)),
122 TyFingerprint::Scalar(Scalar::Uint(UintTy::U16)),
123 TyFingerprint::Scalar(Scalar::Uint(UintTy::U32)),
124 TyFingerprint::Scalar(Scalar::Uint(UintTy::U64)),
125 TyFingerprint::Scalar(Scalar::Uint(UintTy::U128)),
126 TyFingerprint::Scalar(Scalar::Uint(UintTy::Usize)),
127 ];
128
129 pub(crate) const ALL_FLOAT_FPS: [TyFingerprint; 2] = [
130 TyFingerprint::Scalar(Scalar::Float(FloatTy::F32)),
131 TyFingerprint::Scalar(Scalar::Float(FloatTy::F64)),
132 ];
133
134 /// Trait impls defined or available in some crate.
135 #[derive(Debug, Eq, PartialEq)]
136 pub struct TraitImpls {
137 // If the `Option<TyFingerprint>` is `None`, the impl may apply to any self type.
138 map: FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Vec<ImplId>>>,
139 }
140
141 impl TraitImpls {
trait_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self>142 pub(crate) fn trait_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> {
143 let _p = profile::span("trait_impls_in_crate_query").detail(|| format!("{krate:?}"));
144 let mut impls = Self { map: FxHashMap::default() };
145
146 let crate_def_map = db.crate_def_map(krate);
147 impls.collect_def_map(db, &crate_def_map);
148 impls.shrink_to_fit();
149
150 Arc::new(impls)
151 }
152
trait_impls_in_block_query(db: &dyn HirDatabase, block: BlockId) -> Arc<Self>153 pub(crate) fn trait_impls_in_block_query(db: &dyn HirDatabase, block: BlockId) -> Arc<Self> {
154 let _p = profile::span("trait_impls_in_block_query");
155 let mut impls = Self { map: FxHashMap::default() };
156
157 let block_def_map = db.block_def_map(block);
158 impls.collect_def_map(db, &block_def_map);
159 impls.shrink_to_fit();
160
161 Arc::new(impls)
162 }
163
trait_impls_in_deps_query( db: &dyn HirDatabase, krate: CrateId, ) -> Arc<[Arc<Self>]>164 pub(crate) fn trait_impls_in_deps_query(
165 db: &dyn HirDatabase,
166 krate: CrateId,
167 ) -> Arc<[Arc<Self>]> {
168 let _p = profile::span("trait_impls_in_deps_query").detail(|| format!("{krate:?}"));
169 let crate_graph = db.crate_graph();
170 // FIXME: use `Arc::from_iter` when it becomes available
171 Arc::from(
172 crate_graph
173 .transitive_deps(krate)
174 .map(|krate| db.trait_impls_in_crate(krate))
175 .collect::<Vec<_>>(),
176 )
177 }
178
shrink_to_fit(&mut self)179 fn shrink_to_fit(&mut self) {
180 self.map.shrink_to_fit();
181 self.map.values_mut().for_each(|map| {
182 map.shrink_to_fit();
183 map.values_mut().for_each(Vec::shrink_to_fit);
184 });
185 }
186
collect_def_map(&mut self, db: &dyn HirDatabase, def_map: &DefMap)187 fn collect_def_map(&mut self, db: &dyn HirDatabase, def_map: &DefMap) {
188 for (_module_id, module_data) in def_map.modules() {
189 for impl_id in module_data.scope.impls() {
190 // Reservation impls should be ignored during trait resolution, so we never need
191 // them during type analysis. See rust-lang/rust#64631 for details.
192 //
193 // FIXME: Reservation impls should be considered during coherence checks. If we are
194 // (ever) to implement coherence checks, this filtering should be done by the trait
195 // solver.
196 if db.attrs(impl_id.into()).by_key("rustc_reservation_impl").exists() {
197 continue;
198 }
199 let target_trait = match db.impl_trait(impl_id) {
200 Some(tr) => tr.skip_binders().hir_trait_id(),
201 None => continue,
202 };
203 let self_ty = db.impl_self_ty(impl_id);
204 let self_ty_fp = TyFingerprint::for_trait_impl(self_ty.skip_binders());
205 self.map
206 .entry(target_trait)
207 .or_default()
208 .entry(self_ty_fp)
209 .or_default()
210 .push(impl_id);
211 }
212
213 // To better support custom derives, collect impls in all unnamed const items.
214 // const _: () = { ... };
215 for konst in collect_unnamed_consts(db, &module_data.scope) {
216 let body = db.body(konst.into());
217 for (_, block_def_map) in body.blocks(db.upcast()) {
218 self.collect_def_map(db, &block_def_map);
219 }
220 }
221 }
222 }
223
224 /// Queries all trait impls for the given type.
for_self_ty_without_blanket_impls( &self, fp: TyFingerprint, ) -> impl Iterator<Item = ImplId> + '_225 pub fn for_self_ty_without_blanket_impls(
226 &self,
227 fp: TyFingerprint,
228 ) -> impl Iterator<Item = ImplId> + '_ {
229 self.map
230 .values()
231 .flat_map(move |impls| impls.get(&Some(fp)).into_iter())
232 .flat_map(|it| it.iter().copied())
233 }
234
235 /// Queries all impls of the given trait.
for_trait(&self, trait_: TraitId) -> impl Iterator<Item = ImplId> + '_236 pub fn for_trait(&self, trait_: TraitId) -> impl Iterator<Item = ImplId> + '_ {
237 self.map
238 .get(&trait_)
239 .into_iter()
240 .flat_map(|map| map.values().flat_map(|v| v.iter().copied()))
241 }
242
243 /// Queries all impls of `trait_` that may apply to `self_ty`.
for_trait_and_self_ty( &self, trait_: TraitId, self_ty: TyFingerprint, ) -> impl Iterator<Item = ImplId> + '_244 pub fn for_trait_and_self_ty(
245 &self,
246 trait_: TraitId,
247 self_ty: TyFingerprint,
248 ) -> impl Iterator<Item = ImplId> + '_ {
249 self.map
250 .get(&trait_)
251 .into_iter()
252 .flat_map(move |map| map.get(&Some(self_ty)).into_iter().chain(map.get(&None)))
253 .flat_map(|v| v.iter().copied())
254 }
255
all_impls(&self) -> impl Iterator<Item = ImplId> + '_256 pub fn all_impls(&self) -> impl Iterator<Item = ImplId> + '_ {
257 self.map.values().flat_map(|map| map.values().flat_map(|v| v.iter().copied()))
258 }
259 }
260
261 /// Inherent impls defined in some crate.
262 ///
263 /// Inherent impls can only be defined in the crate that also defines the self type of the impl
264 /// (note that some primitives are considered to be defined by both libcore and liballoc).
265 ///
266 /// This makes inherent impl lookup easier than trait impl lookup since we only have to consider a
267 /// single crate.
268 #[derive(Debug, Eq, PartialEq)]
269 pub struct InherentImpls {
270 map: FxHashMap<TyFingerprint, Vec<ImplId>>,
271 invalid_impls: Vec<ImplId>,
272 }
273
274 impl InherentImpls {
inherent_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self>275 pub(crate) fn inherent_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> {
276 let _p = profile::span("inherent_impls_in_crate_query").detail(|| format!("{krate:?}"));
277 let mut impls = Self { map: FxHashMap::default(), invalid_impls: Vec::default() };
278
279 let crate_def_map = db.crate_def_map(krate);
280 impls.collect_def_map(db, &crate_def_map);
281 impls.shrink_to_fit();
282
283 Arc::new(impls)
284 }
285
inherent_impls_in_block_query(db: &dyn HirDatabase, block: BlockId) -> Arc<Self>286 pub(crate) fn inherent_impls_in_block_query(db: &dyn HirDatabase, block: BlockId) -> Arc<Self> {
287 let _p = profile::span("inherent_impls_in_block_query");
288 let mut impls = Self { map: FxHashMap::default(), invalid_impls: Vec::default() };
289
290 let block_def_map = db.block_def_map(block);
291 impls.collect_def_map(db, &block_def_map);
292 impls.shrink_to_fit();
293
294 Arc::new(impls)
295 }
296
shrink_to_fit(&mut self)297 fn shrink_to_fit(&mut self) {
298 self.map.values_mut().for_each(Vec::shrink_to_fit);
299 self.map.shrink_to_fit();
300 }
301
collect_def_map(&mut self, db: &dyn HirDatabase, def_map: &DefMap)302 fn collect_def_map(&mut self, db: &dyn HirDatabase, def_map: &DefMap) {
303 for (_module_id, module_data) in def_map.modules() {
304 for impl_id in module_data.scope.impls() {
305 let data = db.impl_data(impl_id);
306 if data.target_trait.is_some() {
307 continue;
308 }
309
310 let self_ty = db.impl_self_ty(impl_id);
311 let self_ty = self_ty.skip_binders();
312
313 match is_inherent_impl_coherent(db, def_map, &data, self_ty) {
314 true => {
315 // `fp` should only be `None` in error cases (either erroneous code or incomplete name resolution)
316 if let Some(fp) = TyFingerprint::for_inherent_impl(self_ty) {
317 self.map.entry(fp).or_default().push(impl_id);
318 }
319 }
320 false => self.invalid_impls.push(impl_id),
321 }
322 }
323
324 // To better support custom derives, collect impls in all unnamed const items.
325 // const _: () = { ... };
326 for konst in collect_unnamed_consts(db, &module_data.scope) {
327 let body = db.body(konst.into());
328 for (_, block_def_map) in body.blocks(db.upcast()) {
329 self.collect_def_map(db, &block_def_map);
330 }
331 }
332 }
333 }
334
for_self_ty(&self, self_ty: &Ty) -> &[ImplId]335 pub fn for_self_ty(&self, self_ty: &Ty) -> &[ImplId] {
336 match TyFingerprint::for_inherent_impl(self_ty) {
337 Some(fp) => self.map.get(&fp).map(|vec| vec.as_ref()).unwrap_or(&[]),
338 None => &[],
339 }
340 }
341
all_impls(&self) -> impl Iterator<Item = ImplId> + '_342 pub fn all_impls(&self) -> impl Iterator<Item = ImplId> + '_ {
343 self.map.values().flat_map(|v| v.iter().copied())
344 }
345
invalid_impls(&self) -> &[ImplId]346 pub fn invalid_impls(&self) -> &[ImplId] {
347 &self.invalid_impls
348 }
349 }
350
incoherent_inherent_impl_crates( db: &dyn HirDatabase, krate: CrateId, fp: TyFingerprint, ) -> SmallVec<[CrateId; 2]>351 pub(crate) fn incoherent_inherent_impl_crates(
352 db: &dyn HirDatabase,
353 krate: CrateId,
354 fp: TyFingerprint,
355 ) -> SmallVec<[CrateId; 2]> {
356 let _p = profile::span("inherent_impl_crates_query");
357 let mut res = SmallVec::new();
358 let crate_graph = db.crate_graph();
359
360 // should pass crate for finger print and do reverse deps
361
362 for krate in crate_graph.transitive_deps(krate) {
363 let impls = db.inherent_impls_in_crate(krate);
364 if impls.map.get(&fp).map_or(false, |v| !v.is_empty()) {
365 res.push(krate);
366 }
367 }
368
369 res
370 }
371
collect_unnamed_consts<'a>( db: &'a dyn HirDatabase, scope: &'a ItemScope, ) -> impl Iterator<Item = ConstId> + 'a372 fn collect_unnamed_consts<'a>(
373 db: &'a dyn HirDatabase,
374 scope: &'a ItemScope,
375 ) -> impl Iterator<Item = ConstId> + 'a {
376 let unnamed_consts = scope.unnamed_consts();
377
378 // FIXME: Also treat consts named `_DERIVE_*` as unnamed, since synstructure generates those.
379 // Should be removed once synstructure stops doing that.
380 let synstructure_hack_consts = scope.values().filter_map(|(item, _)| match item {
381 ModuleDefId::ConstId(id) => {
382 let loc = id.lookup(db.upcast());
383 let item_tree = loc.id.item_tree(db.upcast());
384 if item_tree[loc.id.value]
385 .name
386 .as_ref()
387 .map_or(false, |n| n.to_smol_str().starts_with("_DERIVE_"))
388 {
389 Some(id)
390 } else {
391 None
392 }
393 }
394 _ => None,
395 });
396
397 unnamed_consts.chain(synstructure_hack_consts)
398 }
399
def_crates( db: &dyn HirDatabase, ty: &Ty, cur_crate: CrateId, ) -> Option<SmallVec<[CrateId; 2]>>400 pub fn def_crates(
401 db: &dyn HirDatabase,
402 ty: &Ty,
403 cur_crate: CrateId,
404 ) -> Option<SmallVec<[CrateId; 2]>> {
405 match ty.kind(Interner) {
406 &TyKind::Adt(AdtId(def_id), _) => {
407 let rustc_has_incoherent_inherent_impls = match def_id {
408 hir_def::AdtId::StructId(id) => db
409 .struct_data(id)
410 .flags
411 .contains(StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL),
412 hir_def::AdtId::UnionId(id) => db
413 .union_data(id)
414 .flags
415 .contains(StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL),
416 hir_def::AdtId::EnumId(id) => db.enum_data(id).rustc_has_incoherent_inherent_impls,
417 };
418 Some(if rustc_has_incoherent_inherent_impls {
419 db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::Adt(def_id))
420 } else {
421 smallvec![def_id.module(db.upcast()).krate()]
422 })
423 }
424 &TyKind::Foreign(id) => {
425 let alias = from_foreign_def_id(id);
426 Some(if db.type_alias_data(alias).rustc_has_incoherent_inherent_impls {
427 db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::ForeignType(id))
428 } else {
429 smallvec![alias.module(db.upcast()).krate()]
430 })
431 }
432 TyKind::Dyn(_) => {
433 let trait_id = ty.dyn_trait()?;
434 Some(if db.trait_data(trait_id).rustc_has_incoherent_inherent_impls {
435 db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::Dyn(trait_id))
436 } else {
437 smallvec![trait_id.module(db.upcast()).krate()]
438 })
439 }
440 // for primitives, there may be impls in various places (core and alloc
441 // mostly). We just check the whole crate graph for crates with impls
442 // (cached behind a query).
443 TyKind::Scalar(_)
444 | TyKind::Str
445 | TyKind::Slice(_)
446 | TyKind::Array(..)
447 | TyKind::Raw(..) => Some(db.incoherent_inherent_impl_crates(
448 cur_crate,
449 TyFingerprint::for_inherent_impl(ty).expect("fingerprint for primitive"),
450 )),
451 _ => None,
452 }
453 }
454
455 /// Look up the method with the given name.
lookup_method( db: &dyn HirDatabase, ty: &Canonical<Ty>, env: Arc<TraitEnvironment>, traits_in_scope: &FxHashSet<TraitId>, visible_from_module: VisibleFromModule, name: &Name, ) -> Option<(ReceiverAdjustments, FunctionId, bool)>456 pub(crate) fn lookup_method(
457 db: &dyn HirDatabase,
458 ty: &Canonical<Ty>,
459 env: Arc<TraitEnvironment>,
460 traits_in_scope: &FxHashSet<TraitId>,
461 visible_from_module: VisibleFromModule,
462 name: &Name,
463 ) -> Option<(ReceiverAdjustments, FunctionId, bool)> {
464 let mut not_visible = None;
465 let res = iterate_method_candidates(
466 ty,
467 db,
468 env,
469 traits_in_scope,
470 visible_from_module,
471 Some(name),
472 LookupMode::MethodCall,
473 |adjustments, f, visible| match f {
474 AssocItemId::FunctionId(f) if visible => Some((adjustments, f, true)),
475 AssocItemId::FunctionId(f) if not_visible.is_none() => {
476 not_visible = Some((adjustments, f, false));
477 None
478 }
479 _ => None,
480 },
481 );
482 res.or(not_visible)
483 }
484
485 /// Whether we're looking up a dotted method call (like `v.len()`) or a path
486 /// (like `Vec::new`).
487 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
488 pub enum LookupMode {
489 /// Looking up a method call like `v.len()`: We only consider candidates
490 /// that have a `self` parameter, and do autoderef.
491 MethodCall,
492 /// Looking up a path like `Vec::new` or `Vec::default`: We consider all
493 /// candidates including associated constants, but don't do autoderef.
494 Path,
495 }
496
497 #[derive(Clone, Copy)]
498 pub enum VisibleFromModule {
499 /// Filter for results that are visible from the given module
500 Filter(ModuleId),
501 /// Include impls from the given block.
502 IncludeBlock(BlockId),
503 /// Do nothing special in regards visibility
504 None,
505 }
506
507 impl From<Option<ModuleId>> for VisibleFromModule {
from(module: Option<ModuleId>) -> Self508 fn from(module: Option<ModuleId>) -> Self {
509 match module {
510 Some(module) => Self::Filter(module),
511 None => Self::None,
512 }
513 }
514 }
515
516 impl From<Option<BlockId>> for VisibleFromModule {
from(block: Option<BlockId>) -> Self517 fn from(block: Option<BlockId>) -> Self {
518 match block {
519 Some(block) => Self::IncludeBlock(block),
520 None => Self::None,
521 }
522 }
523 }
524
525 #[derive(Debug, Clone, Default)]
526 pub struct ReceiverAdjustments {
527 autoref: Option<Mutability>,
528 autoderefs: usize,
529 unsize_array: bool,
530 }
531
532 impl ReceiverAdjustments {
apply(&self, table: &mut InferenceTable<'_>, ty: Ty) -> (Ty, Vec<Adjustment>)533 pub(crate) fn apply(&self, table: &mut InferenceTable<'_>, ty: Ty) -> (Ty, Vec<Adjustment>) {
534 let mut ty = table.resolve_ty_shallow(&ty);
535 let mut adjust = Vec::new();
536 for _ in 0..self.autoderefs {
537 match autoderef::autoderef_step(table, ty.clone()) {
538 None => {
539 never!("autoderef not possible for {:?}", ty);
540 ty = TyKind::Error.intern(Interner);
541 break;
542 }
543 Some((kind, new_ty)) => {
544 ty = new_ty.clone();
545 adjust.push(Adjustment {
546 kind: Adjust::Deref(match kind {
547 // FIXME should we know the mutability here, when autoref is `None`?
548 AutoderefKind::Overloaded => Some(OverloadedDeref(self.autoref)),
549 AutoderefKind::Builtin => None,
550 }),
551 target: new_ty,
552 });
553 }
554 }
555 }
556 if let Some(m) = self.autoref {
557 let a = Adjustment::borrow(m, ty);
558 ty = a.target.clone();
559 adjust.push(a);
560 }
561 if self.unsize_array {
562 ty = 'x: {
563 if let TyKind::Ref(m, l, inner) = ty.kind(Interner) {
564 if let TyKind::Array(inner, _) = inner.kind(Interner) {
565 break 'x TyKind::Ref(
566 m.clone(),
567 l.clone(),
568 TyKind::Slice(inner.clone()).intern(Interner),
569 )
570 .intern(Interner);
571 }
572 }
573 // FIXME: report diagnostic if array unsizing happens without indirection.
574 ty
575 };
576 adjust.push(Adjustment {
577 kind: Adjust::Pointer(PointerCast::Unsize),
578 target: ty.clone(),
579 });
580 }
581 (ty, adjust)
582 }
583
with_autoref(&self, m: Mutability) -> ReceiverAdjustments584 fn with_autoref(&self, m: Mutability) -> ReceiverAdjustments {
585 Self { autoref: Some(m), ..*self }
586 }
587 }
588
589 // This would be nicer if it just returned an iterator, but that runs into
590 // lifetime problems, because we need to borrow temp `CrateImplDefs`.
591 // FIXME add a context type here?
iterate_method_candidates<T>( ty: &Canonical<Ty>, db: &dyn HirDatabase, env: Arc<TraitEnvironment>, traits_in_scope: &FxHashSet<TraitId>, visible_from_module: VisibleFromModule, name: Option<&Name>, mode: LookupMode, mut callback: impl FnMut(ReceiverAdjustments, AssocItemId, bool) -> Option<T>, ) -> Option<T>592 pub(crate) fn iterate_method_candidates<T>(
593 ty: &Canonical<Ty>,
594 db: &dyn HirDatabase,
595 env: Arc<TraitEnvironment>,
596 traits_in_scope: &FxHashSet<TraitId>,
597 visible_from_module: VisibleFromModule,
598 name: Option<&Name>,
599 mode: LookupMode,
600 mut callback: impl FnMut(ReceiverAdjustments, AssocItemId, bool) -> Option<T>,
601 ) -> Option<T> {
602 let mut slot = None;
603 iterate_method_candidates_dyn(
604 ty,
605 db,
606 env,
607 traits_in_scope,
608 visible_from_module,
609 name,
610 mode,
611 &mut |adj, item, visible| {
612 assert!(slot.is_none());
613 if let Some(it) = callback(adj, item, visible) {
614 slot = Some(it);
615 return ControlFlow::Break(());
616 }
617 ControlFlow::Continue(())
618 },
619 );
620 slot
621 }
622
lookup_impl_const( db: &dyn HirDatabase, env: Arc<TraitEnvironment>, const_id: ConstId, subs: Substitution, ) -> (ConstId, Substitution)623 pub fn lookup_impl_const(
624 db: &dyn HirDatabase,
625 env: Arc<TraitEnvironment>,
626 const_id: ConstId,
627 subs: Substitution,
628 ) -> (ConstId, Substitution) {
629 let trait_id = match const_id.lookup(db.upcast()).container {
630 ItemContainerId::TraitId(id) => id,
631 _ => return (const_id, subs),
632 };
633 let substitution = Substitution::from_iter(Interner, subs.iter(Interner));
634 let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution };
635
636 let const_data = db.const_data(const_id);
637 let name = match const_data.name.as_ref() {
638 Some(name) => name,
639 None => return (const_id, subs),
640 };
641
642 lookup_impl_assoc_item_for_trait_ref(trait_ref, db, env, name)
643 .and_then(
644 |assoc| if let (AssocItemId::ConstId(id), s) = assoc { Some((id, s)) } else { None },
645 )
646 .unwrap_or((const_id, subs))
647 }
648
649 /// Checks if the self parameter of `Trait` method is the `dyn Trait` and we should
650 /// call the method using the vtable.
is_dyn_method( db: &dyn HirDatabase, _env: Arc<TraitEnvironment>, func: FunctionId, fn_subst: Substitution, ) -> Option<usize>651 pub fn is_dyn_method(
652 db: &dyn HirDatabase,
653 _env: Arc<TraitEnvironment>,
654 func: FunctionId,
655 fn_subst: Substitution,
656 ) -> Option<usize> {
657 let ItemContainerId::TraitId(trait_id) = func.lookup(db.upcast()).container else {
658 return None;
659 };
660 let trait_params = db.generic_params(trait_id.into()).type_or_consts.len();
661 let fn_params = fn_subst.len(Interner) - trait_params;
662 let trait_ref = TraitRef {
663 trait_id: to_chalk_trait_id(trait_id),
664 substitution: Substitution::from_iter(Interner, fn_subst.iter(Interner).skip(fn_params)),
665 };
666 let self_ty = trait_ref.self_type_parameter(Interner);
667 if let TyKind::Dyn(d) = self_ty.kind(Interner) {
668 let is_my_trait_in_bounds =
669 d.bounds.skip_binders().as_slice(Interner).iter().any(|x| match x.skip_binders() {
670 // rustc doesn't accept `impl Foo<2> for dyn Foo<5>`, so if the trait id is equal, no matter
671 // what the generics are, we are sure that the method is come from the vtable.
672 WhereClause::Implemented(tr) => tr.trait_id == trait_ref.trait_id,
673 _ => false,
674 });
675 if is_my_trait_in_bounds {
676 return Some(fn_params);
677 }
678 }
679 None
680 }
681
682 /// Looks up the impl method that actually runs for the trait method `func`.
683 ///
684 /// Returns `func` if it's not a method defined in a trait or the lookup failed.
lookup_impl_method( db: &dyn HirDatabase, env: Arc<TraitEnvironment>, func: FunctionId, fn_subst: Substitution, ) -> (FunctionId, Substitution)685 pub fn lookup_impl_method(
686 db: &dyn HirDatabase,
687 env: Arc<TraitEnvironment>,
688 func: FunctionId,
689 fn_subst: Substitution,
690 ) -> (FunctionId, Substitution) {
691 let ItemContainerId::TraitId(trait_id) = func.lookup(db.upcast()).container else {
692 return (func, fn_subst)
693 };
694 let trait_params = db.generic_params(trait_id.into()).type_or_consts.len();
695 let fn_params = fn_subst.len(Interner) - trait_params;
696 let trait_ref = TraitRef {
697 trait_id: to_chalk_trait_id(trait_id),
698 substitution: Substitution::from_iter(Interner, fn_subst.iter(Interner).skip(fn_params)),
699 };
700
701 let name = &db.function_data(func).name;
702 let Some((impl_fn, impl_subst)) = lookup_impl_assoc_item_for_trait_ref(trait_ref, db, env, name)
703 .and_then(|assoc| {
704 if let (AssocItemId::FunctionId(id), subst) = assoc {
705 Some((id, subst))
706 } else {
707 None
708 }
709 })
710 else {
711 return (func, fn_subst);
712 };
713 (
714 impl_fn,
715 Substitution::from_iter(
716 Interner,
717 fn_subst.iter(Interner).take(fn_params).chain(impl_subst.iter(Interner)),
718 ),
719 )
720 }
721
lookup_impl_assoc_item_for_trait_ref( trait_ref: TraitRef, db: &dyn HirDatabase, env: Arc<TraitEnvironment>, name: &Name, ) -> Option<(AssocItemId, Substitution)>722 fn lookup_impl_assoc_item_for_trait_ref(
723 trait_ref: TraitRef,
724 db: &dyn HirDatabase,
725 env: Arc<TraitEnvironment>,
726 name: &Name,
727 ) -> Option<(AssocItemId, Substitution)> {
728 let hir_trait_id = trait_ref.hir_trait_id();
729 let self_ty = trait_ref.self_type_parameter(Interner);
730 let self_ty_fp = TyFingerprint::for_trait_impl(&self_ty)?;
731 let impls = db.trait_impls_in_deps(env.krate);
732 let self_impls = match self_ty.kind(Interner) {
733 TyKind::Adt(id, _) => {
734 id.0.module(db.upcast()).containing_block().map(|x| db.trait_impls_in_block(x))
735 }
736 _ => None,
737 };
738 let impls = impls
739 .iter()
740 .chain(self_impls.as_ref())
741 .flat_map(|impls| impls.for_trait_and_self_ty(hir_trait_id, self_ty_fp));
742
743 let table = InferenceTable::new(db, env);
744
745 let (impl_data, impl_subst) = find_matching_impl(impls, table, trait_ref)?;
746 let item = impl_data.items.iter().find_map(|&it| match it {
747 AssocItemId::FunctionId(f) => {
748 (db.function_data(f).name == *name).then_some(AssocItemId::FunctionId(f))
749 }
750 AssocItemId::ConstId(c) => db
751 .const_data(c)
752 .name
753 .as_ref()
754 .map(|n| n == name)
755 .and_then(|result| if result { Some(AssocItemId::ConstId(c)) } else { None }),
756 AssocItemId::TypeAliasId(_) => None,
757 })?;
758 Some((item, impl_subst))
759 }
760
find_matching_impl( mut impls: impl Iterator<Item = ImplId>, mut table: InferenceTable<'_>, actual_trait_ref: TraitRef, ) -> Option<(Arc<ImplData>, Substitution)>761 fn find_matching_impl(
762 mut impls: impl Iterator<Item = ImplId>,
763 mut table: InferenceTable<'_>,
764 actual_trait_ref: TraitRef,
765 ) -> Option<(Arc<ImplData>, Substitution)> {
766 let db = table.db;
767 impls.find_map(|impl_| {
768 table.run_in_snapshot(|table| {
769 let impl_data = db.impl_data(impl_);
770 let impl_substs =
771 TyBuilder::subst_for_def(db, impl_, None).fill_with_inference_vars(table).build();
772 let trait_ref = db
773 .impl_trait(impl_)
774 .expect("non-trait method in find_matching_impl")
775 .substitute(Interner, &impl_substs);
776
777 if !table.unify(&trait_ref, &actual_trait_ref) {
778 return None;
779 }
780
781 let wcs = crate::chalk_db::convert_where_clauses(db, impl_.into(), &impl_substs)
782 .into_iter()
783 .map(|b| b.cast(Interner));
784 let goal = crate::Goal::all(Interner, wcs);
785 table.try_obligation(goal.clone())?;
786 table.register_obligation(goal);
787 Some((impl_data, table.resolve_completely(impl_substs)))
788 })
789 })
790 }
791
is_inherent_impl_coherent( db: &dyn HirDatabase, def_map: &DefMap, impl_data: &ImplData, self_ty: &Ty, ) -> bool792 fn is_inherent_impl_coherent(
793 db: &dyn HirDatabase,
794 def_map: &DefMap,
795 impl_data: &ImplData,
796 self_ty: &Ty,
797 ) -> bool {
798 let self_ty = self_ty.kind(Interner);
799 let impl_allowed = match self_ty {
800 TyKind::Tuple(_, _)
801 | TyKind::FnDef(_, _)
802 | TyKind::Array(_, _)
803 | TyKind::Never
804 | TyKind::Raw(_, _)
805 | TyKind::Ref(_, _, _)
806 | TyKind::Slice(_)
807 | TyKind::Str
808 | TyKind::Scalar(_) => def_map.is_rustc_coherence_is_core(),
809
810 &TyKind::Adt(AdtId(adt), _) => adt.module(db.upcast()).krate() == def_map.krate(),
811 TyKind::Dyn(it) => it.principal().map_or(false, |trait_ref| {
812 from_chalk_trait_id(trait_ref.trait_id).module(db.upcast()).krate() == def_map.krate()
813 }),
814
815 _ => true,
816 };
817 impl_allowed || {
818 let rustc_has_incoherent_inherent_impls = match self_ty {
819 TyKind::Tuple(_, _)
820 | TyKind::FnDef(_, _)
821 | TyKind::Array(_, _)
822 | TyKind::Never
823 | TyKind::Raw(_, _)
824 | TyKind::Ref(_, _, _)
825 | TyKind::Slice(_)
826 | TyKind::Str
827 | TyKind::Scalar(_) => true,
828
829 &TyKind::Adt(AdtId(adt), _) => match adt {
830 hir_def::AdtId::StructId(id) => db
831 .struct_data(id)
832 .flags
833 .contains(StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL),
834 hir_def::AdtId::UnionId(id) => db
835 .union_data(id)
836 .flags
837 .contains(StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL),
838 hir_def::AdtId::EnumId(it) => db.enum_data(it).rustc_has_incoherent_inherent_impls,
839 },
840 TyKind::Dyn(it) => it.principal().map_or(false, |trait_ref| {
841 db.trait_data(from_chalk_trait_id(trait_ref.trait_id))
842 .rustc_has_incoherent_inherent_impls
843 }),
844
845 _ => false,
846 };
847 rustc_has_incoherent_inherent_impls
848 && !impl_data.items.is_empty()
849 && impl_data.items.iter().copied().all(|assoc| match assoc {
850 AssocItemId::FunctionId(it) => db.function_data(it).rustc_allow_incoherent_impl,
851 AssocItemId::ConstId(it) => db.const_data(it).rustc_allow_incoherent_impl,
852 AssocItemId::TypeAliasId(it) => db.type_alias_data(it).rustc_allow_incoherent_impl,
853 })
854 }
855 }
856
iterate_path_candidates( ty: &Canonical<Ty>, db: &dyn HirDatabase, env: Arc<TraitEnvironment>, traits_in_scope: &FxHashSet<TraitId>, visible_from_module: VisibleFromModule, name: Option<&Name>, callback: &mut dyn FnMut(AssocItemId) -> ControlFlow<()>, ) -> ControlFlow<()>857 pub fn iterate_path_candidates(
858 ty: &Canonical<Ty>,
859 db: &dyn HirDatabase,
860 env: Arc<TraitEnvironment>,
861 traits_in_scope: &FxHashSet<TraitId>,
862 visible_from_module: VisibleFromModule,
863 name: Option<&Name>,
864 callback: &mut dyn FnMut(AssocItemId) -> ControlFlow<()>,
865 ) -> ControlFlow<()> {
866 iterate_method_candidates_dyn(
867 ty,
868 db,
869 env,
870 traits_in_scope,
871 visible_from_module,
872 name,
873 LookupMode::Path,
874 // the adjustments are not relevant for path lookup
875 &mut |_, id, _| callback(id),
876 )
877 }
878
iterate_method_candidates_dyn( ty: &Canonical<Ty>, db: &dyn HirDatabase, env: Arc<TraitEnvironment>, traits_in_scope: &FxHashSet<TraitId>, visible_from_module: VisibleFromModule, name: Option<&Name>, mode: LookupMode, callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, ) -> ControlFlow<()>879 pub fn iterate_method_candidates_dyn(
880 ty: &Canonical<Ty>,
881 db: &dyn HirDatabase,
882 env: Arc<TraitEnvironment>,
883 traits_in_scope: &FxHashSet<TraitId>,
884 visible_from_module: VisibleFromModule,
885 name: Option<&Name>,
886 mode: LookupMode,
887 callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
888 ) -> ControlFlow<()> {
889 match mode {
890 LookupMode::MethodCall => {
891 // For method calls, rust first does any number of autoderef, and
892 // then one autoref (i.e. when the method takes &self or &mut self).
893 // Note that when we've got a receiver like &S, even if the method
894 // we find in the end takes &self, we still do the autoderef step
895 // (just as rustc does an autoderef and then autoref again).
896
897 // We have to be careful about the order we're looking at candidates
898 // in here. Consider the case where we're resolving `x.clone()`
899 // where `x: &Vec<_>`. This resolves to the clone method with self
900 // type `Vec<_>`, *not* `&_`. I.e. we need to consider methods where
901 // the receiver type exactly matches before cases where we have to
902 // do autoref. But in the autoderef steps, the `&_` self type comes
903 // up *before* the `Vec<_>` self type.
904 //
905 // On the other hand, we don't want to just pick any by-value method
906 // before any by-autoref method; it's just that we need to consider
907 // the methods by autoderef order of *receiver types*, not *self
908 // types*.
909
910 let mut table = InferenceTable::new(db, env.clone());
911 let ty = table.instantiate_canonical(ty.clone());
912 let deref_chain = autoderef_method_receiver(&mut table, ty);
913
914 let result = deref_chain.into_iter().try_for_each(|(receiver_ty, adj)| {
915 iterate_method_candidates_with_autoref(
916 &receiver_ty,
917 adj,
918 db,
919 env.clone(),
920 traits_in_scope,
921 visible_from_module,
922 name,
923 callback,
924 )
925 });
926 result
927 }
928 LookupMode::Path => {
929 // No autoderef for path lookups
930 iterate_method_candidates_for_self_ty(
931 ty,
932 db,
933 env,
934 traits_in_scope,
935 visible_from_module,
936 name,
937 callback,
938 )
939 }
940 }
941 }
942
iterate_method_candidates_with_autoref( receiver_ty: &Canonical<Ty>, first_adjustment: ReceiverAdjustments, db: &dyn HirDatabase, env: Arc<TraitEnvironment>, traits_in_scope: &FxHashSet<TraitId>, visible_from_module: VisibleFromModule, name: Option<&Name>, mut callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, ) -> ControlFlow<()>943 fn iterate_method_candidates_with_autoref(
944 receiver_ty: &Canonical<Ty>,
945 first_adjustment: ReceiverAdjustments,
946 db: &dyn HirDatabase,
947 env: Arc<TraitEnvironment>,
948 traits_in_scope: &FxHashSet<TraitId>,
949 visible_from_module: VisibleFromModule,
950 name: Option<&Name>,
951 mut callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
952 ) -> ControlFlow<()> {
953 if receiver_ty.value.is_general_var(Interner, &receiver_ty.binders) {
954 // don't try to resolve methods on unknown types
955 return ControlFlow::Continue(());
956 }
957
958 let mut iterate_method_candidates_by_receiver = move |receiver_ty, first_adjustment| {
959 iterate_method_candidates_by_receiver(
960 receiver_ty,
961 first_adjustment,
962 db,
963 env.clone(),
964 traits_in_scope,
965 visible_from_module,
966 name,
967 &mut callback,
968 )
969 };
970
971 let mut maybe_reborrowed = first_adjustment.clone();
972 if let Some((_, _, m)) = receiver_ty.value.as_reference() {
973 // Prefer reborrow of references to move
974 maybe_reborrowed.autoref = Some(m);
975 maybe_reborrowed.autoderefs += 1;
976 }
977
978 iterate_method_candidates_by_receiver(receiver_ty, maybe_reborrowed)?;
979
980 let refed = Canonical {
981 value: TyKind::Ref(Mutability::Not, static_lifetime(), receiver_ty.value.clone())
982 .intern(Interner),
983 binders: receiver_ty.binders.clone(),
984 };
985
986 iterate_method_candidates_by_receiver(&refed, first_adjustment.with_autoref(Mutability::Not))?;
987
988 let ref_muted = Canonical {
989 value: TyKind::Ref(Mutability::Mut, static_lifetime(), receiver_ty.value.clone())
990 .intern(Interner),
991 binders: receiver_ty.binders.clone(),
992 };
993
994 iterate_method_candidates_by_receiver(
995 &ref_muted,
996 first_adjustment.with_autoref(Mutability::Mut),
997 )
998 }
999
iterate_method_candidates_by_receiver( receiver_ty: &Canonical<Ty>, receiver_adjustments: ReceiverAdjustments, db: &dyn HirDatabase, env: Arc<TraitEnvironment>, traits_in_scope: &FxHashSet<TraitId>, visible_from_module: VisibleFromModule, name: Option<&Name>, mut callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, ) -> ControlFlow<()>1000 fn iterate_method_candidates_by_receiver(
1001 receiver_ty: &Canonical<Ty>,
1002 receiver_adjustments: ReceiverAdjustments,
1003 db: &dyn HirDatabase,
1004 env: Arc<TraitEnvironment>,
1005 traits_in_scope: &FxHashSet<TraitId>,
1006 visible_from_module: VisibleFromModule,
1007 name: Option<&Name>,
1008 mut callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
1009 ) -> ControlFlow<()> {
1010 let mut table = InferenceTable::new(db, env);
1011 let receiver_ty = table.instantiate_canonical(receiver_ty.clone());
1012 let snapshot = table.snapshot();
1013 // We're looking for methods with *receiver* type receiver_ty. These could
1014 // be found in any of the derefs of receiver_ty, so we have to go through
1015 // that.
1016 let mut autoderef = autoderef::Autoderef::new(&mut table, receiver_ty.clone());
1017 while let Some((self_ty, _)) = autoderef.next() {
1018 iterate_inherent_methods(
1019 &self_ty,
1020 autoderef.table,
1021 name,
1022 Some(&receiver_ty),
1023 Some(receiver_adjustments.clone()),
1024 visible_from_module,
1025 &mut callback,
1026 )?
1027 }
1028
1029 table.rollback_to(snapshot);
1030
1031 let mut autoderef = autoderef::Autoderef::new(&mut table, receiver_ty.clone());
1032 while let Some((self_ty, _)) = autoderef.next() {
1033 iterate_trait_method_candidates(
1034 &self_ty,
1035 autoderef.table,
1036 traits_in_scope,
1037 name,
1038 Some(&receiver_ty),
1039 Some(receiver_adjustments.clone()),
1040 &mut callback,
1041 )?
1042 }
1043
1044 ControlFlow::Continue(())
1045 }
1046
iterate_method_candidates_for_self_ty( self_ty: &Canonical<Ty>, db: &dyn HirDatabase, env: Arc<TraitEnvironment>, traits_in_scope: &FxHashSet<TraitId>, visible_from_module: VisibleFromModule, name: Option<&Name>, mut callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, ) -> ControlFlow<()>1047 fn iterate_method_candidates_for_self_ty(
1048 self_ty: &Canonical<Ty>,
1049 db: &dyn HirDatabase,
1050 env: Arc<TraitEnvironment>,
1051 traits_in_scope: &FxHashSet<TraitId>,
1052 visible_from_module: VisibleFromModule,
1053 name: Option<&Name>,
1054 mut callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
1055 ) -> ControlFlow<()> {
1056 let mut table = InferenceTable::new(db, env);
1057 let self_ty = table.instantiate_canonical(self_ty.clone());
1058 iterate_inherent_methods(
1059 &self_ty,
1060 &mut table,
1061 name,
1062 None,
1063 None,
1064 visible_from_module,
1065 &mut callback,
1066 )?;
1067 iterate_trait_method_candidates(
1068 &self_ty,
1069 &mut table,
1070 traits_in_scope,
1071 name,
1072 None,
1073 None,
1074 callback,
1075 )
1076 }
1077
iterate_trait_method_candidates( self_ty: &Ty, table: &mut InferenceTable<'_>, traits_in_scope: &FxHashSet<TraitId>, name: Option<&Name>, receiver_ty: Option<&Ty>, receiver_adjustments: Option<ReceiverAdjustments>, callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, ) -> ControlFlow<()>1078 fn iterate_trait_method_candidates(
1079 self_ty: &Ty,
1080 table: &mut InferenceTable<'_>,
1081 traits_in_scope: &FxHashSet<TraitId>,
1082 name: Option<&Name>,
1083 receiver_ty: Option<&Ty>,
1084 receiver_adjustments: Option<ReceiverAdjustments>,
1085 callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
1086 ) -> ControlFlow<()> {
1087 let db = table.db;
1088 let env = table.trait_env.clone();
1089 let self_is_array = matches!(self_ty.kind(Interner), chalk_ir::TyKind::Array(..));
1090
1091 let canonical_self_ty = table.canonicalize(self_ty.clone()).value;
1092
1093 'traits: for &t in traits_in_scope {
1094 let data = db.trait_data(t);
1095
1096 // Traits annotated with `#[rustc_skip_array_during_method_dispatch]` are skipped during
1097 // method resolution, if the receiver is an array, and we're compiling for editions before
1098 // 2021.
1099 // This is to make `[a].into_iter()` not break code with the new `IntoIterator` impl for
1100 // arrays.
1101 if data.skip_array_during_method_dispatch && self_is_array {
1102 // FIXME: this should really be using the edition of the method name's span, in case it
1103 // comes from a macro
1104 if db.crate_graph()[env.krate].edition < Edition::Edition2021 {
1105 continue;
1106 }
1107 }
1108
1109 // we'll be lazy about checking whether the type implements the
1110 // trait, but if we find out it doesn't, we'll skip the rest of the
1111 // iteration
1112 let mut known_implemented = false;
1113 for &(_, item) in data.items.iter() {
1114 // Don't pass a `visible_from_module` down to `is_valid_candidate`,
1115 // since only inherent methods should be included into visibility checking.
1116 let visible = match is_valid_candidate(table, name, receiver_ty, item, self_ty, None) {
1117 IsValidCandidate::Yes => true,
1118 IsValidCandidate::NotVisible => false,
1119 IsValidCandidate::No => continue,
1120 };
1121 if !known_implemented {
1122 let goal = generic_implements_goal(db, env.clone(), t, &canonical_self_ty);
1123 if db.trait_solve(env.krate, env.block, goal.cast(Interner)).is_none() {
1124 continue 'traits;
1125 }
1126 }
1127 known_implemented = true;
1128 callback(receiver_adjustments.clone().unwrap_or_default(), item, visible)?;
1129 }
1130 }
1131 ControlFlow::Continue(())
1132 }
1133
iterate_inherent_methods( self_ty: &Ty, table: &mut InferenceTable<'_>, name: Option<&Name>, receiver_ty: Option<&Ty>, receiver_adjustments: Option<ReceiverAdjustments>, visible_from_module: VisibleFromModule, callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, ) -> ControlFlow<()>1134 fn iterate_inherent_methods(
1135 self_ty: &Ty,
1136 table: &mut InferenceTable<'_>,
1137 name: Option<&Name>,
1138 receiver_ty: Option<&Ty>,
1139 receiver_adjustments: Option<ReceiverAdjustments>,
1140 visible_from_module: VisibleFromModule,
1141 callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
1142 ) -> ControlFlow<()> {
1143 let db = table.db;
1144 let env = table.trait_env.clone();
1145
1146 // For trait object types and placeholder types with trait bounds, the methods of the trait and
1147 // its super traits are considered inherent methods. This matters because these methods have
1148 // higher priority than the other traits' methods, which would be considered in
1149 // `iterate_trait_method_candidates()` only after this function.
1150 match self_ty.kind(Interner) {
1151 TyKind::Placeholder(_) => {
1152 let env = table.trait_env.clone();
1153 let traits = env
1154 .traits_in_scope_from_clauses(self_ty.clone())
1155 .flat_map(|t| all_super_traits(db.upcast(), t));
1156 iterate_inherent_trait_methods(
1157 self_ty,
1158 table,
1159 name,
1160 receiver_ty,
1161 receiver_adjustments.clone(),
1162 callback,
1163 traits,
1164 )?;
1165 }
1166 TyKind::Dyn(_) => {
1167 if let Some(principal_trait) = self_ty.dyn_trait() {
1168 let traits = all_super_traits(db.upcast(), principal_trait);
1169 iterate_inherent_trait_methods(
1170 self_ty,
1171 table,
1172 name,
1173 receiver_ty,
1174 receiver_adjustments.clone(),
1175 callback,
1176 traits.into_iter(),
1177 )?;
1178 }
1179 }
1180 _ => {}
1181 }
1182
1183 let def_crates = match def_crates(db, self_ty, env.krate) {
1184 Some(k) => k,
1185 None => return ControlFlow::Continue(()),
1186 };
1187
1188 let (module, mut block) = match visible_from_module {
1189 VisibleFromModule::Filter(module) => (Some(module), module.containing_block()),
1190 VisibleFromModule::IncludeBlock(block) => (None, Some(block)),
1191 VisibleFromModule::None => (None, None),
1192 };
1193
1194 while let Some(block_id) = block {
1195 let impls = db.inherent_impls_in_block(block_id);
1196 impls_for_self_ty(
1197 &impls,
1198 self_ty,
1199 table,
1200 name,
1201 receiver_ty,
1202 receiver_adjustments.clone(),
1203 module,
1204 callback,
1205 )?;
1206
1207 block = db.block_def_map(block_id).parent().and_then(|module| module.containing_block());
1208 }
1209
1210 for krate in def_crates {
1211 let impls = db.inherent_impls_in_crate(krate);
1212 impls_for_self_ty(
1213 &impls,
1214 self_ty,
1215 table,
1216 name,
1217 receiver_ty,
1218 receiver_adjustments.clone(),
1219 module,
1220 callback,
1221 )?;
1222 }
1223 return ControlFlow::Continue(());
1224
1225 fn iterate_inherent_trait_methods(
1226 self_ty: &Ty,
1227 table: &mut InferenceTable<'_>,
1228 name: Option<&Name>,
1229 receiver_ty: Option<&Ty>,
1230 receiver_adjustments: Option<ReceiverAdjustments>,
1231 callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
1232 traits: impl Iterator<Item = TraitId>,
1233 ) -> ControlFlow<()> {
1234 let db = table.db;
1235 for t in traits {
1236 let data = db.trait_data(t);
1237 for &(_, item) in data.items.iter() {
1238 // We don't pass `visible_from_module` as all trait items should be visible.
1239 let visible =
1240 match is_valid_candidate(table, name, receiver_ty, item, self_ty, None) {
1241 IsValidCandidate::Yes => true,
1242 IsValidCandidate::NotVisible => false,
1243 IsValidCandidate::No => continue,
1244 };
1245 callback(receiver_adjustments.clone().unwrap_or_default(), item, visible)?;
1246 }
1247 }
1248 ControlFlow::Continue(())
1249 }
1250
1251 fn impls_for_self_ty(
1252 impls: &InherentImpls,
1253 self_ty: &Ty,
1254 table: &mut InferenceTable<'_>,
1255 name: Option<&Name>,
1256 receiver_ty: Option<&Ty>,
1257 receiver_adjustments: Option<ReceiverAdjustments>,
1258 visible_from_module: Option<ModuleId>,
1259 callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
1260 ) -> ControlFlow<()> {
1261 let db = table.db;
1262 let impls_for_self_ty = impls.for_self_ty(self_ty);
1263 for &impl_def in impls_for_self_ty {
1264 for &item in &db.impl_data(impl_def).items {
1265 let visible = match is_valid_candidate(
1266 table,
1267 name,
1268 receiver_ty,
1269 item,
1270 self_ty,
1271 visible_from_module,
1272 ) {
1273 IsValidCandidate::Yes => true,
1274 IsValidCandidate::NotVisible => false,
1275 IsValidCandidate::No => continue,
1276 };
1277 callback(receiver_adjustments.clone().unwrap_or_default(), item, visible)?;
1278 }
1279 }
1280 ControlFlow::Continue(())
1281 }
1282 }
1283
1284 /// Returns the receiver type for the index trait call.
resolve_indexing_op( db: &dyn HirDatabase, env: Arc<TraitEnvironment>, ty: Canonical<Ty>, index_trait: TraitId, ) -> Option<ReceiverAdjustments>1285 pub(crate) fn resolve_indexing_op(
1286 db: &dyn HirDatabase,
1287 env: Arc<TraitEnvironment>,
1288 ty: Canonical<Ty>,
1289 index_trait: TraitId,
1290 ) -> Option<ReceiverAdjustments> {
1291 let mut table = InferenceTable::new(db, env.clone());
1292 let ty = table.instantiate_canonical(ty);
1293 let deref_chain = autoderef_method_receiver(&mut table, ty);
1294 for (ty, adj) in deref_chain {
1295 let goal = generic_implements_goal(db, table.trait_env.clone(), index_trait, &ty);
1296 if db
1297 .trait_solve(table.trait_env.krate, table.trait_env.block, goal.cast(Interner))
1298 .is_some()
1299 {
1300 return Some(adj);
1301 }
1302 }
1303 None
1304 }
1305
1306 macro_rules! check_that {
1307 ($cond:expr) => {
1308 if !$cond {
1309 return IsValidCandidate::No;
1310 }
1311 };
1312 }
1313
is_valid_candidate( table: &mut InferenceTable<'_>, name: Option<&Name>, receiver_ty: Option<&Ty>, item: AssocItemId, self_ty: &Ty, visible_from_module: Option<ModuleId>, ) -> IsValidCandidate1314 fn is_valid_candidate(
1315 table: &mut InferenceTable<'_>,
1316 name: Option<&Name>,
1317 receiver_ty: Option<&Ty>,
1318 item: AssocItemId,
1319 self_ty: &Ty,
1320 visible_from_module: Option<ModuleId>,
1321 ) -> IsValidCandidate {
1322 let db = table.db;
1323 match item {
1324 AssocItemId::FunctionId(f) => {
1325 is_valid_fn_candidate(table, f, name, receiver_ty, self_ty, visible_from_module)
1326 }
1327 AssocItemId::ConstId(c) => {
1328 check_that!(receiver_ty.is_none());
1329 check_that!(name.map_or(true, |n| db.const_data(c).name.as_ref() == Some(n)));
1330
1331 if let Some(from_module) = visible_from_module {
1332 if !db.const_visibility(c).is_visible_from(db.upcast(), from_module) {
1333 cov_mark::hit!(const_candidate_not_visible);
1334 return IsValidCandidate::NotVisible;
1335 }
1336 }
1337 if let ItemContainerId::ImplId(impl_id) = c.lookup(db.upcast()).container {
1338 let self_ty_matches = table.run_in_snapshot(|table| {
1339 let expected_self_ty = TyBuilder::impl_self_ty(db, impl_id)
1340 .fill_with_inference_vars(table)
1341 .build();
1342 table.unify(&expected_self_ty, self_ty)
1343 });
1344 if !self_ty_matches {
1345 cov_mark::hit!(const_candidate_self_type_mismatch);
1346 return IsValidCandidate::No;
1347 }
1348 }
1349 IsValidCandidate::Yes
1350 }
1351 _ => IsValidCandidate::No,
1352 }
1353 }
1354
1355 enum IsValidCandidate {
1356 Yes,
1357 No,
1358 NotVisible,
1359 }
1360
is_valid_fn_candidate( table: &mut InferenceTable<'_>, fn_id: FunctionId, name: Option<&Name>, receiver_ty: Option<&Ty>, self_ty: &Ty, visible_from_module: Option<ModuleId>, ) -> IsValidCandidate1361 fn is_valid_fn_candidate(
1362 table: &mut InferenceTable<'_>,
1363 fn_id: FunctionId,
1364 name: Option<&Name>,
1365 receiver_ty: Option<&Ty>,
1366 self_ty: &Ty,
1367 visible_from_module: Option<ModuleId>,
1368 ) -> IsValidCandidate {
1369 let db = table.db;
1370 let data = db.function_data(fn_id);
1371
1372 check_that!(name.map_or(true, |n| n == &data.name));
1373 if let Some(from_module) = visible_from_module {
1374 if !db.function_visibility(fn_id).is_visible_from(db.upcast(), from_module) {
1375 cov_mark::hit!(autoderef_candidate_not_visible);
1376 return IsValidCandidate::NotVisible;
1377 }
1378 }
1379 table.run_in_snapshot(|table| {
1380 let container = fn_id.lookup(db.upcast()).container;
1381 let (impl_subst, expect_self_ty) = match container {
1382 ItemContainerId::ImplId(it) => {
1383 let subst =
1384 TyBuilder::subst_for_def(db, it, None).fill_with_inference_vars(table).build();
1385 let self_ty = db.impl_self_ty(it).substitute(Interner, &subst);
1386 (subst, self_ty)
1387 }
1388 ItemContainerId::TraitId(it) => {
1389 let subst =
1390 TyBuilder::subst_for_def(db, it, None).fill_with_inference_vars(table).build();
1391 let self_ty = subst.at(Interner, 0).assert_ty_ref(Interner).clone();
1392 (subst, self_ty)
1393 }
1394 _ => unreachable!(),
1395 };
1396
1397 let fn_subst = TyBuilder::subst_for_def(db, fn_id, Some(impl_subst.clone()))
1398 .fill_with_inference_vars(table)
1399 .build();
1400
1401 check_that!(table.unify(&expect_self_ty, self_ty));
1402
1403 if let Some(receiver_ty) = receiver_ty {
1404 check_that!(data.has_self_param());
1405
1406 let sig = db.callable_item_signature(fn_id.into());
1407 let expected_receiver =
1408 sig.map(|s| s.params()[0].clone()).substitute(Interner, &fn_subst);
1409
1410 check_that!(table.unify(receiver_ty, &expected_receiver));
1411 }
1412
1413 if let ItemContainerId::ImplId(impl_id) = container {
1414 // We need to consider the bounds on the impl to distinguish functions of the same name
1415 // for a type.
1416 let predicates = db.generic_predicates(impl_id.into());
1417 let valid = predicates
1418 .iter()
1419 .map(|predicate| {
1420 let (p, b) = predicate
1421 .clone()
1422 .substitute(Interner, &impl_subst)
1423 // Skipping the inner binders is ok, as we don't handle quantified where
1424 // clauses yet.
1425 .into_value_and_skipped_binders();
1426 stdx::always!(b.len(Interner) == 0);
1427 p
1428 })
1429 // It's ok to get ambiguity here, as we may not have enough information to prove
1430 // obligations. We'll check if the user is calling the selected method properly
1431 // later anyway.
1432 .all(|p| table.try_obligation(p.cast(Interner)).is_some());
1433 match valid {
1434 true => IsValidCandidate::Yes,
1435 false => IsValidCandidate::No,
1436 }
1437 } else {
1438 // For `ItemContainerId::TraitId`, we check if `self_ty` implements the trait in
1439 // `iterate_trait_method_candidates()`.
1440 // For others, this function shouldn't be called.
1441 IsValidCandidate::Yes
1442 }
1443 })
1444 }
1445
implements_trait( ty: &Canonical<Ty>, db: &dyn HirDatabase, env: Arc<TraitEnvironment>, trait_: TraitId, ) -> bool1446 pub fn implements_trait(
1447 ty: &Canonical<Ty>,
1448 db: &dyn HirDatabase,
1449 env: Arc<TraitEnvironment>,
1450 trait_: TraitId,
1451 ) -> bool {
1452 let goal = generic_implements_goal(db, env.clone(), trait_, ty);
1453 let solution = db.trait_solve(env.krate, env.block, goal.cast(Interner));
1454
1455 solution.is_some()
1456 }
1457
implements_trait_unique( ty: &Canonical<Ty>, db: &dyn HirDatabase, env: Arc<TraitEnvironment>, trait_: TraitId, ) -> bool1458 pub fn implements_trait_unique(
1459 ty: &Canonical<Ty>,
1460 db: &dyn HirDatabase,
1461 env: Arc<TraitEnvironment>,
1462 trait_: TraitId,
1463 ) -> bool {
1464 let goal = generic_implements_goal(db, env.clone(), trait_, ty);
1465 let solution = db.trait_solve(env.krate, env.block, goal.cast(Interner));
1466
1467 matches!(solution, Some(crate::Solution::Unique(_)))
1468 }
1469
1470 /// This creates Substs for a trait with the given Self type and type variables
1471 /// for all other parameters, to query Chalk with it.
generic_implements_goal( db: &dyn HirDatabase, env: Arc<TraitEnvironment>, trait_: TraitId, self_ty: &Canonical<Ty>, ) -> Canonical<InEnvironment<super::DomainGoal>>1472 fn generic_implements_goal(
1473 db: &dyn HirDatabase,
1474 env: Arc<TraitEnvironment>,
1475 trait_: TraitId,
1476 self_ty: &Canonical<Ty>,
1477 ) -> Canonical<InEnvironment<super::DomainGoal>> {
1478 let mut kinds = self_ty.binders.interned().to_vec();
1479 let trait_ref = TyBuilder::trait_ref(db, trait_)
1480 .push(self_ty.value.clone())
1481 .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len())
1482 .build();
1483 kinds.extend(trait_ref.substitution.iter(Interner).skip(1).map(|x| {
1484 let vk = match x.data(Interner) {
1485 chalk_ir::GenericArgData::Ty(_) => {
1486 chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)
1487 }
1488 chalk_ir::GenericArgData::Lifetime(_) => chalk_ir::VariableKind::Lifetime,
1489 chalk_ir::GenericArgData::Const(c) => {
1490 chalk_ir::VariableKind::Const(c.data(Interner).ty.clone())
1491 }
1492 };
1493 chalk_ir::WithKind::new(vk, UniverseIndex::ROOT)
1494 }));
1495 let obligation = trait_ref.cast(Interner);
1496 Canonical {
1497 binders: CanonicalVarKinds::from_iter(Interner, kinds),
1498 value: InEnvironment::new(&env.env, obligation),
1499 }
1500 }
1501
autoderef_method_receiver( table: &mut InferenceTable<'_>, ty: Ty, ) -> Vec<(Canonical<Ty>, ReceiverAdjustments)>1502 fn autoderef_method_receiver(
1503 table: &mut InferenceTable<'_>,
1504 ty: Ty,
1505 ) -> Vec<(Canonical<Ty>, ReceiverAdjustments)> {
1506 let mut deref_chain: Vec<_> = Vec::new();
1507 let mut autoderef = autoderef::Autoderef::new(table, ty);
1508 while let Some((ty, derefs)) = autoderef.next() {
1509 deref_chain.push((
1510 autoderef.table.canonicalize(ty).value,
1511 ReceiverAdjustments { autoref: None, autoderefs: derefs, unsize_array: false },
1512 ));
1513 }
1514 // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!)
1515 if let Some((TyKind::Array(parameters, _), binders, adj)) =
1516 deref_chain.last().map(|(ty, adj)| (ty.value.kind(Interner), ty.binders.clone(), adj))
1517 {
1518 let unsized_ty = TyKind::Slice(parameters.clone()).intern(Interner);
1519 deref_chain.push((
1520 Canonical { value: unsized_ty, binders },
1521 ReceiverAdjustments { unsize_array: true, ..adj.clone() },
1522 ));
1523 }
1524 deref_chain
1525 }
1526