pub fn translate_substs<'tcx>(
    infcx: &InferCtxt<'tcx>,
    param_env: ParamEnv<'tcx>,
    source_impl: DefId,
    source_substs: SubstsRef<'tcx>,
    target_node: Node
) -> SubstsRef<'tcx>
Expand description

Given a subst for the requested impl, translate it to a subst appropriate for the actual item definition (whether it be in that impl, a parent impl, or the trait).

When we have selected one impl, but are actually using item definitions from a parent impl providing a default, we need a way to translate between the type parameters of the two impls. Here the source_impl is the one we’ve selected, and source_substs is a substitution of its generics. And target_node is the impl/trait we’re actually going to get the definition from. The resulting substitution will map from target_node’s generics to source_impl’s generics as instantiated by source_subst.

For example, consider the following scenario:

trait Foo { ... }
impl<T, U> Foo for (T, U) { ... }  // target impl
impl<V> Foo for (V, V) { ... }     // source impl

Suppose we have selected “source impl” with V instantiated with u32. This function will produce a substitution with T and U both mapping to u32.

where-clauses add some trickiness here, because they can be used to “define” an argument indirectly:

impl<'a, I, T: 'a> Iterator for Cloned<I>
   where I: Iterator<Item = &'a T>, T: Clone

In a case like this, the substitution for T is determined indirectly, through associated type projection. We deal with such cases by using fulfillment to relate the two impls, requiring that all projections are resolved.