diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 46e6243c8bf30..ce78a39d599a5 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -520,26 +520,39 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr) // Otherwise there may be def_map borrow conflicts let def = cx.tcx.def_map.borrow()[&expr.id].full_def(); 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 { + 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::DefVariant(enum_id, variant_id, false) => match cx.tcx.node_id_to_type(expr.id).sty { + // A variant constructor. + ty::TyBareFn(..) => (variant_id, ItemKind::Function), + // A unit variant, similar special case to the struct case above. + ty::TyEnum(adt_def, substs) => { + debug_assert!(adt_def.did == enum_id); + let index = adt_def.variant_index_with_id(variant_id); + return ExprKind::Adt { adt_def: adt_def, - variant_index: 0, substs: substs, + variant_index: index, fields: vec![], base: None - }, - ref sty => panic!("unexpected sty: {:?}", sty) - } + }; + }, + ref sty => panic!("unexpected sty: {:?}", sty) }, def::DefConst(def_id) | def::DefAssociatedConst(def_id) => { diff --git a/src/librustc_trans/trans/mir/rvalue.rs b/src/librustc_trans/trans/mir/rvalue.rs index 55a41201b2ba1..a08ec123895df 100644 --- a/src/librustc_trans/trans/mir/rvalue.rs +++ b/src/librustc_trans/trans/mir/rvalue.rs @@ -97,10 +97,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { 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 => { + // Unit struct or variant; both are translated very differently compared to any + // other aggregate + mir::AggregateKind::Adt(adt_def, index, _) + if adt_def.variants[index].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); }, diff --git a/src/test/run-pass/mir_refs_correct.rs b/src/test/run-pass/mir_refs_correct.rs index 9b349c0e4e21b..2c0cd5d6c8ad6 100644 --- a/src/test/run-pass/mir_refs_correct.rs +++ b/src/test/run-pass/mir_refs_correct.rs @@ -182,6 +182,11 @@ fn t21() -> Unit { Unit } +#[rustc_mir] +fn t22() -> Option { + None +} + fn main(){ unsafe { assert_eq!(t1()(), regular()); @@ -222,5 +227,6 @@ fn main(){ assert_eq!(t19()(322u64, 2u32), F::f(322u64, 2u32)); assert_eq!(t20()(123u64, 38u32), >::staticmeth(123, 38)); assert_eq!(t21(), Unit); + assert_eq!(t22(), None); } }