Skip to content

Commit f1bd907

Browse files
committed
use adt::trans_const when translating constant closures and tuples
Fixes rust-lang#36401
1 parent 1fca1ab commit f1bd907

File tree

2 files changed

+83
-28
lines changed

2 files changed

+83
-28
lines changed

src/librustc_trans/mir/constant.rs

+58-28
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ use value::Value;
3838
use syntax::ast;
3939
use syntax_pos::{Span, DUMMY_SP};
4040

41+
use std::fmt;
4142
use std::ptr;
4243

4344
use super::operand::{OperandRef, OperandValue};
@@ -149,6 +150,12 @@ impl<'tcx> Const<'tcx> {
149150
}
150151
}
151152

153+
impl<'tcx> fmt::Debug for Const<'tcx> {
154+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
155+
write!(f, "Const({:?}: {:?})", Value(self.llval), self.ty)
156+
}
157+
}
158+
152159
#[derive(Copy, Clone)]
153160
enum Base {
154161
/// A constant value without an unique address.
@@ -472,7 +479,8 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
472479

473480
fn const_operand(&self, operand: &mir::Operand<'tcx>, span: Span)
474481
-> Result<Const<'tcx>, ConstEvalErr> {
475-
match *operand {
482+
debug!("const_operand({:?} @ {:?})", operand, span);
483+
let result = match *operand {
476484
mir::Operand::Consume(ref lvalue) => {
477485
Ok(self.const_lvalue(lvalue, span)?.to_const(span))
478486
}
@@ -501,29 +509,41 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
501509
}
502510
}
503511
}
504-
}
512+
};
513+
debug!("const_operand({:?} @ {:?}) = {:?}", operand, span,
514+
result.as_ref().ok());
515+
result
516+
}
517+
518+
fn const_array(&self, array_ty: Ty<'tcx>, fields: &[ValueRef])
519+
-> Const<'tcx>
520+
{
521+
let elem_ty = array_ty.builtin_index().unwrap_or_else(|| {
522+
bug!("bad array type {:?}", array_ty)
523+
});
524+
let llunitty = type_of::type_of(self.ccx, elem_ty);
525+
// If the array contains enums, an LLVM array won't work.
526+
let val = if fields.iter().all(|&f| val_ty(f) == llunitty) {
527+
C_array(llunitty, fields)
528+
} else {
529+
C_struct(self.ccx, fields, false)
530+
};
531+
Const::new(val, array_ty)
505532
}
506533

507534
fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>,
508535
dest_ty: Ty<'tcx>, span: Span)
509536
-> Result<Const<'tcx>, ConstEvalErr> {
510537
let tcx = self.ccx.tcx();
538+
debug!("const_rvalue({:?}: {:?} @ {:?})", rvalue, dest_ty, span);
511539
let val = match *rvalue {
512540
mir::Rvalue::Use(ref operand) => self.const_operand(operand, span)?,
513541

514542
mir::Rvalue::Repeat(ref elem, ref count) => {
515543
let elem = self.const_operand(elem, span)?;
516544
let size = count.value.as_u64(tcx.sess.target.uint_type);
517545
let fields = vec![elem.llval; size as usize];
518-
519-
let llunitty = type_of::type_of(self.ccx, elem.ty);
520-
// If the array contains enums, an LLVM array won't work.
521-
let val = if val_ty(elem.llval) == llunitty {
522-
C_array(llunitty, &fields)
523-
} else {
524-
C_struct(self.ccx, &fields, false)
525-
};
526-
Const::new(val, dest_ty)
546+
self.const_array(dest_ty, &fields)
527547
}
528548

529549
mir::Rvalue::Aggregate(ref kind, ref operands) => {
@@ -547,22 +567,26 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
547567
self.monomorphize(&substs));
548568
}
549569

550-
let val = if let mir::AggregateKind::Adt(adt_def, index, _, _) = *kind {
551-
let repr = adt::represent_type(self.ccx, dest_ty);
552-
let disr = Disr::from(adt_def.variants[index].disr_val);
553-
adt::trans_const(self.ccx, &repr, disr, &fields)
554-
} else if let ty::TyArray(elem_ty, _) = dest_ty.sty {
555-
let llunitty = type_of::type_of(self.ccx, elem_ty);
556-
// If the array contains enums, an LLVM array won't work.
557-
if fields.iter().all(|&f| val_ty(f) == llunitty) {
558-
C_array(llunitty, &fields)
559-
} else {
560-
C_struct(self.ccx, &fields, false)
570+
match *kind {
571+
mir::AggregateKind::Vec => {
572+
self.const_array(dest_ty, &fields)
561573
}
562-
} else {
563-
C_struct(self.ccx, &fields, false)
564-
};
565-
Const::new(val, dest_ty)
574+
mir::AggregateKind::Adt(..) |
575+
mir::AggregateKind::Closure(..) |
576+
mir::AggregateKind::Tuple => {
577+
let disr = match *kind {
578+
mir::AggregateKind::Adt(adt_def, index, _, _) => {
579+
Disr::from(adt_def.variants[index].disr_val)
580+
}
581+
_ => Disr(0)
582+
};
583+
let repr = adt::represent_type(self.ccx, dest_ty);
584+
Const::new(
585+
adt::trans_const(self.ccx, &repr, disr, &fields),
586+
dest_ty
587+
)
588+
}
589+
}
566590
}
567591

568592
mir::Rvalue::Cast(ref kind, ref source, cast_ty) => {
@@ -786,6 +810,8 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
786810
_ => span_bug!(span, "{:?} in constant", rvalue)
787811
};
788812

813+
debug!("const_rvalue({:?}: {:?} @ {:?}) = {:?}", rvalue, dest_ty, span, val);
814+
789815
Ok(val)
790816
}
791817

@@ -935,6 +961,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
935961
constant: &mir::Constant<'tcx>)
936962
-> Const<'tcx>
937963
{
964+
debug!("trans_constant({:?})", constant);
938965
let ty = bcx.monomorphize(&constant.ty);
939966
let result = match constant.literal.clone() {
940967
mir::Literal::Item { def_id, substs } => {
@@ -959,11 +986,14 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
959986
}
960987
};
961988

962-
result.unwrap_or_else(|_| {
989+
let result = result.unwrap_or_else(|_| {
963990
// We've errored, so we don't have to produce working code.
964991
let llty = type_of::type_of(bcx.ccx(), ty);
965992
Const::new(C_undef(llty), ty)
966-
})
993+
});
994+
995+
debug!("trans_constant({:?}) = {:?}", constant, result);
996+
result
967997
}
968998
}
969999

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

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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+
#[derive(Debug)]
12+
pub enum Event {
13+
Key(u8),
14+
Resize,
15+
Unknown(u16),
16+
}
17+
18+
static XTERM_SINGLE_BYTES : [(u8, Event); 1] = [(1, Event::Resize)];
19+
20+
fn main() {
21+
match XTERM_SINGLE_BYTES[0] {
22+
(1, Event::Resize) => {},
23+
ref bad => panic!("unexpected {:?}", bad)
24+
}
25+
}

0 commit comments

Comments
 (0)