mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 15:23:46 +00:00
use adt::trans_const
when translating constant closures and tuples
Fixes #36401
This commit is contained in:
parent
1fca1ab0e7
commit
f1bd907789
@ -38,6 +38,7 @@ use value::Value;
|
||||
use syntax::ast;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
|
||||
use std::fmt;
|
||||
use std::ptr;
|
||||
|
||||
use super::operand::{OperandRef, OperandValue};
|
||||
@ -149,6 +150,12 @@ impl<'tcx> Const<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for Const<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Const({:?}: {:?})", Value(self.llval), self.ty)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum Base {
|
||||
/// A constant value without an unique address.
|
||||
@ -472,7 +479,8 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||
|
||||
fn const_operand(&self, operand: &mir::Operand<'tcx>, span: Span)
|
||||
-> Result<Const<'tcx>, ConstEvalErr> {
|
||||
match *operand {
|
||||
debug!("const_operand({:?} @ {:?})", operand, span);
|
||||
let result = match *operand {
|
||||
mir::Operand::Consume(ref lvalue) => {
|
||||
Ok(self.const_lvalue(lvalue, span)?.to_const(span))
|
||||
}
|
||||
@ -501,13 +509,33 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
debug!("const_operand({:?} @ {:?}) = {:?}", operand, span,
|
||||
result.as_ref().ok());
|
||||
result
|
||||
}
|
||||
|
||||
fn const_array(&self, array_ty: Ty<'tcx>, fields: &[ValueRef])
|
||||
-> Const<'tcx>
|
||||
{
|
||||
let elem_ty = array_ty.builtin_index().unwrap_or_else(|| {
|
||||
bug!("bad array type {:?}", array_ty)
|
||||
});
|
||||
let llunitty = type_of::type_of(self.ccx, elem_ty);
|
||||
// If the array contains enums, an LLVM array won't work.
|
||||
let val = if fields.iter().all(|&f| val_ty(f) == llunitty) {
|
||||
C_array(llunitty, fields)
|
||||
} else {
|
||||
C_struct(self.ccx, fields, false)
|
||||
};
|
||||
Const::new(val, array_ty)
|
||||
}
|
||||
|
||||
fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>,
|
||||
dest_ty: Ty<'tcx>, span: Span)
|
||||
-> Result<Const<'tcx>, ConstEvalErr> {
|
||||
let tcx = self.ccx.tcx();
|
||||
debug!("const_rvalue({:?}: {:?} @ {:?})", rvalue, dest_ty, span);
|
||||
let val = match *rvalue {
|
||||
mir::Rvalue::Use(ref operand) => self.const_operand(operand, span)?,
|
||||
|
||||
@ -515,15 +543,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||
let elem = self.const_operand(elem, span)?;
|
||||
let size = count.value.as_u64(tcx.sess.target.uint_type);
|
||||
let fields = vec![elem.llval; size as usize];
|
||||
|
||||
let llunitty = type_of::type_of(self.ccx, elem.ty);
|
||||
// If the array contains enums, an LLVM array won't work.
|
||||
let val = if val_ty(elem.llval) == llunitty {
|
||||
C_array(llunitty, &fields)
|
||||
} else {
|
||||
C_struct(self.ccx, &fields, false)
|
||||
};
|
||||
Const::new(val, dest_ty)
|
||||
self.const_array(dest_ty, &fields)
|
||||
}
|
||||
|
||||
mir::Rvalue::Aggregate(ref kind, ref operands) => {
|
||||
@ -547,22 +567,26 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||
self.monomorphize(&substs));
|
||||
}
|
||||
|
||||
let val = if let mir::AggregateKind::Adt(adt_def, index, _, _) = *kind {
|
||||
let repr = adt::represent_type(self.ccx, dest_ty);
|
||||
let disr = Disr::from(adt_def.variants[index].disr_val);
|
||||
adt::trans_const(self.ccx, &repr, disr, &fields)
|
||||
} else if let ty::TyArray(elem_ty, _) = dest_ty.sty {
|
||||
let llunitty = type_of::type_of(self.ccx, elem_ty);
|
||||
// If the array contains enums, an LLVM array won't work.
|
||||
if fields.iter().all(|&f| val_ty(f) == llunitty) {
|
||||
C_array(llunitty, &fields)
|
||||
} else {
|
||||
C_struct(self.ccx, &fields, false)
|
||||
match *kind {
|
||||
mir::AggregateKind::Vec => {
|
||||
self.const_array(dest_ty, &fields)
|
||||
}
|
||||
} else {
|
||||
C_struct(self.ccx, &fields, false)
|
||||
};
|
||||
Const::new(val, dest_ty)
|
||||
mir::AggregateKind::Adt(..) |
|
||||
mir::AggregateKind::Closure(..) |
|
||||
mir::AggregateKind::Tuple => {
|
||||
let disr = match *kind {
|
||||
mir::AggregateKind::Adt(adt_def, index, _, _) => {
|
||||
Disr::from(adt_def.variants[index].disr_val)
|
||||
}
|
||||
_ => Disr(0)
|
||||
};
|
||||
let repr = adt::represent_type(self.ccx, dest_ty);
|
||||
Const::new(
|
||||
adt::trans_const(self.ccx, &repr, disr, &fields),
|
||||
dest_ty
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mir::Rvalue::Cast(ref kind, ref source, cast_ty) => {
|
||||
@ -786,6 +810,8 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||
_ => span_bug!(span, "{:?} in constant", rvalue)
|
||||
};
|
||||
|
||||
debug!("const_rvalue({:?}: {:?} @ {:?}) = {:?}", rvalue, dest_ty, span, val);
|
||||
|
||||
Ok(val)
|
||||
}
|
||||
|
||||
@ -935,6 +961,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
constant: &mir::Constant<'tcx>)
|
||||
-> Const<'tcx>
|
||||
{
|
||||
debug!("trans_constant({:?})", constant);
|
||||
let ty = bcx.monomorphize(&constant.ty);
|
||||
let result = match constant.literal.clone() {
|
||||
mir::Literal::Item { def_id, substs } => {
|
||||
@ -959,11 +986,14 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
}
|
||||
};
|
||||
|
||||
result.unwrap_or_else(|_| {
|
||||
let result = result.unwrap_or_else(|_| {
|
||||
// We've errored, so we don't have to produce working code.
|
||||
let llty = type_of::type_of(bcx.ccx(), ty);
|
||||
Const::new(C_undef(llty), ty)
|
||||
})
|
||||
});
|
||||
|
||||
debug!("trans_constant({:?}) = {:?}", constant, result);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
|
25
src/test/run-pass/issue-36401.rs
Normal file
25
src/test/run-pass/issue-36401.rs
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Event {
|
||||
Key(u8),
|
||||
Resize,
|
||||
Unknown(u16),
|
||||
}
|
||||
|
||||
static XTERM_SINGLE_BYTES : [(u8, Event); 1] = [(1, Event::Resize)];
|
||||
|
||||
fn main() {
|
||||
match XTERM_SINGLE_BYTES[0] {
|
||||
(1, Event::Resize) => {},
|
||||
ref bad => panic!("unexpected {:?}", bad)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user