diem/diem · error

ICE invalid bind_exp for single value

Error message

ICE invalid bind_exp for single value

What it means

Internal compiler error in the HLIR translate pass when translating a single-value borrow. The code expects bind_exp_impl to return an expression whose value is HE::Move { from_user: false, var } (a compiler-generated move of a fresh temp); anything else means the temporary-binding invariant established by earlier passes was violated. It is unreachable for well-formed typed expressions.

Source

Thrown at language/move-lang/src/hlir/translate.rs:1264

                .map(|(e, tmp_item)| match tmp_item {
                    TmpItem::Single(s) => H::ExpListItem::Single(e, s),
                    TmpItem::Splat(loc, ss) => H::ExpListItem::Splat(loc, e, ss),
                })
                .collect();
            HE::ExpList(items)
        }
        TE::Borrow(mut_, te, f) => {
            let e = exp(context, result, None, *te);
            HE::Borrow(mut_, e, f)
        }
        TE::TempBorrow(mut_, te) => {
            let eb = exp_(context, result, None, *te);
            let tmp = match bind_exp_impl(context, result, eb, true).exp.value {
                HE::Move {
                    from_user: false,
                    var,
                } => var,
                _ => panic!("ICE invalid bind_exp for single value"),
            };
            HE::BorrowLocal(mut_, tmp)
        }
        TE::Cast(te, rhs_ty) => {
            use N::BuiltinTypeName_ as BT;
            let e = exp(context, result, None, *te);
            let bt = match rhs_ty.value.builtin_name() {
                Some(bt @ sp!(_, BT::U8))
                | Some(bt @ sp!(_, BT::U64))
                | Some(bt @ sp!(_, BT::U128)) => bt.clone(),
                _ => panic!("ICE typing failed for cast"),
            };
            HE::Cast(e, bt)
        }
        TE::Annotate(te, rhs_ty) => {
            let expected_ty = type_(context, *rhs_ty);
            return exp_(context, result, Some(&expected_ty), *te);
        }

View on GitHub (pinned to fc4714a8ea)

Solutions

  1. Fix all earlier compiler diagnostics first — this panic usually occurs while already-erroring code is translated
  2. Upgrade move-compiler to the latest version; if reproducible on clean code, file a minimal repro upstream
  3. Simplify the borrow expression (borrow a local or field directly instead of a complex expression)
  4. Avoid building a patched move-lang without running its test suite

Example fix

// before
let r = &compute(x + y);
// after
let tmp = compute(x + y);
let r = &tmp; // borrow a simple local so temp-binding invariants hold
Defensive patterns

Strategy: validation

Validate before calling

// Ensure type checking succeeded and borrows target simple locals before translation:
if context.env.has_diags() {
    return Err("abort translation: prior diagnostics present".into());
}

Try / catch

let result = std::panic::catch_unwind(|| translate_program(texp));
if result.is_err() {
    eprintln!("compiler ICE: invalid bind_exp for single value");
    std::process::exit(1);
}

Prevention

When it happens

Trigger: Translating a borrow of a single (non-list) expression where the bound expression did not lower to a synthetic move of a fresh local — typically only when earlier typing errors exist or an internal pass produced a non-standard expression shape.

Common situations: Compiling Move sources with prior type errors where `&expr` or `&mut expr` wraps an already-failed expression; running a modified compiler; compiler version bugs in borrow translation.

Related errors


AI-assisted analysis of diem/diem@fc4714a8ea (2026-09-04). Data as JSON: /api/errors/cdfd7869cd991b0d. Report an issue: GitHub.