fn trans_fn_pointer_shim<'a, 'tcx>(
    ccx: &'a CrateContext<'a, 'tcx>,
    method_instance: Instance<'tcx>,
    closure_kind: ty::ClosureKind,
    bare_fn_ty: Ty<'tcx>)
    -> ValueRef
{
    let tcx = ccx.tcx();

    // Normalize the type for better caching.
    let bare_fn_ty = tcx.normalize_associated_type(&bare_fn_ty);

    // If this is an impl of `Fn` or `FnMut` trait, the receiver is `&self`.
    let is_by_ref = match closure_kind {
        ty::ClosureKind::Fn | ty::ClosureKind::FnMut => true,
        ty::ClosureKind::FnOnce => false,
    };

    let llfnpointer = match bare_fn_ty.sty {
        ty::TyFnDef(def_id, substs, _) => {
            // Function definitions have to be turned into a pointer.
            let llfn = Callee::def(ccx, def_id, substs).reify(ccx);
            if !is_by_ref {
                // A by-value fn item is ignored, so the shim has
                // the same signature as the original function.
                return llfn;
            }
            Some(llfn)
        }
        _ => None
    };

    let bare_fn_ty_maybe_ref = if is_by_ref {
        tcx.mk_imm_ref(tcx.mk_region(ty::ReErased), bare_fn_ty)
    } else {
        bare_fn_ty
    };

    // Check if we already trans'd this shim.
    if let Some(&llval) = ccx.fn_pointer_shims().borrow().get(&bare_fn_ty_maybe_ref) {
        return llval;
    }

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

    // Construct the "tuply" version of `bare_fn_ty`. It takes two arguments: `self`,
    // which is the fn pointer, and `args`, which is the arguments tuple.
    let sig = match bare_fn_ty.sty {
        ty::TyFnDef(..,
                    &ty::BareFnTy { unsafety: hir::Unsafety::Normal,
                                    abi: Abi::Rust,
                                    ref sig }) |
        ty::TyFnPtr(&ty::BareFnTy { unsafety: hir::Unsafety::Normal,
                                    abi: Abi::Rust,
                                    ref sig }) => sig,

        _ => {
            bug!("trans_fn_pointer_shim invoked on invalid type: {}",
                 bare_fn_ty);
        }
    };
    let sig = tcx.erase_late_bound_regions_and_normalize(sig);
    let tuple_input_ty = tcx.intern_tup(sig.inputs());
    let sig = tcx.mk_fn_sig(
        [bare_fn_ty_maybe_ref, tuple_input_ty].iter().cloned(),
        sig.output(),
        false
    );
    let fn_ty = FnType::new(ccx, Abi::RustCall, &sig, &[]);
    let tuple_fn_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
        unsafety: hir::Unsafety::Normal,
        abi: Abi::RustCall,
        sig: ty::Binder(sig)
    }));
    debug!("tuple_fn_ty: {:?}", tuple_fn_ty);

    //
    let function_name = method_instance.symbol_name(ccx.shared());
    let llfn = declare::define_internal_fn(ccx, &function_name, tuple_fn_ty);
    attributes::set_frame_pointer_elimination(ccx, llfn);
    //
    let bcx = Builder::new_block(ccx, llfn, "entry-block");

    let mut llargs = get_params(llfn);

    let self_arg = llargs.remove(fn_ty.ret.is_indirect() as usize);
    let llfnpointer = llfnpointer.unwrap_or_else(|| {
        // the first argument (`self`) will be ptr to the fn pointer
        if is_by_ref {
            bcx.load(self_arg)
        } else {
            self_arg
        }
    });

    let callee = Callee {
        data: Fn(llfnpointer),
        ty: bare_fn_ty
    };
    let fn_ret = callee.ty.fn_ret();
    let fn_ty = callee.direct_fn_type(ccx, &[]);
    let llret = bcx.call(llfnpointer, &llargs, None);
    fn_ty.apply_attrs_callsite(llret);

    if fn_ret.0.is_never() {
        bcx.unreachable();
    } else {
        if fn_ty.ret.is_indirect() || fn_ty.ret.is_ignore() {
            bcx.ret_void();
        } else {
            bcx.ret(llret);
        }
    }

    ccx.fn_pointer_shims().borrow_mut().insert(bare_fn_ty_maybe_ref, llfn);

    llfn
}
/// Translates an adapter that implements the `Fn` trait for a fn
/// pointer. This is basically the equivalent of something like:
///
/// ```
/// impl<'a> Fn(&'a int) -> &'a int for fn(&int) -> &int {
///     extern "rust-abi" fn call(&self, args: (&'a int,)) -> &'a int {
///         (*self)(args.0)
///     }
/// }
/// ```
///
/// but for the bare function type given.
Translates an adapter that implements the `Fn` trait for a fn
pointer. This is basically the equivalent of something like.



but for the bare function type given.
Translates an adapter that implements the ` Fn ` trait for a fn pointer . This is basically the equivalent of something like . but for the bare function type given .
fn trans_fn_pointer_shim<'a, 'tcx>(
    ccx: &'a CrateContext<'a, 'tcx>,
    method_instance: Instance<'tcx>,
    closure_kind: ty::ClosureKind,
    bare_fn_ty: Ty<'tcx>)
    -> ValueRef
{
    let tcx = ccx.tcx();
    // Normalize the type for better caching.
    let bare_fn_ty = tcx.normalize_associated_type(&bare_fn_ty);
    // If this is an impl of `Fn` or `FnMut` trait, the receiver is `&self`.
    let is_by_ref = match closure_kind {
        ty::ClosureKind::Fn | ty::ClosureKind::FnMut => true,
        ty::ClosureKind::FnOnce => false,
    };
    let llfnpointer = match bare_fn_ty.sty {
        ty::TyFnDef(def_id, substs, _) => {
            // Function definitions have to be turned into a pointer.
            let llfn = Callee::def(ccx, def_id, substs).reify(ccx);
            if !is_by_ref {
                // A by-value fn item is ignored, so the shim has
                // the same signature as the original function.
                return llfn;
            }
            Some(llfn)
        }
        _ => None
    };
    let bare_fn_ty_maybe_ref = if is_by_ref {
        tcx.mk_imm_ref(tcx.mk_region(ty::ReErased), bare_fn_ty)
    } else {
        bare_fn_ty
    };
    // Check if we already trans'd this shim.
    if let Some(&llval) = ccx.fn_pointer_shims().borrow().get(&bare_fn_ty_maybe_ref) {
        return llval;
    }
    debug!("trans_fn_pointer_shim(bare_fn_ty={:?})",
           bare_fn_ty);
    // Construct the "tuply" version of `bare_fn_ty`. It takes two arguments: `self`,
    // which is the fn pointer, and `args`, which is the arguments tuple.
    let sig = match bare_fn_ty.sty {
        ty::TyFnDef(..,
                    &ty::BareFnTy { unsafety: hir::Unsafety::Normal,
                                    abi: Abi::Rust,
                                    ref sig }) |
        ty::TyFnPtr(&ty::BareFnTy { unsafety: hir::Unsafety::Normal,
                                    abi: Abi::Rust,
                                    ref sig }) => sig,
        _ => {
            bug!("trans_fn_pointer_shim invoked on invalid type: {}",
                 bare_fn_ty);
        }
    };
    let sig = tcx.erase_late_bound_regions_and_normalize(sig);
    let tuple_input_ty = tcx.intern_tup(sig.inputs());
    let sig = tcx.mk_fn_sig(
        [bare_fn_ty_maybe_ref, tuple_input_ty].iter().cloned(),
        sig.output(),
        false
    );
    let fn_ty = FnType::new(ccx, Abi::RustCall, &sig, &[]);
    let tuple_fn_ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
        unsafety: hir::Unsafety::Normal,
        abi: Abi::RustCall,
        sig: ty::Binder(sig)
    }));
    debug!("tuple_fn_ty: {:?}", tuple_fn_ty);
    //
    let function_name = method_instance.symbol_name(ccx.shared());
    let llfn = declare::define_internal_fn(ccx, &function_name, tuple_fn_ty);
    attributes::set_frame_pointer_elimination(ccx, llfn);
    //
    let bcx = Builder::new_block(ccx, llfn, "entry-block");
    let mut llargs = get_params(llfn);
    let self_arg = llargs.remove(fn_ty.ret.is_indirect() as usize);
    let llfnpointer = llfnpointer.unwrap_or_else(|| {
        // the first argument (`self`) will be ptr to the fn pointer
        if is_by_ref {
            bcx.load(self_arg)
        } else {
            self_arg
        }
    });
    let callee = Callee {
        data: Fn(llfnpointer),
        ty: bare_fn_ty
    };
    let fn_ret = callee.ty.fn_ret();
    let fn_ty = callee.direct_fn_type(ccx, &[]);
    let llret = bcx.call(llfnpointer, &llargs, None);
    fn_ty.apply_attrs_callsite(llret);
    if fn_ret.0.is_never() {
        bcx.unreachable();
    } else {
        if fn_ty.ret.is_indirect() || fn_ty.ret.is_ignore() {
            bcx.ret_void();
        } else {
            bcx.ret(llret);
        }
    }
    ccx.fn_pointer_shims().borrow_mut().insert(bare_fn_ty_maybe_ref, llfn);
    llfn
}
fn trans_fn_pointer_shim < ' a , ' tcx > ( ccx : & ' a CrateContext < ' a , ' tcx > , method_instance : Instance < ' tcx > , closure_kind : ty :: ClosureKind , bare_fn_ty : Ty < ' tcx > ) -> ValueRef { let tcx = ccx . tcx ( ) ; // Normalize the type for better caching. let bare_fn_ty = tcx . normalize_associated_type ( & bare_fn_ty ) ; // If this is an impl of `Fn` or `FnMut` trait, the receiver is `&self`. let is_by_ref = match closure_kind { ty :: ClosureKind :: Fn | ty :: ClosureKind :: FnMut => true , ty :: ClosureKind :: FnOnce => false , } ; let llfnpointer = match bare_fn_ty . sty { ty :: TyFnDef ( def_id , substs , _ ) => { // Function definitions have to be turned into a pointer. let llfn = Callee :: def ( ccx , def_id , substs ) . reify ( ccx ) ; if ! is_by_ref { // A by-value fn item is ignored, so the shim has // the same signature as the original function. return llfn ; } Some ( llfn ) } _ => None } ; let bare_fn_ty_maybe_ref = if is_by_ref { tcx . mk_imm_ref ( tcx . mk_region ( ty :: ReErased ) , bare_fn_ty ) } else { bare_fn_ty } ; // Check if we already trans'd this shim. if let Some ( & llval ) = ccx . fn_pointer_shims ( ) . borrow ( ) . get ( & bare_fn_ty_maybe_ref ) { return llval ; } debug ! ( " " bare_fn_ty ) ; // Construct the "tuply" version of `bare_fn_ty`. It takes two arguments: `self`, // which is the fn pointer, and `args`, which is the arguments tuple. let sig = match bare_fn_ty . sty { ty :: TyFnDef ( .. , & ty :: BareFnTy { unsafety : hir :: Unsafety :: Normal , abi : Abi :: Rust , ref sig } ) | ty :: TyFnPtr ( & ty :: BareFnTy { unsafety : hir :: Unsafety :: Normal , abi : Abi :: Rust , ref sig } ) => sig , _ => { bug ! ( " " bare_fn_ty ) ; } } ; let sig = tcx . erase_late_bound_regions_and_normalize ( sig ) ; let tuple_input_ty = tcx . intern_tup ( sig . inputs ( ) ) ; let sig = tcx . mk_fn_sig ( [ bare_fn_ty_maybe_ref , tuple_input_ty ] . iter ( ) . cloned ( ) , sig . output ( ) , false ) ; let fn_ty = FnType :: new ( ccx , Abi :: RustCall , & sig , & [ ] ) ; let tuple_fn_ty = tcx . mk_fn_ptr ( tcx . mk_bare_fn ( ty :: BareFnTy { unsafety : hir :: Unsafety :: Normal , abi : Abi :: RustCall , sig : ty :: Binder ( sig ) } ) ) ; debug ! ( " " tuple_fn_ty ) ; // let function_name = method_instance . symbol_name ( ccx . shared ( ) ) ; let llfn = declare :: define_internal_fn ( ccx , & function_name , tuple_fn_ty ) ; attributes :: set_frame_pointer_elimination ( ccx , llfn ) ; // let bcx = Builder :: new_block ( ccx , llfn , " " ) ; let mut llargs = get_params ( llfn ) ; let self_arg = llargs . remove ( fn_ty . ret . is_indirect ( ) as usize ) ; let llfnpointer = llfnpointer . unwrap_or_else ( | | { // the first argument (`self`) will be ptr to the fn pointer if is_by_ref { bcx . load ( self_arg ) } else { self_arg } } ) ; let callee = Callee { data : Fn ( llfnpointer ) , ty : bare_fn_ty } ; let fn_ret = callee . ty . fn_ret ( ) ; let fn_ty = callee . direct_fn_type ( ccx , & [ ] ) ; let llret = bcx . call ( llfnpointer , & llargs , None ) ; fn_ty . apply_attrs_callsite ( llret ) ; if fn_ret . 0 . is_never ( ) { bcx . unreachable ( ) ; } else { if fn_ty . ret . is_indirect ( ) || fn_ty . ret . is_ignore ( ) { bcx . ret_void ( ) ; } else { bcx . ret ( llret ) ; } } ccx . fn_pointer_shims ( ) . borrow_mut ( ) . insert ( bare_fn_ty_maybe_ref , llfn ) ; llfn }
Translates an adapter that implements the `Fn` trait for a fn
pointer.
Translates an adapter that implements the ` Fn ` trait for a fn pointer .
ccx
&'a CrateContext<'a, 'tcx>
method_instance
Instance<'tcx>
closure_kind
ty::ClosureKind
bare_fn_ty
Ty<'tcx>
ccx
&'a CrateContext<'a, 'tcx>
method_instance
Instance<'tcx>
closure_kind
ty::ClosureKind
bare_fn_ty
Ty<'tcx>