Properly translate unit structs in MIR
This commit is contained in:
parent
4ce1dafd1d
commit
75e8f4afca
@ -701,9 +701,9 @@ pub struct Constant<'tcx> {
|
||||
#[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable)]
|
||||
pub enum ItemKind {
|
||||
Constant,
|
||||
/// This is any sort of callable (usually those that have a type of `fn(…) -> …`). This
|
||||
/// includes functions, constructors, but not methods which have their own ItemKind.
|
||||
Function,
|
||||
Struct,
|
||||
Variant,
|
||||
Method,
|
||||
}
|
||||
|
||||
|
@ -519,51 +519,51 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
|
||||
let substs = cx.tcx.mk_substs(cx.tcx.node_id_item_substs(expr.id).substs);
|
||||
// Otherwise there may be def_map borrow conflicts
|
||||
let def = cx.tcx.def_map.borrow()[&expr.id].full_def();
|
||||
match def {
|
||||
def::DefVariant(_, def_id, false) |
|
||||
def::DefStruct(def_id) |
|
||||
def::DefFn(def_id, _) |
|
||||
def::DefMethod(def_id) => {
|
||||
let kind = match def {
|
||||
def::DefVariant(..) => ItemKind::Variant,
|
||||
def::DefStruct(..) => ItemKind::Struct,
|
||||
def::DefFn(..) => ItemKind::Function,
|
||||
def::DefMethod(..) => ItemKind::Method,
|
||||
_ => panic!()
|
||||
};
|
||||
ExprKind::Literal {
|
||||
literal: Literal::Item { def_id: def_id, kind: kind, substs: substs }
|
||||
let (def_id, kind) = match def {
|
||||
// A variant constructor.
|
||||
def::DefVariant(_, def_id, false) => (def_id, ItemKind::Function),
|
||||
// A regular function.
|
||||
def::DefFn(def_id, _) => (def_id, ItemKind::Function),
|
||||
def::DefMethod(def_id) => (def_id, ItemKind::Method),
|
||||
def::DefStruct(def_id) => {
|
||||
match cx.tcx.node_id_to_type(expr.id).sty {
|
||||
// A tuple-struct constructor.
|
||||
ty::TyBareFn(..) => (def_id, ItemKind::Function),
|
||||
// This is a special case: a unit struct which is used as a value. We return a
|
||||
// completely different ExprKind here to account for this special case.
|
||||
ty::TyStruct(adt_def, substs) => return ExprKind::Adt {
|
||||
adt_def: adt_def,
|
||||
variant_index: 0,
|
||||
substs: substs,
|
||||
fields: vec![],
|
||||
base: None
|
||||
},
|
||||
ref sty => panic!("unexpected sty: {:?}", sty)
|
||||
}
|
||||
},
|
||||
def::DefConst(def_id) |
|
||||
def::DefAssociatedConst(def_id) => {
|
||||
if let Some(v) = cx.try_const_eval_literal(expr) {
|
||||
ExprKind::Literal { literal: v }
|
||||
return ExprKind::Literal { literal: v };
|
||||
} else {
|
||||
ExprKind::Literal {
|
||||
literal: Literal::Item {
|
||||
def_id: def_id,
|
||||
kind: ItemKind::Constant,
|
||||
substs: substs
|
||||
}
|
||||
}
|
||||
(def_id, ItemKind::Constant)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def::DefStatic(node_id, _) =>
|
||||
ExprKind::StaticRef {
|
||||
id: node_id,
|
||||
},
|
||||
def::DefStatic(node_id, _) => return ExprKind::StaticRef {
|
||||
id: node_id,
|
||||
},
|
||||
|
||||
def @ def::DefLocal(..) |
|
||||
def @ def::DefUpvar(..) =>
|
||||
convert_var(cx, expr, def),
|
||||
def @ def::DefUpvar(..) => return convert_var(cx, expr, def),
|
||||
|
||||
def =>
|
||||
cx.tcx.sess.span_bug(
|
||||
expr.span,
|
||||
&format!("def `{:?}` not yet implemented", def)),
|
||||
};
|
||||
ExprKind::Literal {
|
||||
literal: Literal::Item { def_id: def_id, kind: kind, substs: substs }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,9 +39,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
did: DefId)
|
||||
-> OperandRef<'tcx> {
|
||||
match kind {
|
||||
ItemKind::Function |
|
||||
ItemKind::Struct |
|
||||
ItemKind::Variant => self.trans_fn_ref(bcx, ty, substs, did),
|
||||
ItemKind::Function => self.trans_fn_ref(bcx, ty, substs, did),
|
||||
ItemKind::Method => match bcx.tcx().impl_or_trait_item(did).container() {
|
||||
ty::ImplContainer(_) => self.trans_fn_ref(bcx, ty, substs, did),
|
||||
ty::TraitContainer(tdid) => self.trans_static_method(bcx, ty, did, tdid, substs)
|
||||
|
@ -19,6 +19,7 @@ use trans::common::{self, Block, Result};
|
||||
use trans::debuginfo::DebugLoc;
|
||||
use trans::declare;
|
||||
use trans::expr;
|
||||
use trans::adt;
|
||||
use trans::machine;
|
||||
use trans::type_::Type;
|
||||
use trans::type_of;
|
||||
@ -26,21 +27,22 @@ use trans::tvec;
|
||||
|
||||
use super::MirContext;
|
||||
use super::operand::{OperandRef, OperandValue};
|
||||
use super::lvalue::LvalueRef;
|
||||
|
||||
impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
pub fn trans_rvalue(&mut self,
|
||||
bcx: Block<'bcx, 'tcx>,
|
||||
lldest: ValueRef,
|
||||
dest: LvalueRef<'tcx>,
|
||||
rvalue: &mir::Rvalue<'tcx>)
|
||||
-> Block<'bcx, 'tcx>
|
||||
{
|
||||
debug!("trans_rvalue(lldest={}, rvalue={:?})",
|
||||
bcx.val_to_string(lldest),
|
||||
debug!("trans_rvalue(dest.llval={}, rvalue={:?})",
|
||||
bcx.val_to_string(dest.llval),
|
||||
rvalue);
|
||||
|
||||
match *rvalue {
|
||||
mir::Rvalue::Use(ref operand) => {
|
||||
self.trans_operand_into(bcx, lldest, operand);
|
||||
self.trans_operand_into(bcx, dest.llval, operand);
|
||||
bcx
|
||||
}
|
||||
|
||||
@ -49,7 +51,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
// into-coerce of a thin pointer to a fat pointer - just
|
||||
// use the operand path.
|
||||
let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
|
||||
self.store_operand(bcx, lldest, temp);
|
||||
self.store_operand(bcx, dest.llval, temp);
|
||||
return bcx;
|
||||
}
|
||||
|
||||
@ -72,12 +74,12 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
base::store_ty(bcx, llval, lltemp, operand.ty);
|
||||
base::coerce_unsized_into(bcx,
|
||||
lltemp, operand.ty,
|
||||
lldest, cast_ty);
|
||||
dest.llval, cast_ty);
|
||||
}
|
||||
OperandValue::Ref(llref) => {
|
||||
base::coerce_unsized_into(bcx,
|
||||
llref, operand.ty,
|
||||
lldest, cast_ty);
|
||||
dest.llval, cast_ty);
|
||||
}
|
||||
}
|
||||
bcx
|
||||
@ -86,20 +88,31 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
mir::Rvalue::Repeat(ref elem, ref count) => {
|
||||
let elem = self.trans_operand(bcx, elem);
|
||||
let size = self.trans_constant(bcx, count).immediate();
|
||||
let base = expr::get_dataptr(bcx, lldest);
|
||||
let base = expr::get_dataptr(bcx, dest.llval);
|
||||
tvec::iter_vec_raw(bcx, base, elem.ty, size, |bcx, llslot, _| {
|
||||
self.store_operand(bcx, llslot, elem);
|
||||
bcx
|
||||
})
|
||||
}
|
||||
|
||||
mir::Rvalue::Aggregate(_, ref operands) => {
|
||||
for (i, operand) in operands.iter().enumerate() {
|
||||
// Note: perhaps this should be StructGep, but
|
||||
// note that in some cases the values here will
|
||||
// not be structs but arrays.
|
||||
let lldest_i = build::GEPi(bcx, lldest, &[0, i]);
|
||||
self.trans_operand_into(bcx, lldest_i, operand);
|
||||
mir::Rvalue::Aggregate(ref kind, ref operands) => {
|
||||
match *kind {
|
||||
// Unit struct, which is translated very differently compared to any other
|
||||
// aggregate
|
||||
mir::AggregateKind::Adt(adt_def, 0, _)
|
||||
if adt_def.struct_variant().kind() == ty::VariantKind::Unit => {
|
||||
let repr = adt::represent_type(bcx.ccx(), dest.ty.to_ty(bcx.tcx()));
|
||||
adt::trans_set_discr(bcx, &*repr, dest.llval, 0);
|
||||
},
|
||||
_ => {
|
||||
for (i, operand) in operands.iter().enumerate() {
|
||||
// Note: perhaps this should be StructGep, but
|
||||
// note that in some cases the values here will
|
||||
// not be structs but arrays.
|
||||
let lldest_i = build::GEPi(bcx, dest.llval, &[0, i]);
|
||||
self.trans_operand_into(bcx, lldest_i, operand);
|
||||
}
|
||||
}
|
||||
}
|
||||
bcx
|
||||
}
|
||||
@ -113,9 +126,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
let llbase1 = build::GEPi(bcx, llbase, &[from_start]);
|
||||
let adj = common::C_uint(ccx, from_start + from_end);
|
||||
let lllen1 = build::Sub(bcx, lllen, adj, DebugLoc::None);
|
||||
let lladdrdest = expr::get_dataptr(bcx, lldest);
|
||||
let lladdrdest = expr::get_dataptr(bcx, dest.llval);
|
||||
build::Store(bcx, llbase1, lladdrdest);
|
||||
let llmetadest = expr::get_meta(bcx, lldest);
|
||||
let llmetadest = expr::get_meta(bcx, dest.llval);
|
||||
build::Store(bcx, lllen1, llmetadest);
|
||||
bcx
|
||||
}
|
||||
@ -127,7 +140,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
_ => {
|
||||
assert!(rvalue_creates_operand(rvalue));
|
||||
let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
|
||||
self.store_operand(bcx, lldest, temp);
|
||||
self.store_operand(bcx, dest.llval, temp);
|
||||
bcx
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
let index = index as usize;
|
||||
match self.temps[index as usize] {
|
||||
TempRef::Lvalue(tr_dest) => {
|
||||
self.trans_rvalue(bcx, tr_dest.llval, rvalue)
|
||||
self.trans_rvalue(bcx, tr_dest, rvalue)
|
||||
}
|
||||
TempRef::Operand(None) => {
|
||||
let (bcx, operand) = self.trans_rvalue_operand(bcx, rvalue);
|
||||
@ -47,7 +47,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
}
|
||||
_ => {
|
||||
let tr_dest = self.trans_lvalue(bcx, lvalue);
|
||||
self.trans_rvalue(bcx, tr_dest.llval, rvalue)
|
||||
self.trans_rvalue(bcx, tr_dest, rvalue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,8 @@
|
||||
extern crate mir_external_refs as ext;
|
||||
|
||||
struct S(u8);
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct Unit;
|
||||
|
||||
impl S {
|
||||
fn hey() -> u8 { 42 }
|
||||
@ -175,6 +177,11 @@ fn t20() -> fn(u64, u32)->(u64, u32) {
|
||||
<u32 as T<_, _>>::staticmeth
|
||||
}
|
||||
|
||||
#[rustc_mir]
|
||||
fn t21() -> Unit {
|
||||
Unit
|
||||
}
|
||||
|
||||
fn main(){
|
||||
unsafe {
|
||||
assert_eq!(t1()(), regular());
|
||||
@ -214,5 +221,6 @@ fn main(){
|
||||
assert_eq!(t18()(50u64, 5u64), F::f(50u64, 5u64));
|
||||
assert_eq!(t19()(322u64, 2u32), F::f(322u64, 2u32));
|
||||
assert_eq!(t20()(123u64, 38u32), <u32 as T<_, _>>::staticmeth(123, 38));
|
||||
assert_eq!(t21(), Unit);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user