pub fn iterate_method_candidates<T>(
    ty: &Canonical<Ty>,
    db: &dyn HirDatabase,
    env: Arc<TraitEnvironment>,
    krate: CrateId,
    traits_in_scope: &FxHashSet<TraitId>,
    name: Option<&Name>,
    mode: LookupMode,
    mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
) -> Option<T> {
    match mode {
        LookupMode::MethodCall => {
            // For method calls, rust first does any number of autoderef, and then one
            // autoref (i.e. when the method takes &self or &mut self). We just ignore
            // the autoref currently -- when we find a method matching the given name,
            // we assume it fits.

            // Also note that when we've got a receiver like &S, even if the method we
            // find in the end takes &self, we still do the autoderef step (just as
            // rustc does an autoderef and then autoref again).
            let ty = InEnvironment { value: ty.clone(), environment: env.clone() };

            // We have to be careful about the order we're looking at candidates
            // in here. Consider the case where we're resolving `x.clone()`
            // where `x: &Vec<_>`. This resolves to the clone method with self
            // type `Vec<_>`, *not* `&_`. I.e. we need to consider methods where
            // the receiver type exactly matches before cases where we have to
            // do autoref. But in the autoderef steps, the `&_` self type comes
            // up *before* the `Vec<_>` self type.
            //
            // On the other hand, we don't want to just pick any by-value method
            // before any by-autoref method; it's just that we need to consider
            // the methods by autoderef order of *receiver types*, not *self
            // types*.

            let deref_chain = autoderef_method_receiver(db, krate, ty);
            for i in 0..deref_chain.len() {
                if let Some(result) = iterate_method_candidates_with_autoref(
                    &deref_chain[i..],
                    db,
                    env.clone(),
                    krate,
                    traits_in_scope,
                    name,
                    &mut callback,
                ) {
                    return Some(result);
                }
            }
            None
        }
        LookupMode::Path => {
            // No autoderef for path lookups
            iterate_method_candidates_for_self_ty(
                &ty,
                db,
                env,
                krate,
                traits_in_scope,
                name,
                &mut callback,
            )
        }
    }
}
// This would be nicer if it just returned an iterator, but that runs into
// lifetime problems, because we need to borrow temp `CrateImplDefs`.
// FIXME add a context type here?
This would be nicer if it just returned an iterator, but that runs into
lifetime problems, because we need to borrow temp `CrateImplDefs`.
This would be nicer if it just returned an iterator but that runs into lifetime problems because we need to borrow temp ` CrateImplDefs ` .
pub fn iterate_method_candidates<T>(
    ty: &Canonical<Ty>,
    db: &dyn HirDatabase,
    env: Arc<TraitEnvironment>,
    krate: CrateId,
    traits_in_scope: &FxHashSet<TraitId>,
    name: Option<&Name>,
    mode: LookupMode,
    mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
) -> Option<T> {
    match mode {
        LookupMode::MethodCall => {
            // For method calls, rust first does any number of autoderef, and then one
            // autoref (i.e. when the method takes &self or &mut self). We just ignore
            // the autoref currently -- when we find a method matching the given name,
            // we assume it fits.
            // Also note that when we've got a receiver like &S, even if the method we
            // find in the end takes &self, we still do the autoderef step (just as
            // rustc does an autoderef and then autoref again).
            let ty = InEnvironment { value: ty.clone(), environment: env.clone() };
            // We have to be careful about the order we're looking at candidates
            // in here. Consider the case where we're resolving `x.clone()`
            // where `x: &Vec<_>`. This resolves to the clone method with self
            // type `Vec<_>`, *not* `&_`. I.e. we need to consider methods where
            // the receiver type exactly matches before cases where we have to
            // do autoref. But in the autoderef steps, the `&_` self type comes
            // up *before* the `Vec<_>` self type.
            //
            // On the other hand, we don't want to just pick any by-value method
            // before any by-autoref method; it's just that we need to consider
            // the methods by autoderef order of *receiver types*, not *self
            // types*.
            let deref_chain = autoderef_method_receiver(db, krate, ty);
            for i in 0..deref_chain.len() {
                if let Some(result) = iterate_method_candidates_with_autoref(
                    &deref_chain[i..],
                    db,
                    env.clone(),
                    krate,
                    traits_in_scope,
                    name,
                    &mut callback,
                ) {
                    return Some(result);
                }
            }
            None
        }
        LookupMode::Path => {
            // No autoderef for path lookups
            iterate_method_candidates_for_self_ty(
                &ty,
                db,
                env,
                krate,
                traits_in_scope,
                name,
                &mut callback,
            )
        }
    }
}
pub fn iterate_method_candidates < T > ( ty : & Canonical < Ty > , db : & dyn HirDatabase , env : Arc < TraitEnvironment > , krate : CrateId , traits_in_scope : & FxHashSet < TraitId > , name : Option < & Name > , mode : LookupMode , mut callback : impl FnMut ( & Ty , AssocItemId ) -> Option < T > , ) -> Option < T > { match mode { LookupMode :: MethodCall => { // For method calls, rust first does any number of autoderef, and then one // autoref (i.e. when the method takes &self or &mut self). We just ignore // the autoref currently -- when we find a method matching the given name, // we assume it fits. // Also note that when we've got a receiver like &S, even if the method we // find in the end takes &self, we still do the autoderef step (just as // rustc does an autoderef and then autoref again). let ty = InEnvironment { value : ty . clone ( ) , environment : env . clone ( ) } ; // We have to be careful about the order we're looking at candidates // in here. Consider the case where we're resolving `x.clone()` // where `x: &Vec<_>`. This resolves to the clone method with self // type `Vec<_>`, *not* `&_`. I.e. we need to consider methods where // the receiver type exactly matches before cases where we have to // do autoref. But in the autoderef steps, the `&_` self type comes // up *before* the `Vec<_>` self type. // // On the other hand, we don't want to just pick any by-value method // before any by-autoref method; it's just that we need to consider // the methods by autoderef order of *receiver types*, not *self // types*. let deref_chain = autoderef_method_receiver ( db , krate , ty ) ; for i in 0 .. deref_chain . len ( ) { if let Some ( result ) = iterate_method_candidates_with_autoref ( & deref_chain [ i .. ] , db , env . clone ( ) , krate , traits_in_scope , name , & mut callback , ) { return Some ( result ) ; } } None } LookupMode :: Path => { // No autoderef for path lookups iterate_method_candidates_for_self_ty ( & ty , db , env , krate , traits_in_scope , name , & mut callback , ) } } }
This would be nicer if it just returned an iterator, but that runs into
lifetime problems, because we need to borrow temp `CrateImplDefs`.
This would be nicer if it just returned an iterator but that runs into lifetime problems because we need to borrow temp ` CrateImplDefs ` .
ty
&Canonical<Ty>
db
&dyn HirDatabase
env
Arc<TraitEnvironment>
krate
CrateId
traits_in_scope
&FxHashSet<TraitId>
name
Option<&Name>
mode
LookupMode
callback
impl FnMut(&Ty, AssocItemId) -> Option<T>
ty
&Canonical<Ty>
db
&dyn HirDatabase
env
Arc<TraitEnvironment>
krate
CrateId
traits_in_scope
&FxHashSet<TraitId>
name
Option<&Name>
mode
LookupMode
callback
impl FnMut(&Ty, AssocItemId) -> Option<T>