Closed
Description
Original testcase by @hoeppnertill (reduced from his nock repo):
#![crate_type="lib"]
pub fn test(foo: bool) -> int {
match foo {
true => *box 0,
false => 0
}
}
Instruction does not dominate all uses!
%6 = bitcast i8* %5 to i64*
%8 = bitcast i64* %6 to i8*
LLVM ERROR: Broken function found, compilation aborted!
The debug log reveals that a (shallow free) cleanup of the Box<int>
rvalue is scheduled in the scope of AST node 11
, while the dereference expression itself has id 16
:
DEBUG:rustc::middle::trans::expr: deref_once(expr=expr(16: *box() 0), datum=Datum((i64*: %7 = bitcast i8* %6 to i64*), Box<int>, RvalueExpr(Rvalue { mode: ByValue })), method_call=MethodCall { expr_id: 16, adjustment: NoAdjustment })
DEBUG:rustc::middle::trans::cleanup: temporary_scope(16) = AstScope(11)
DEBUG:rustc::middle::trans::cleanup: schedule_free_value(AstScope(11), val=(i64*: %7 = bitcast i8* %6 to i64*), heap=HeapExchange)
DEBUG:rustc::middle::trans::cleanup: schedule_clean_in_ast_scope(cleanup_scope=11)
DEBUG:rustc::middle::trans::expr: deref_once(expr=16, method_call=MethodCall { expr_id: 16, adjustment: NoAdjustment }, result=Datum((i64*: %7 = bitcast i8* %6 to i64*), int, RvalueExpr(Rvalue { mode: ByRef })))
--pretty expanded,identified
reveals that id 11
refers to the entire function's block:
pub fn test(foo /* pat 5 */: bool) -> int {
(match (foo /* 13 */) {
(true /* 15 */) /* pat 14 */ =>
(*(box() (0 /* 18 */) /* 17 */) /* 16 */),
(false /* 20 */) /* pat 19 */ => (0 /* 21 */),
} /* 12 */)
} /* block 11 */ /* 3 */
This means the cleanup of a value valid only within a match arm is scheduled outside the arm.
cc @nikomatsakis @pnkfelix