Mark enums with non-zero discriminant as non-zero
This commit is contained in:
parent
6dc035ed91
commit
49e6b466e9
@ -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.
|
||||
|
39
src/test/run-pass/nonzero-enum.rs
Normal file
39
src/test/run-pass/nonzero-enum.rs
Normal file
@ -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!();
|
||||
}
|
||||
}
|
@ -15,6 +15,8 @@
|
||||
#![feature(test)]
|
||||
#![feature(libc)]
|
||||
|
||||
#![cfg_attr(stage0, feature(question_mark))]
|
||||
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate libc;
|
||||
|
Loading…
Reference in New Issue
Block a user