pub fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                         expr: &hir::Expr)
                         -> DatumBlock<'blk, 'tcx, Expr> {
    debug!("trans(expr={:?})", expr);

    let mut bcx = bcx;
    let fcx = bcx.fcx;
    let qualif = *bcx.tcx().const_qualif_map.borrow().get(&expr.id).unwrap();
    let adjusted_global = !qualif.intersects(check_const::ConstQualif::NON_STATIC_BORROWS);
    let global = if !qualif.intersects(
        check_const::ConstQualif::NOT_CONST |
        check_const::ConstQualif::NEEDS_DROP
    ) {
        let global = consts::get_const_expr_as_global(bcx.ccx(), expr, qualif,
                                                      bcx.fcx.param_substs);

        if qualif.intersects(check_const::ConstQualif::HAS_STATIC_BORROWS) {
            // Is borrowed as 'static, must return lvalue.

            // Cast pointer to global, because constants have different types.
            let const_ty = expr_ty_adjusted(bcx, expr);
            let llty = type_of::type_of(bcx.ccx(), const_ty);
            let global = PointerCast(bcx, global, llty.ptr_to());
            let datum = Datum::new(global, const_ty, Lvalue::new("expr::trans"));
            return DatumBlock::new(bcx, datum.to_expr_datum());
        }

        // Otherwise, keep around and perform adjustments, if needed.
        let const_ty = if adjusted_global {
            expr_ty_adjusted(bcx, expr)
        } else {
            expr_ty(bcx, expr)
        };

        // This could use a better heuristic.
        Some(if type_is_immediate(bcx.ccx(), const_ty) {
            // Cast pointer to global, because constants have different types.
            let llty = type_of::type_of(bcx.ccx(), const_ty);
            let global = PointerCast(bcx, global, llty.ptr_to());
            // Maybe just get the value directly, instead of loading it?
            immediate_rvalue(load_ty(bcx, global, const_ty), const_ty)
        } else {
            let scratch = alloc_ty(bcx, const_ty, "const");
            call_lifetime_start(bcx, scratch);
            let lldest = if !const_ty.is_structural() {
                // Cast pointer to slot, because constants have different types.
                PointerCast(bcx, scratch, val_ty(global))
            } else {
                // In this case, memcpy_ty calls llvm.memcpy after casting both
                // source and destination to i8*, so we don't need any casts.
                scratch
            };
            memcpy_ty(bcx, lldest, global, const_ty);
            Datum::new(scratch, const_ty, Rvalue::new(ByRef))
        })
    } else {
        None
    };

    let cleanup_debug_loc = debuginfo::get_cleanup_debug_loc_for_ast_node(bcx.ccx(),
                                                                          expr.id,
                                                                          expr.span,
                                                                          false);
    fcx.push_ast_cleanup_scope(cleanup_debug_loc);
    let datum = match global {
        Some(rvalue) => rvalue.to_expr_datum(),
        None => unpack_datum!(bcx, trans_unadjusted(bcx, expr))
    };
    let datum = if adjusted_global {
        datum // trans::consts already performed adjustments.
    } else {
        unpack_datum!(bcx, apply_adjustments(bcx, expr, datum))
    };
    bcx = fcx.pop_and_trans_ast_cleanup_scope(bcx, expr.id);
    return DatumBlock::new(bcx, datum);
}
/// Translates an expression, returning a datum (and new block) encapsulating the result. When
/// possible, it is preferred to use `trans_into`, as that may avoid creating a temporary on the
/// stack.
Translates an expression, returning a datum (and new block) encapsulating the result. When
possible, it is preferred to use `trans_into`, as that may avoid creating a temporary on the
stack.
Translates an expression returning a datum ( and new block ) encapsulating the result . When possible it is preferred to use ` trans_into ` as that may avoid creating a temporary on the stack .
pub fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                         expr: &hir::Expr)
                         -> DatumBlock<'blk, 'tcx, Expr> {
    debug!("trans(expr={:?})", expr);
    let mut bcx = bcx;
    let fcx = bcx.fcx;
    let qualif = *bcx.tcx().const_qualif_map.borrow().get(&expr.id).unwrap();
    let adjusted_global = !qualif.intersects(check_const::ConstQualif::NON_STATIC_BORROWS);
    let global = if !qualif.intersects(
        check_const::ConstQualif::NOT_CONST |
        check_const::ConstQualif::NEEDS_DROP
    ) {
        let global = consts::get_const_expr_as_global(bcx.ccx(), expr, qualif,
                                                      bcx.fcx.param_substs);
        if qualif.intersects(check_const::ConstQualif::HAS_STATIC_BORROWS) {
            // Is borrowed as 'static, must return lvalue.
            // Cast pointer to global, because constants have different types.
            let const_ty = expr_ty_adjusted(bcx, expr);
            let llty = type_of::type_of(bcx.ccx(), const_ty);
            let global = PointerCast(bcx, global, llty.ptr_to());
            let datum = Datum::new(global, const_ty, Lvalue::new("expr::trans"));
            return DatumBlock::new(bcx, datum.to_expr_datum());
        }
        // Otherwise, keep around and perform adjustments, if needed.
        let const_ty = if adjusted_global {
            expr_ty_adjusted(bcx, expr)
        } else {
            expr_ty(bcx, expr)
        };
        // This could use a better heuristic.
        Some(if type_is_immediate(bcx.ccx(), const_ty) {
            // Cast pointer to global, because constants have different types.
            let llty = type_of::type_of(bcx.ccx(), const_ty);
            let global = PointerCast(bcx, global, llty.ptr_to());
            // Maybe just get the value directly, instead of loading it?
            immediate_rvalue(load_ty(bcx, global, const_ty), const_ty)
        } else {
            let scratch = alloc_ty(bcx, const_ty, "const");
            call_lifetime_start(bcx, scratch);
            let lldest = if !const_ty.is_structural() {
                // Cast pointer to slot, because constants have different types.
                PointerCast(bcx, scratch, val_ty(global))
            } else {
                // In this case, memcpy_ty calls llvm.memcpy after casting both
                // source and destination to i8*, so we don't need any casts.
                scratch
            };
            memcpy_ty(bcx, lldest, global, const_ty);
            Datum::new(scratch, const_ty, Rvalue::new(ByRef))
        })
    } else {
        None
    };
    let cleanup_debug_loc = debuginfo::get_cleanup_debug_loc_for_ast_node(bcx.ccx(),
                                                                          expr.id,
                                                                          expr.span,
                                                                          false);
    fcx.push_ast_cleanup_scope(cleanup_debug_loc);
    let datum = match global {
        Some(rvalue) => rvalue.to_expr_datum(),
        None => unpack_datum!(bcx, trans_unadjusted(bcx, expr))
    };
    let datum = if adjusted_global {
        datum // trans::consts already performed adjustments.
    } else {
        unpack_datum!(bcx, apply_adjustments(bcx, expr, datum))
    };
    bcx = fcx.pop_and_trans_ast_cleanup_scope(bcx, expr.id);
    return DatumBlock::new(bcx, datum);
}
pub fn trans < ' blk , ' tcx > ( bcx : Block < ' blk , ' tcx > , expr : & hir :: Expr ) -> DatumBlock < ' blk , ' tcx , Expr > { debug ! ( " " expr ) ; let mut bcx = bcx ; let fcx = bcx . fcx ; let qualif = * bcx . tcx ( ) . const_qualif_map . borrow ( ) . get ( & expr . id ) . unwrap ( ) ; let adjusted_global = ! qualif . intersects ( check_const :: ConstQualif :: NON_STATIC_BORROWS ) ; let global = if ! qualif . intersects ( check_const :: ConstQualif :: NOT_CONST | check_const :: ConstQualif :: NEEDS_DROP ) { let global = consts :: get_const_expr_as_global ( bcx . ccx ( ) , expr , qualif , bcx . fcx . param_substs ) ; if qualif . intersects ( check_const :: ConstQualif :: HAS_STATIC_BORROWS ) { // Is borrowed as 'static, must return lvalue. // Cast pointer to global, because constants have different types. let const_ty = expr_ty_adjusted ( bcx , expr ) ; let llty = type_of :: type_of ( bcx . ccx ( ) , const_ty ) ; let global = PointerCast ( bcx , global , llty . ptr_to ( ) ) ; let datum = Datum :: new ( global , const_ty , Lvalue :: new ( " " ) ) ; return DatumBlock :: new ( bcx , datum . to_expr_datum ( ) ) ; } // Otherwise, keep around and perform adjustments, if needed. let const_ty = if adjusted_global { expr_ty_adjusted ( bcx , expr ) } else { expr_ty ( bcx , expr ) } ; // This could use a better heuristic. Some ( if type_is_immediate ( bcx . ccx ( ) , const_ty ) { // Cast pointer to global, because constants have different types. let llty = type_of :: type_of ( bcx . ccx ( ) , const_ty ) ; let global = PointerCast ( bcx , global , llty . ptr_to ( ) ) ; // Maybe just get the value directly, instead of loading it? immediate_rvalue ( load_ty ( bcx , global , const_ty ) , const_ty ) } else { let scratch = alloc_ty ( bcx , const_ty , " " ) ; call_lifetime_start ( bcx , scratch ) ; let lldest = if ! const_ty . is_structural ( ) { // Cast pointer to slot, because constants have different types. PointerCast ( bcx , scratch , val_ty ( global ) ) } else { // In this case, memcpy_ty calls llvm.memcpy after casting both // source and destination to i8*, so we don't need any casts. scratch } ; memcpy_ty ( bcx , lldest , global , const_ty ) ; Datum :: new ( scratch , const_ty , Rvalue :: new ( ByRef ) ) } ) } else { None } ; let cleanup_debug_loc = debuginfo :: get_cleanup_debug_loc_for_ast_node ( bcx . ccx ( ) , expr . id , expr . span , false ) ; fcx . push_ast_cleanup_scope ( cleanup_debug_loc ) ; let datum = match global { Some ( rvalue ) => rvalue . to_expr_datum ( ) , None => unpack_datum ! ( bcx trans_unadjusted ( bcx expr ) ) } ; let datum = if adjusted_global { datum // trans::consts already performed adjustments. } else { unpack_datum ! ( bcx apply_adjustments ( bcx expr datum ) ) } ; bcx = fcx . pop_and_trans_ast_cleanup_scope ( bcx , expr . id ) ; return DatumBlock :: new ( bcx , datum ) ; }
Translates an expression, returning a datum (and new block) encapsulating the result.
Translates an expression returning a datum ( and new block ) encapsulating the result .
bcx
Block<'blk, 'tcx>
expr
&hir::Expr
bcx
Block<'blk, 'tcx>
expr
&hir::Expr