Skip to content

Commit 75e8f4a

Browse files
committed
Properly translate unit structs in MIR
1 parent 4ce1daf commit 75e8f4a

File tree

6 files changed

+73
-54
lines changed

6 files changed

+73
-54
lines changed

src/librustc/mir/repr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -701,9 +701,9 @@ pub struct Constant<'tcx> {
701701
#[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable)]
702702
pub enum ItemKind {
703703
Constant,
704+
/// This is any sort of callable (usually those that have a type of `fn(…) -> …`). This
705+
/// includes functions, constructors, but not methods which have their own ItemKind.
704706
Function,
705-
Struct,
706-
Variant,
707707
Method,
708708
}
709709

src/librustc_mir/hair/cx/expr.rs

+29-29
Original file line numberDiff line numberDiff line change
@@ -519,51 +519,51 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
519519
let substs = cx.tcx.mk_substs(cx.tcx.node_id_item_substs(expr.id).substs);
520520
// Otherwise there may be def_map borrow conflicts
521521
let def = cx.tcx.def_map.borrow()[&expr.id].full_def();
522-
match def {
523-
def::DefVariant(_, def_id, false) |
524-
def::DefStruct(def_id) |
525-
def::DefFn(def_id, _) |
526-
def::DefMethod(def_id) => {
527-
let kind = match def {
528-
def::DefVariant(..) => ItemKind::Variant,
529-
def::DefStruct(..) => ItemKind::Struct,
530-
def::DefFn(..) => ItemKind::Function,
531-
def::DefMethod(..) => ItemKind::Method,
532-
_ => panic!()
533-
};
534-
ExprKind::Literal {
535-
literal: Literal::Item { def_id: def_id, kind: kind, substs: substs }
522+
let (def_id, kind) = match def {
523+
// A variant constructor.
524+
def::DefVariant(_, def_id, false) => (def_id, ItemKind::Function),
525+
// A regular function.
526+
def::DefFn(def_id, _) => (def_id, ItemKind::Function),
527+
def::DefMethod(def_id) => (def_id, ItemKind::Method),
528+
def::DefStruct(def_id) => {
529+
match cx.tcx.node_id_to_type(expr.id).sty {
530+
// A tuple-struct constructor.
531+
ty::TyBareFn(..) => (def_id, ItemKind::Function),
532+
// This is a special case: a unit struct which is used as a value. We return a
533+
// completely different ExprKind here to account for this special case.
534+
ty::TyStruct(adt_def, substs) => return ExprKind::Adt {
535+
adt_def: adt_def,
536+
variant_index: 0,
537+
substs: substs,
538+
fields: vec![],
539+
base: None
540+
},
541+
ref sty => panic!("unexpected sty: {:?}", sty)
536542
}
537543
},
538544
def::DefConst(def_id) |
539545
def::DefAssociatedConst(def_id) => {
540546
if let Some(v) = cx.try_const_eval_literal(expr) {
541-
ExprKind::Literal { literal: v }
547+
return ExprKind::Literal { literal: v };
542548
} else {
543-
ExprKind::Literal {
544-
literal: Literal::Item {
545-
def_id: def_id,
546-
kind: ItemKind::Constant,
547-
substs: substs
548-
}
549-
}
549+
(def_id, ItemKind::Constant)
550550
}
551551
}
552552

553-
554-
def::DefStatic(node_id, _) =>
555-
ExprKind::StaticRef {
556-
id: node_id,
557-
},
553+
def::DefStatic(node_id, _) => return ExprKind::StaticRef {
554+
id: node_id,
555+
},
558556

559557
def @ def::DefLocal(..) |
560-
def @ def::DefUpvar(..) =>
561-
convert_var(cx, expr, def),
558+
def @ def::DefUpvar(..) => return convert_var(cx, expr, def),
562559

563560
def =>
564561
cx.tcx.sess.span_bug(
565562
expr.span,
566563
&format!("def `{:?}` not yet implemented", def)),
564+
};
565+
ExprKind::Literal {
566+
literal: Literal::Item { def_id: def_id, kind: kind, substs: substs }
567567
}
568568
}
569569

src/librustc_trans/trans/mir/did.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
3939
did: DefId)
4040
-> OperandRef<'tcx> {
4141
match kind {
42-
ItemKind::Function |
43-
ItemKind::Struct |
44-
ItemKind::Variant => self.trans_fn_ref(bcx, ty, substs, did),
42+
ItemKind::Function => self.trans_fn_ref(bcx, ty, substs, did),
4543
ItemKind::Method => match bcx.tcx().impl_or_trait_item(did).container() {
4644
ty::ImplContainer(_) => self.trans_fn_ref(bcx, ty, substs, did),
4745
ty::TraitContainer(tdid) => self.trans_static_method(bcx, ty, did, tdid, substs)

src/librustc_trans/trans/mir/rvalue.rs

+31-18
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,30 @@ use trans::common::{self, Block, Result};
1919
use trans::debuginfo::DebugLoc;
2020
use trans::declare;
2121
use trans::expr;
22+
use trans::adt;
2223
use trans::machine;
2324
use trans::type_::Type;
2425
use trans::type_of;
2526
use trans::tvec;
2627

2728
use super::MirContext;
2829
use super::operand::{OperandRef, OperandValue};
30+
use super::lvalue::LvalueRef;
2931

3032
impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
3133
pub fn trans_rvalue(&mut self,
3234
bcx: Block<'bcx, 'tcx>,
33-
lldest: ValueRef,
35+
dest: LvalueRef<'tcx>,
3436
rvalue: &mir::Rvalue<'tcx>)
3537
-> Block<'bcx, 'tcx>
3638
{
37-
debug!("trans_rvalue(lldest={}, rvalue={:?})",
38-
bcx.val_to_string(lldest),
39+
debug!("trans_rvalue(dest.llval={}, rvalue={:?})",
40+
bcx.val_to_string(dest.llval),
3941
rvalue);
4042

4143
match *rvalue {
4244
mir::Rvalue::Use(ref operand) => {
43-
self.trans_operand_into(bcx, lldest, operand);
45+
self.trans_operand_into(bcx, dest.llval, operand);
4446
bcx
4547
}
4648

@@ -49,7 +51,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
4951
// into-coerce of a thin pointer to a fat pointer - just
5052
// use the operand path.
5153
let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
52-
self.store_operand(bcx, lldest, temp);
54+
self.store_operand(bcx, dest.llval, temp);
5355
return bcx;
5456
}
5557

@@ -72,12 +74,12 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
7274
base::store_ty(bcx, llval, lltemp, operand.ty);
7375
base::coerce_unsized_into(bcx,
7476
lltemp, operand.ty,
75-
lldest, cast_ty);
77+
dest.llval, cast_ty);
7678
}
7779
OperandValue::Ref(llref) => {
7880
base::coerce_unsized_into(bcx,
7981
llref, operand.ty,
80-
lldest, cast_ty);
82+
dest.llval, cast_ty);
8183
}
8284
}
8385
bcx
@@ -86,20 +88,31 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
8688
mir::Rvalue::Repeat(ref elem, ref count) => {
8789
let elem = self.trans_operand(bcx, elem);
8890
let size = self.trans_constant(bcx, count).immediate();
89-
let base = expr::get_dataptr(bcx, lldest);
91+
let base = expr::get_dataptr(bcx, dest.llval);
9092
tvec::iter_vec_raw(bcx, base, elem.ty, size, |bcx, llslot, _| {
9193
self.store_operand(bcx, llslot, elem);
9294
bcx
9395
})
9496
}
9597

96-
mir::Rvalue::Aggregate(_, ref operands) => {
97-
for (i, operand) in operands.iter().enumerate() {
98-
// Note: perhaps this should be StructGep, but
99-
// note that in some cases the values here will
100-
// not be structs but arrays.
101-
let lldest_i = build::GEPi(bcx, lldest, &[0, i]);
102-
self.trans_operand_into(bcx, lldest_i, operand);
98+
mir::Rvalue::Aggregate(ref kind, ref operands) => {
99+
match *kind {
100+
// Unit struct, which is translated very differently compared to any other
101+
// aggregate
102+
mir::AggregateKind::Adt(adt_def, 0, _)
103+
if adt_def.struct_variant().kind() == ty::VariantKind::Unit => {
104+
let repr = adt::represent_type(bcx.ccx(), dest.ty.to_ty(bcx.tcx()));
105+
adt::trans_set_discr(bcx, &*repr, dest.llval, 0);
106+
},
107+
_ => {
108+
for (i, operand) in operands.iter().enumerate() {
109+
// Note: perhaps this should be StructGep, but
110+
// note that in some cases the values here will
111+
// not be structs but arrays.
112+
let lldest_i = build::GEPi(bcx, dest.llval, &[0, i]);
113+
self.trans_operand_into(bcx, lldest_i, operand);
114+
}
115+
}
103116
}
104117
bcx
105118
}
@@ -113,9 +126,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
113126
let llbase1 = build::GEPi(bcx, llbase, &[from_start]);
114127
let adj = common::C_uint(ccx, from_start + from_end);
115128
let lllen1 = build::Sub(bcx, lllen, adj, DebugLoc::None);
116-
let lladdrdest = expr::get_dataptr(bcx, lldest);
129+
let lladdrdest = expr::get_dataptr(bcx, dest.llval);
117130
build::Store(bcx, llbase1, lladdrdest);
118-
let llmetadest = expr::get_meta(bcx, lldest);
131+
let llmetadest = expr::get_meta(bcx, dest.llval);
119132
build::Store(bcx, lllen1, llmetadest);
120133
bcx
121134
}
@@ -127,7 +140,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
127140
_ => {
128141
assert!(rvalue_creates_operand(rvalue));
129142
let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
130-
self.store_operand(bcx, lldest, temp);
143+
self.store_operand(bcx, dest.llval, temp);
131144
bcx
132145
}
133146
}

src/librustc_trans/trans/mir/statement.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
3131
let index = index as usize;
3232
match self.temps[index as usize] {
3333
TempRef::Lvalue(tr_dest) => {
34-
self.trans_rvalue(bcx, tr_dest.llval, rvalue)
34+
self.trans_rvalue(bcx, tr_dest, rvalue)
3535
}
3636
TempRef::Operand(None) => {
3737
let (bcx, operand) = self.trans_rvalue_operand(bcx, rvalue);
@@ -47,7 +47,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
4747
}
4848
_ => {
4949
let tr_dest = self.trans_lvalue(bcx, lvalue);
50-
self.trans_rvalue(bcx, tr_dest.llval, rvalue)
50+
self.trans_rvalue(bcx, tr_dest, rvalue)
5151
}
5252
}
5353
}

src/test/run-pass/mir_refs_correct.rs

+8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
extern crate mir_external_refs as ext;
1515

1616
struct S(u8);
17+
#[derive(Debug, PartialEq, Eq)]
18+
struct Unit;
1719

1820
impl S {
1921
fn hey() -> u8 { 42 }
@@ -175,6 +177,11 @@ fn t20() -> fn(u64, u32)->(u64, u32) {
175177
<u32 as T<_, _>>::staticmeth
176178
}
177179

180+
#[rustc_mir]
181+
fn t21() -> Unit {
182+
Unit
183+
}
184+
178185
fn main(){
179186
unsafe {
180187
assert_eq!(t1()(), regular());
@@ -214,5 +221,6 @@ fn main(){
214221
assert_eq!(t18()(50u64, 5u64), F::f(50u64, 5u64));
215222
assert_eq!(t19()(322u64, 2u32), F::f(322u64, 2u32));
216223
assert_eq!(t20()(123u64, 38u32), <u32 as T<_, _>>::staticmeth(123, 38));
224+
assert_eq!(t21(), Unit);
217225
}
218226
}

0 commit comments

Comments
 (0)