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
- Fix all earlier compiler diagnostics first — this panic usually occurs while already-erroring code is translated
- Upgrade move-compiler to the latest version; if reproducible on clean code, file a minimal repro upstream
- Simplify the borrow expression (borrow a local or field directly instead of a complex expression)
- 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
- Fix all type errors before lower-to-HLIR runs
- Borrow local variables/fields directly instead of complex computed expressions
- Keep the compiler toolchain on a vetted release
- Attach minimal repros when filing compiler bugs
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
- ICE unexpanded use
- ICE typing failed for cast
- ICE either the type did not have 'drop' when it should have
- ICE expansion failed
- {:#?}{:#?}
AI-assisted analysis of diem/diem@fc4714a8ea (2026-09-04).
Data as JSON: /api/errors/cdfd7869cd991b0d.
Report an issue: GitHub.