Skip to content

Commit e13090e

Browse files
committed
Fixes issue #43205: ICE in Rvalue::Len evaluation.
- fixes evaluation of array length for zero-sized type referenced by rvalue operand. - adds test to verify fix. Cause of the issue. Zero-sized aggregates are handled as operands, not lvalues. Therefore while visiting Assign statement by LocalAnalyser, mark_as_lvalue() is not called for related Local. This behaviour is controlled by rvalue_creates_operand() method. As result it causes error later, when rvalue operand is evaluated in trans_rvalue_operand() while handling Rvalue::Len case. Array length evaluation invokes trans_lvalue() which expects referenced Local to be value, not operand. How it is fixed. In certain cases result of Rvalue::Len can be evaluated without calling trans_lvalue(). Method evaluate_array_len() is introduced to handle length evaluation for zero-sized types referenced by Locals.
1 parent a3f0ee9 commit e13090e

File tree

2 files changed

+37
-3
lines changed

2 files changed

+37
-3
lines changed

src/librustc_trans/mir/rvalue.rs

+23-3
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use type_of;
2929
use tvec;
3030
use value::Value;
3131

32-
use super::MirContext;
32+
use super::{MirContext, LocalRef};
3333
use super::constant::const_scalar_checked_binop;
3434
use super::operand::{OperandRef, OperandValue};
3535
use super::lvalue::LvalueRef;
@@ -381,9 +381,9 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
381381
}
382382

383383
mir::Rvalue::Len(ref lvalue) => {
384-
let tr_lvalue = self.trans_lvalue(&bcx, lvalue);
384+
let size = self.evaluate_array_len(&bcx, lvalue);
385385
let operand = OperandRef {
386-
val: OperandValue::Immediate(tr_lvalue.len(bcx.ccx)),
386+
val: OperandValue::Immediate(size),
387387
ty: bcx.tcx().types.usize,
388388
};
389389
(bcx, operand)
@@ -512,6 +512,26 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
512512
}
513513
}
514514

515+
fn evaluate_array_len(&mut self,
516+
bcx: &Builder<'a, 'tcx>,
517+
lvalue: &mir::Lvalue<'tcx>) -> ValueRef
518+
{
519+
// ZST are passed as operands and require special handling
520+
// because trans_lvalue() panics if Local is operand.
521+
if let mir::Lvalue::Local(index) = *lvalue {
522+
if let LocalRef::Operand(Some(op)) = self.locals[index] {
523+
if common::type_is_zero_size(bcx.ccx, op.ty) {
524+
if let ty::TyArray(_, n) = op.ty.sty {
525+
return common::C_uint(bcx.ccx, n);
526+
}
527+
}
528+
}
529+
}
530+
// use common size calculation for non zero-sized types
531+
let tr_value = self.trans_lvalue(&bcx, lvalue);
532+
return tr_value.len(bcx.ccx);
533+
}
534+
515535
pub fn trans_scalar_binop(&mut self,
516536
bcx: &Builder<'a, 'tcx>,
517537
op: mir::BinOp,

src/test/run-pass/issue-43205.rs

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {
12+
&&[()][0];
13+
println!("{:?}", &[(),()][1]);
14+
}

0 commit comments

Comments
 (0)