diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index ec6843eb75d1f..5ce43d905ec71 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -597,7 +597,8 @@ impl<'a, 'gcx, 'tcx> Struct {
                                   -> Result<Option<FieldPath>, LayoutError<'gcx>> {
         let tcx = infcx.tcx.global_tcx();
         match (ty.layout(infcx)?, &ty.sty) {
-            (&Scalar { non_zero: true, .. }, _) => Ok(Some(vec![])),
+            (&Scalar { non_zero: true, .. }, _) |
+            (&CEnum { non_zero: true, .. }, _) => Ok(Some(vec![])),
             (&FatPointer { non_zero: true, .. }, _) => {
                 Ok(Some(vec![FAT_PTR_ADDR as u32]))
             }
@@ -769,6 +770,7 @@ pub enum Layout {
     CEnum {
         discr: Integer,
         signed: bool,
+        non_zero: bool,
         // Inclusive discriminant range.
         // If min > max, it represents min...u64::MAX followed by 0...max.
         // FIXME(eddyb) always use the shortest range, e.g. by finding
@@ -1002,9 +1004,10 @@ impl<'a, 'gcx, 'tcx> Layout {
 
                 if def.is_enum() && def.variants.iter().all(|v| v.fields.is_empty()) {
                     // All bodies empty -> intlike
-                    let (mut min, mut max) = (i64::MAX, i64::MIN);
+                    let (mut min, mut max, mut non_zero) = (i64::MAX, i64::MIN, true);
                     for v in &def.variants {
                         let x = v.disr_val.to_u64_unchecked() as i64;
+                        if x == 0 { non_zero = false; }
                         if x < min { min = x; }
                         if x > max { max = x; }
                     }
@@ -1013,6 +1016,7 @@ impl<'a, 'gcx, 'tcx> Layout {
                     return success(CEnum {
                         discr: discr,
                         signed: signed,
+                        non_zero: non_zero,
                         min: min as u64,
                         max: max as u64
                     });
@@ -1069,19 +1073,17 @@ impl<'a, 'gcx, 'tcx> Layout {
 
                         // FIXME(eddyb) should take advantage of a newtype.
                         if path == &[0] && variants[discr].len() == 1 {
-                            match *variants[discr][0].layout(infcx)? {
-                                Scalar { value, .. } => {
-                                    return success(RawNullablePointer {
-                                        nndiscr: discr as u64,
-                                        value: value
-                                    });
-                                }
-                                _ => {
-                                    bug!("Layout::compute: `{}`'s non-zero \
-                                        `{}` field not scalar?!",
-                                        ty, variants[discr][0])
-                                }
-                            }
+                            let value = match *variants[discr][0].layout(infcx)? {
+                                Scalar { value, .. } => value,
+                                CEnum { discr, .. } => Int(discr),
+                                _ => bug!("Layout::compute: `{}`'s non-zero \
+                                           `{}` field not scalar?!",
+                                           ty, variants[discr][0])
+                            };
+                            return success(RawNullablePointer {
+                                nndiscr: discr as u64,
+                                value: value,
+                            });
                         }
 
                         path.push(0); // For GEP through a pointer.
diff --git a/src/test/run-pass/nonzero-enum.rs b/src/test/run-pass/nonzero-enum.rs
new file mode 100644
index 0000000000000..266506e04b74d
--- /dev/null
+++ b/src/test/run-pass/nonzero-enum.rs
@@ -0,0 +1,39 @@
+// 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.
+
+use std::mem::size_of;
+
+enum E {
+    A = 1,
+    B = 2,
+    C = 3,
+}
+
+struct S {
+    a: u16,
+    b: u8,
+    e: E,
+}
+
+fn main() {
+    assert_eq!(size_of::<E>(), 1);
+    assert_eq!(size_of::<Option<E>>(), 1);
+    assert_eq!(size_of::<Result<E, ()>>(), 1);
+    assert_eq!(size_of::<S>(), 4);
+    assert_eq!(size_of::<Option<S>>(), 4);
+    let enone = None::<E>;
+    let esome = Some(E::A);
+    if let Some(..) = enone {
+        panic!();
+    }
+    if let None = esome {
+        panic!();
+    }
+}
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index 81478c18d7b24..e6efd45cad186 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -15,6 +15,8 @@
 #![feature(test)]
 #![feature(libc)]
 
+#![cfg_attr(stage0, feature(question_mark))]
+
 #![deny(warnings)]
 
 extern crate libc;