pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                          span: Span,
                                          self_expr: Option<&hir::Expr>,
                                          m_name: ast::Name,
                                          trait_def_id: DefId,
                                          autoderefs: usize,
                                          unsize: bool,
                                          self_ty: ty::Ty<'tcx>,
                                          opt_input_types: Option<Vec<ty::Ty<'tcx>>>)
                                          -> Option<ty::MethodCallee<'tcx>>
{
    debug!("lookup_in_trait_adjusted(self_ty={:?}, self_expr={:?}, m_name={}, trait_def_id={:?})",
           self_ty,
           self_expr,
           m_name,
           trait_def_id);

    let trait_def = fcx.tcx().lookup_trait_def(trait_def_id);

    let type_parameter_defs = trait_def.generics.types.get_slice(subst::TypeSpace);
    let expected_number_of_input_types = type_parameter_defs.len();

    assert_eq!(trait_def.generics.types.len(subst::FnSpace), 0);
    assert!(trait_def.generics.regions.is_empty());

    // Construct a trait-reference `self_ty : Trait<input_tys>`
    let mut substs = subst::Substs::new_trait(Vec::new(), Vec::new(), self_ty);

    match opt_input_types {
        Some(input_types) => {
            assert_eq!(expected_number_of_input_types, input_types.len());
            substs.types.replace(subst::ParamSpace::TypeSpace, input_types);
        }

        None => {
            fcx.inh.infcx.type_vars_for_defs(
                span,
                subst::ParamSpace::TypeSpace,
                &mut substs,
                type_parameter_defs);
        }
    }

    let trait_ref = ty::TraitRef::new(trait_def_id, fcx.tcx().mk_substs(substs));

    // Construct an obligation
    let poly_trait_ref = trait_ref.to_poly_trait_ref();
    let obligation = traits::Obligation::misc(span,
                                              fcx.body_id,
                                              poly_trait_ref.to_predicate());

    // Now we want to know if this can be matched
    let mut selcx = traits::SelectionContext::new(fcx.infcx());
    if !selcx.evaluate_obligation(&obligation) {
        debug!("--> Cannot match obligation");
        return None; // Cannot be matched, no such method resolution is possible.
    }

    // Trait must have a method named `m_name` and it should not have
    // type parameters or early-bound regions.
    let tcx = fcx.tcx();
    let method_item = trait_item(tcx, trait_def_id, m_name).unwrap();
    let method_ty = method_item.as_opt_method().unwrap();
    assert_eq!(method_ty.generics.types.len(subst::FnSpace), 0);
    assert_eq!(method_ty.generics.regions.len(subst::FnSpace), 0);

    debug!("lookup_in_trait_adjusted: method_item={:?} method_ty={:?}",
           method_item, method_ty);

    // Instantiate late-bound regions and substitute the trait
    // parameters into the method type to get the actual method type.
    //
    // NB: Instantiate late-bound regions first so that
    // `instantiate_type_scheme` can normalize associated types that
    // may reference those regions.
    let fn_sig = fcx.infcx().replace_late_bound_regions_with_fresh_var(span,
                                                                       infer::FnCall,
                                                                       &method_ty.fty.sig).0;
    let fn_sig = fcx.instantiate_type_scheme(span, trait_ref.substs, &fn_sig);
    let transformed_self_ty = fn_sig.inputs[0];
    let fty = tcx.mk_fn(None, tcx.mk_bare_fn(ty::BareFnTy {
        sig: ty::Binder(fn_sig),
        unsafety: method_ty.fty.unsafety,
        abi: method_ty.fty.abi.clone(),
    }));

    debug!("lookup_in_trait_adjusted: matched method fty={:?} obligation={:?}",
           fty,
           obligation);

    // Register obligations for the parameters.  This will include the
    // `Self` parameter, which in turn has a bound of the main trait,
    // so this also effectively registers `obligation` as well.  (We
    // used to register `obligation` explicitly, but that resulted in
    // double error messages being reported.)
    //
    // Note that as the method comes from a trait, it should not have
    // any late-bound regions appearing in its bounds.
    let method_bounds = fcx.instantiate_bounds(span, trait_ref.substs, &method_ty.predicates);
    assert!(!method_bounds.has_escaping_regions());
    fcx.add_obligations_for_parameters(
        traits::ObligationCause::misc(span, fcx.body_id),
        &method_bounds);

    // FIXME(#18653) -- Try to resolve obligations, giving us more
    // typing information, which can sometimes be needed to avoid
    // pathological region inference failures.
    fcx.select_new_obligations();

    // Insert any adjustments needed (always an autoref of some mutability).
    match self_expr {
        None => { }

        Some(self_expr) => {
            debug!("lookup_in_trait_adjusted: inserting adjustment if needed \
                   (self-id={}, autoderefs={}, unsize={}, explicit_self={:?})",
                   self_expr.id, autoderefs, unsize,
                   method_ty.explicit_self);

            match method_ty.explicit_self {
                ty::ByValueExplicitSelfCategory => {
                    // Trait method is fn(self), no transformation needed.
                    assert!(!unsize);
                    fcx.write_autoderef_adjustment(self_expr.id, autoderefs);
                }

                ty::ByReferenceExplicitSelfCategory(..) => {
                    // Trait method is fn(&self) or fn(&mut self), need an
                    // autoref. Pull the region etc out of the type of first argument.
                    match transformed_self_ty.sty {
                        ty::TyRef(region, ty::TypeAndMut { mutbl, ty: _ }) => {
                            fcx.write_adjustment(self_expr.id,
                                ty::AdjustDerefRef(ty::AutoDerefRef {
                                    autoderefs: autoderefs,
                                    autoref: Some(ty::AutoPtr(region, mutbl)),
                                    unsize: if unsize {
                                        Some(transformed_self_ty)
                                    } else {
                                        None
                                    }
                                }));
                        }

                        _ => {
                            fcx.tcx().sess.span_bug(
                                span,
                                &format!(
                                    "trait method is &self but first arg is: {}",
                                    transformed_self_ty));
                        }
                    }
                }

                _ => {
                    fcx.tcx().sess.span_bug(
                        span,
                        &format!(
                            "unexpected explicit self type in operator method: {:?}",
                            method_ty.explicit_self));
                }
            }
        }
    }

    let callee = ty::MethodCallee {
        def_id: method_item.def_id(),
        ty: fty,
        substs: trait_ref.substs
    };

    debug!("callee = {:?}", callee);

    Some(callee)
}
/// `lookup_in_trait_adjusted` is used for overloaded operators. It does a very narrow slice of
/// what the normal probe/confirm path does. In particular, it doesn't really do any probing: it
/// simply constructs an obligation for a particular trait with the given self-type and checks
/// whether that trait is implemented.
///
/// FIXME(#18741) -- It seems likely that we can consolidate some of this code with the other
/// method-lookup code. In particular, autoderef on index is basically identical to autoderef with
/// normal probes, except that the test also looks for built-in indexing. Also, the second half of
/// this method is basically the same as confirmation.
`lookup_in_trait_adjusted` is used for overloaded operators. It does a very narrow slice of
what the normal probe/confirm path does. In particular, it doesn't really do any probing: it
simply constructs an obligation for a particular trait with the given self-type and checks
whether that trait is implemented.


` lookup_in_trait_adjusted ` is used for overloaded operators . It does a very narrow slice of what the normal probe / confirm path does . In particular it doesn ' t really do any probing : it simply constructs an obligation for a particular trait with the given self - type and checks whether that trait is implemented .
pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                          span: Span,
                                          self_expr: Option<&hir::Expr>,
                                          m_name: ast::Name,
                                          trait_def_id: DefId,
                                          autoderefs: usize,
                                          unsize: bool,
                                          self_ty: ty::Ty<'tcx>,
                                          opt_input_types: Option<Vec<ty::Ty<'tcx>>>)
                                          -> Option<ty::MethodCallee<'tcx>>
{
    debug!("lookup_in_trait_adjusted(self_ty={:?}, self_expr={:?}, m_name={}, trait_def_id={:?})",
           self_ty,
           self_expr,
           m_name,
           trait_def_id);
    let trait_def = fcx.tcx().lookup_trait_def(trait_def_id);
    let type_parameter_defs = trait_def.generics.types.get_slice(subst::TypeSpace);
    let expected_number_of_input_types = type_parameter_defs.len();
    assert_eq!(trait_def.generics.types.len(subst::FnSpace), 0);
    assert!(trait_def.generics.regions.is_empty());
    // Construct a trait-reference `self_ty : Trait<input_tys>`
    let mut substs = subst::Substs::new_trait(Vec::new(), Vec::new(), self_ty);
    match opt_input_types {
        Some(input_types) => {
            assert_eq!(expected_number_of_input_types, input_types.len());
            substs.types.replace(subst::ParamSpace::TypeSpace, input_types);
        }
        None => {
            fcx.inh.infcx.type_vars_for_defs(
                span,
                subst::ParamSpace::TypeSpace,
                &mut substs,
                type_parameter_defs);
        }
    }
    let trait_ref = ty::TraitRef::new(trait_def_id, fcx.tcx().mk_substs(substs));
    // Construct an obligation
    let poly_trait_ref = trait_ref.to_poly_trait_ref();
    let obligation = traits::Obligation::misc(span,
                                              fcx.body_id,
                                              poly_trait_ref.to_predicate());
    // Now we want to know if this can be matched
    let mut selcx = traits::SelectionContext::new(fcx.infcx());
    if !selcx.evaluate_obligation(&obligation) {
        debug!("--> Cannot match obligation");
        return None; // Cannot be matched, no such method resolution is possible.
    }
    // Trait must have a method named `m_name` and it should not have
    // type parameters or early-bound regions.
    let tcx = fcx.tcx();
    let method_item = trait_item(tcx, trait_def_id, m_name).unwrap();
    let method_ty = method_item.as_opt_method().unwrap();
    assert_eq!(method_ty.generics.types.len(subst::FnSpace), 0);
    assert_eq!(method_ty.generics.regions.len(subst::FnSpace), 0);
    debug!("lookup_in_trait_adjusted: method_item={:?} method_ty={:?}",
           method_item, method_ty);
    // Instantiate late-bound regions and substitute the trait
    // parameters into the method type to get the actual method type.
    //
    // NB: Instantiate late-bound regions first so that
    // `instantiate_type_scheme` can normalize associated types that
    // may reference those regions.
    let fn_sig = fcx.infcx().replace_late_bound_regions_with_fresh_var(span,
                                                                       infer::FnCall,
                                                                       &method_ty.fty.sig).0;
    let fn_sig = fcx.instantiate_type_scheme(span, trait_ref.substs, &fn_sig);
    let transformed_self_ty = fn_sig.inputs[0];
    let fty = tcx.mk_fn(None, tcx.mk_bare_fn(ty::BareFnTy {
        sig: ty::Binder(fn_sig),
        unsafety: method_ty.fty.unsafety,
        abi: method_ty.fty.abi.clone(),
    }));
    debug!("lookup_in_trait_adjusted: matched method fty={:?} obligation={:?}",
           fty,
           obligation);
    // Register obligations for the parameters.  This will include the
    // `Self` parameter, which in turn has a bound of the main trait,
    // so this also effectively registers `obligation` as well.  (We
    // used to register `obligation` explicitly, but that resulted in
    // double error messages being reported.)
    //
    // Note that as the method comes from a trait, it should not have
    // any late-bound regions appearing in its bounds.
    let method_bounds = fcx.instantiate_bounds(span, trait_ref.substs, &method_ty.predicates);
    assert!(!method_bounds.has_escaping_regions());
    fcx.add_obligations_for_parameters(
        traits::ObligationCause::misc(span, fcx.body_id),
        &method_bounds);
    // FIXME(#18653) -- Try to resolve obligations, giving us more
    // typing information, which can sometimes be needed to avoid
    // pathological region inference failures.
    fcx.select_new_obligations();
    // Insert any adjustments needed (always an autoref of some mutability).
    match self_expr {
        None => { }
        Some(self_expr) => {
            debug!("lookup_in_trait_adjusted: inserting adjustment if needed \
                   (self-id={}, autoderefs={}, unsize={}, explicit_self={:?})",
                   self_expr.id, autoderefs, unsize,
                   method_ty.explicit_self);
            match method_ty.explicit_self {
                ty::ByValueExplicitSelfCategory => {
                    // Trait method is fn(self), no transformation needed.
                    assert!(!unsize);
                    fcx.write_autoderef_adjustment(self_expr.id, autoderefs);
                }
                ty::ByReferenceExplicitSelfCategory(..) => {
                    // Trait method is fn(&self) or fn(&mut self), need an
                    // autoref. Pull the region etc out of the type of first argument.
                    match transformed_self_ty.sty {
                        ty::TyRef(region, ty::TypeAndMut { mutbl, ty: _ }) => {
                            fcx.write_adjustment(self_expr.id,
                                ty::AdjustDerefRef(ty::AutoDerefRef {
                                    autoderefs: autoderefs,
                                    autoref: Some(ty::AutoPtr(region, mutbl)),
                                    unsize: if unsize {
                                        Some(transformed_self_ty)
                                    } else {
                                        None
                                    }
                                }));
                        }
                        _ => {
                            fcx.tcx().sess.span_bug(
                                span,
                                &format!(
                                    "trait method is &self but first arg is: {}",
                                    transformed_self_ty));
                        }
                    }
                }
                _ => {
                    fcx.tcx().sess.span_bug(
                        span,
                        &format!(
                            "unexpected explicit self type in operator method: {:?}",
                            method_ty.explicit_self));
                }
            }
        }
    }
    let callee = ty::MethodCallee {
        def_id: method_item.def_id(),
        ty: fty,
        substs: trait_ref.substs
    };
    debug!("callee = {:?}", callee);
    Some(callee)
}
pub fn lookup_in_trait_adjusted < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > , span : Span , self_expr : Option < & hir :: Expr > , m_name : ast :: Name , trait_def_id : DefId , autoderefs : usize , unsize : bool , self_ty : ty :: Ty < ' tcx > , opt_input_types : Option < Vec < ty :: Ty < ' tcx > > > ) -> Option < ty :: MethodCallee < ' tcx > > { debug ! ( " " self_ty self_expr m_name trait_def_id ) ; let trait_def = fcx . tcx ( ) . lookup_trait_def ( trait_def_id ) ; let type_parameter_defs = trait_def . generics . types . get_slice ( subst :: TypeSpace ) ; let expected_number_of_input_types = type_parameter_defs . len ( ) ; assert_eq ! ( trait_def generics types len ( subst FnSpace ) 0 ) ; assert ! ( trait_def generics regions is_empty ( ) ) ; // Construct a trait-reference `self_ty : Trait<input_tys>` let mut substs = subst :: Substs :: new_trait ( Vec :: new ( ) , Vec :: new ( ) , self_ty ) ; match opt_input_types { Some ( input_types ) => { assert_eq ! ( expected_number_of_input_types input_types len ( ) ) ; substs . types . replace ( subst :: ParamSpace :: TypeSpace , input_types ) ; } None => { fcx . inh . infcx . type_vars_for_defs ( span , subst :: ParamSpace :: TypeSpace , & mut substs , type_parameter_defs ) ; } } let trait_ref = ty :: TraitRef :: new ( trait_def_id , fcx . tcx ( ) . mk_substs ( substs ) ) ; // Construct an obligation let poly_trait_ref = trait_ref . to_poly_trait_ref ( ) ; let obligation = traits :: Obligation :: misc ( span , fcx . body_id , poly_trait_ref . to_predicate ( ) ) ; // Now we want to know if this can be matched let mut selcx = traits :: SelectionContext :: new ( fcx . infcx ( ) ) ; if ! selcx . evaluate_obligation ( & obligation ) { debug ! ( " " ) ; return None ; // Cannot be matched, no such method resolution is possible. } // Trait must have a method named `m_name` and it should not have // type parameters or early-bound regions. let tcx = fcx . tcx ( ) ; let method_item = trait_item ( tcx , trait_def_id , m_name ) . unwrap ( ) ; let method_ty = method_item . as_opt_method ( ) . unwrap ( ) ; assert_eq ! ( method_ty generics types len ( subst FnSpace ) 0 ) ; assert_eq ! ( method_ty generics regions len ( subst FnSpace ) 0 ) ; debug ! ( " " method_item method_ty ) ; // Instantiate late-bound regions and substitute the trait // parameters into the method type to get the actual method type. // // NB: Instantiate late-bound regions first so that // `instantiate_type_scheme` can normalize associated types that // may reference those regions. let fn_sig = fcx . infcx ( ) . replace_late_bound_regions_with_fresh_var ( span , infer :: FnCall , & method_ty . fty . sig ) . 0 ; let fn_sig = fcx . instantiate_type_scheme ( span , trait_ref . substs , & fn_sig ) ; let transformed_self_ty = fn_sig . inputs [ 0 ] ; let fty = tcx . mk_fn ( None , tcx . mk_bare_fn ( ty :: BareFnTy { sig : ty :: Binder ( fn_sig ) , unsafety : method_ty . fty . unsafety , abi : method_ty . fty . abi . clone ( ) , } ) ) ; debug ! ( " " fty obligation ) ; // Register obligations for the parameters.  This will include the // `Self` parameter, which in turn has a bound of the main trait, // so this also effectively registers `obligation` as well.  (We // used to register `obligation` explicitly, but that resulted in // double error messages being reported.) // // Note that as the method comes from a trait, it should not have // any late-bound regions appearing in its bounds. let method_bounds = fcx . instantiate_bounds ( span , trait_ref . substs , & method_ty . predicates ) ; assert ! ( method_bounds has_escaping_regions ( ) ) ; fcx . add_obligations_for_parameters ( traits :: ObligationCause :: misc ( span , fcx . body_id ) , & method_bounds ) ; // FIXME(#18653) -- Try to resolve obligations, giving us more // typing information, which can sometimes be needed to avoid // pathological region inference failures. fcx . select_new_obligations ( ) ; // Insert any adjustments needed (always an autoref of some mutability). match self_expr { None => { } Some ( self_expr ) => { debug ! ( " \
 " self_expr id autoderefs unsize method_ty explicit_self ) ; match method_ty . explicit_self { ty :: ByValueExplicitSelfCategory => { // Trait method is fn(self), no transformation needed. assert ! ( unsize ) ; fcx . write_autoderef_adjustment ( self_expr . id , autoderefs ) ; } ty :: ByReferenceExplicitSelfCategory ( .. ) => { // Trait method is fn(&self) or fn(&mut self), need an // autoref. Pull the region etc out of the type of first argument. match transformed_self_ty . sty { ty :: TyRef ( region , ty :: TypeAndMut { mutbl , ty : _ } ) => { fcx . write_adjustment ( self_expr . id , ty :: AdjustDerefRef ( ty :: AutoDerefRef { autoderefs : autoderefs , autoref : Some ( ty :: AutoPtr ( region , mutbl ) ) , unsize : if unsize { Some ( transformed_self_ty ) } else { None } } ) ) ; } _ => { fcx . tcx ( ) . sess . span_bug ( span , & format ! ( " " transformed_self_ty ) ) ; } } } _ => { fcx . tcx ( ) . sess . span_bug ( span , & format ! ( " " method_ty explicit_self ) ) ; } } } } let callee = ty :: MethodCallee { def_id : method_item . def_id ( ) , ty : fty , substs : trait_ref . substs } ; debug ! ( " " callee ) ; Some ( callee ) }
`lookup_in_trait_adjusted` is used for overloaded operators.
` lookup_in_trait_adjusted ` is used for overloaded operators .
fcx
&FnCtxt<'a, 'tcx>
span
Span
self_expr
Option<&hir::Expr>
m_name
ast::Name
trait_def_id
DefId
autoderefs
usize
unsize
bool
self_ty
ty::Ty<'tcx>
opt_input_types
Option<Vec<ty::Ty<'tcx>>>
fcx
&FnCtxt<'a, 'tcx>
span
Span
self_expr
Option<&hir::Expr>
m_name
ast::Name
trait_def_id
DefId
autoderefs
usize
unsize
bool
self_ty
ty::Ty<'tcx>
opt_input_types
Option<Vec<ty::Ty<'tcx>>>