Auto merge of #39686 - frewsxcv:rollup, r=frewsxcv

Rollup of 5 pull requests

- Successful merges: #39595, #39601, #39602, #39615, #39647
- Failed merges:
This commit is contained in:
bors 2017-02-09 14:25:04 +00:00
commit e7fc53b8f0
16 changed files with 279 additions and 187 deletions

View File

@ -14,6 +14,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
zlib1g-dev \
g++-arm-linux-gnueabi \
g++-arm-linux-gnueabihf \
gcc-sparc64-linux-gnu \
libc6-dev-sparc64-cross \
bzip2 \
patch
@ -60,9 +62,11 @@ ENV TARGETS=$TARGETS,mipsel-unknown-linux-musl
ENV TARGETS=$TARGETS,arm-unknown-linux-musleabi
ENV TARGETS=$TARGETS,arm-unknown-linux-musleabihf
ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabihf
ENV TARGETS=$TARGETS,sparc64-unknown-linux-gnu
ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \
CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc
CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \
CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc
# Suppress some warnings in the openwrt toolchains we downloaded
ENV STAGING_DIR=/tmp

94
src/libcore/fmt/float.rs Normal file
View File

@ -0,0 +1,94 @@
// Copyright 2017 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 fmt::{Formatter, Result, LowerExp, UpperExp, Display, Debug};
use num::flt2dec;
// Common code of floating point Debug and Display.
fn float_to_decimal_common<T>(fmt: &mut Formatter, num: &T, negative_zero: bool) -> Result
where T: flt2dec::DecodableFloat
{
let force_sign = fmt.sign_plus();
let sign = match (force_sign, negative_zero) {
(false, false) => flt2dec::Sign::Minus,
(false, true) => flt2dec::Sign::MinusRaw,
(true, false) => flt2dec::Sign::MinusPlus,
(true, true) => flt2dec::Sign::MinusPlusRaw,
};
let mut buf = [0; 1024]; // enough for f32 and f64
let mut parts = [flt2dec::Part::Zero(0); 16];
let formatted = if let Some(precision) = fmt.precision {
flt2dec::to_exact_fixed_str(flt2dec::strategy::grisu::format_exact, *num, sign,
precision, false, &mut buf, &mut parts)
} else {
flt2dec::to_shortest_str(flt2dec::strategy::grisu::format_shortest, *num, sign,
0, false, &mut buf, &mut parts)
};
fmt.pad_formatted_parts(&formatted)
}
// Common code of floating point LowerExp and UpperExp.
fn float_to_exponential_common<T>(fmt: &mut Formatter, num: &T, upper: bool) -> Result
where T: flt2dec::DecodableFloat
{
let force_sign = fmt.sign_plus();
let sign = match force_sign {
false => flt2dec::Sign::Minus,
true => flt2dec::Sign::MinusPlus,
};
let mut buf = [0; 1024]; // enough for f32 and f64
let mut parts = [flt2dec::Part::Zero(0); 16];
let formatted = if let Some(precision) = fmt.precision {
// 1 integral digit + `precision` fractional digits = `precision + 1` total digits
flt2dec::to_exact_exp_str(flt2dec::strategy::grisu::format_exact, *num, sign,
precision + 1, upper, &mut buf, &mut parts)
} else {
flt2dec::to_shortest_exp_str(flt2dec::strategy::grisu::format_shortest, *num, sign,
(0, 0), upper, &mut buf, &mut parts)
};
fmt.pad_formatted_parts(&formatted)
}
macro_rules! floating {
($ty:ident) => (
#[stable(feature = "rust1", since = "1.0.0")]
impl Debug for $ty {
fn fmt(&self, fmt: &mut Formatter) -> Result {
float_to_decimal_common(fmt, self, true)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Display for $ty {
fn fmt(&self, fmt: &mut Formatter) -> Result {
float_to_decimal_common(fmt, self, false)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl LowerExp for $ty {
fn fmt(&self, fmt: &mut Formatter) -> Result {
float_to_exponential_common(fmt, self, false)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl UpperExp for $ty {
fn fmt(&self, fmt: &mut Formatter) -> Result {
float_to_exponential_common(fmt, self, true)
}
}
)
}
floating! { f32 }
floating! { f64 }

View File

@ -21,6 +21,10 @@ use result;
use slice;
use str;
mod float;
mod num;
mod builders;
#[unstable(feature = "fmt_flags_align", issue = "27726")]
/// Possible alignments returned by `Formatter::align`
#[derive(Debug)]
@ -38,9 +42,6 @@ pub enum Alignment {
#[stable(feature = "debug_builders", since = "1.2.0")]
pub use self::builders::{DebugStruct, DebugTuple, DebugSet, DebugList, DebugMap};
mod num;
mod builders;
#[unstable(feature = "fmt_internals", reason = "internal to format_args!",
issue = "0")]
#[doc(hidden)]
@ -1511,86 +1512,6 @@ impl<'a, T: ?Sized> Pointer for &'a mut T {
}
}
// Common code of floating point Debug and Display.
fn float_to_decimal_common<T>(fmt: &mut Formatter, num: &T, negative_zero: bool) -> Result
where T: flt2dec::DecodableFloat
{
let force_sign = fmt.sign_plus();
let sign = match (force_sign, negative_zero) {
(false, false) => flt2dec::Sign::Minus,
(false, true) => flt2dec::Sign::MinusRaw,
(true, false) => flt2dec::Sign::MinusPlus,
(true, true) => flt2dec::Sign::MinusPlusRaw,
};
let mut buf = [0; 1024]; // enough for f32 and f64
let mut parts = [flt2dec::Part::Zero(0); 16];
let formatted = if let Some(precision) = fmt.precision {
flt2dec::to_exact_fixed_str(flt2dec::strategy::grisu::format_exact, *num, sign,
precision, false, &mut buf, &mut parts)
} else {
flt2dec::to_shortest_str(flt2dec::strategy::grisu::format_shortest, *num, sign,
0, false, &mut buf, &mut parts)
};
fmt.pad_formatted_parts(&formatted)
}
// Common code of floating point LowerExp and UpperExp.
fn float_to_exponential_common<T>(fmt: &mut Formatter, num: &T, upper: bool) -> Result
where T: flt2dec::DecodableFloat
{
let force_sign = fmt.sign_plus();
let sign = match force_sign {
false => flt2dec::Sign::Minus,
true => flt2dec::Sign::MinusPlus,
};
let mut buf = [0; 1024]; // enough for f32 and f64
let mut parts = [flt2dec::Part::Zero(0); 16];
let formatted = if let Some(precision) = fmt.precision {
// 1 integral digit + `precision` fractional digits = `precision + 1` total digits
flt2dec::to_exact_exp_str(flt2dec::strategy::grisu::format_exact, *num, sign,
precision + 1, upper, &mut buf, &mut parts)
} else {
flt2dec::to_shortest_exp_str(flt2dec::strategy::grisu::format_shortest, *num, sign,
(0, 0), upper, &mut buf, &mut parts)
};
fmt.pad_formatted_parts(&formatted)
}
macro_rules! floating { ($ty:ident) => {
#[stable(feature = "rust1", since = "1.0.0")]
impl Debug for $ty {
fn fmt(&self, fmt: &mut Formatter) -> Result {
float_to_decimal_common(fmt, self, true)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Display for $ty {
fn fmt(&self, fmt: &mut Formatter) -> Result {
float_to_decimal_common(fmt, self, false)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl LowerExp for $ty {
fn fmt(&self, fmt: &mut Formatter) -> Result {
float_to_exponential_common(fmt, self, false)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl UpperExp for $ty {
fn fmt(&self, fmt: &mut Formatter) -> Result {
float_to_exponential_common(fmt, self, true)
}
}
} }
floating! { f32 }
floating! { f64 }
// Implementation of Display/Debug for various core types
#[stable(feature = "rust1", since = "1.0.0")]

View File

@ -9,11 +9,29 @@
// except according to those terms.
#[test]
fn test_format_float() {
assert!("1" == format!("{:.0}", 1.0f64));
assert!("9" == format!("{:.0}", 9.4f64));
assert!("10" == format!("{:.0}", 9.9f64));
assert!("9.8" == format!("{:.1}", 9.849f64));
assert!("9.9" == format!("{:.1}", 9.851f64));
assert!("1" == format!("{:.0}", 0.5f64));
fn test_format_f64() {
assert_eq!("1", format!("{:.0}", 1.0f64));
assert_eq!("9", format!("{:.0}", 9.4f64));
assert_eq!("10", format!("{:.0}", 9.9f64));
assert_eq!("9.8", format!("{:.1}", 9.849f64));
assert_eq!("9.9", format!("{:.1}", 9.851f64));
assert_eq!("1", format!("{:.0}", 0.5f64));
assert_eq!("1.23456789e6", format!("{:e}", 1234567.89f64));
assert_eq!("1.23456789e3", format!("{:e}", 1234.56789f64));
assert_eq!("1.23456789E6", format!("{:E}", 1234567.89f64));
assert_eq!("1.23456789E3", format!("{:E}", 1234.56789f64));
}
#[test]
fn test_format_f32() {
assert_eq!("1", format!("{:.0}", 1.0f32));
assert_eq!("9", format!("{:.0}", 9.4f32));
assert_eq!("10", format!("{:.0}", 9.9f32));
assert_eq!("9.8", format!("{:.1}", 9.849f32));
assert_eq!("9.9", format!("{:.1}", 9.851f32));
assert_eq!("1", format!("{:.0}", 0.5f32));
assert_eq!("1.2345679e6", format!("{:e}", 1234567.89f32));
assert_eq!("1.2345679e3", format!("{:e}", 1234.56789f32));
assert_eq!("1.2345679E6", format!("{:E}", 1234567.89f32));
assert_eq!("1.2345679E3", format!("{:E}", 1234.56789f32));
}

@ -1 +1 @@
Subproject commit cb7f66732175e6171587ed69656b7aae7dd2e6ec
Subproject commit 8d8264b967a31a1a8cebe2a05110564106b6e909

View File

@ -202,7 +202,9 @@ impl<'tcx> cmt_<'tcx> {
Categorization::Downcast(ref cmt, _) => {
if let Categorization::Local(_) = cmt.cat {
if let ty::TyAdt(def, _) = self.ty.sty {
return def.struct_variant().find_field_named(name).map(|x| x.did);
if def.is_struct() {
return def.struct_variant().find_field_named(name).map(|x| x.did);
}
}
None
} else {

View File

@ -26,6 +26,7 @@ use middle::resolve_lifetime;
use middle::stability;
use mir::Mir;
use ty::subst::{Kind, Substs};
use ty::ReprOptions;
use traits;
use ty::{self, TraitRef, Ty, TypeAndMut};
use ty::{TyS, TypeVariants, Slice};
@ -672,9 +673,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
pub fn alloc_adt_def(self,
did: DefId,
kind: AdtKind,
variants: Vec<ty::VariantDef>)
variants: Vec<ty::VariantDef>,
repr: ReprOptions)
-> &'gcx ty::AdtDef {
let def = ty::AdtDef::new(self, did, kind, variants);
let def = ty::AdtDef::new(self, did, kind, variants, repr);
self.global_arenas.adt_def.alloc(def)
}

View File

@ -15,7 +15,7 @@ pub use self::Primitive::*;
use infer::InferCtxt;
use session::Session;
use traits;
use ty::{self, Ty, TyCtxt, TypeFoldable};
use ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions};
use syntax::ast::{FloatTy, IntTy, UintTy};
use syntax::attr;
@ -437,7 +437,7 @@ impl Integer {
/// signed discriminant range and #[repr] attribute.
/// N.B.: u64 values above i64::MAX will be treated as signed, but
/// that shouldn't affect anything, other than maybe debuginfo.
fn repr_discr(tcx: TyCtxt, ty: Ty, hints: &[attr::ReprAttr], min: i64, max: i64)
fn repr_discr(tcx: TyCtxt, ty: Ty, repr: &ReprOptions, min: i64, max: i64)
-> (Integer, bool) {
// Theoretically, negative values could be larger in unsigned representation
// than the unsigned representation of the signed minimum. However, if there
@ -449,34 +449,24 @@ impl Integer {
let mut min_from_extern = None;
let min_default = I8;
for &r in hints.iter() {
match r {
attr::ReprInt(ity) => {
let discr = Integer::from_attr(&tcx.data_layout, ity);
let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
if discr < fit {
bug!("Integer::repr_discr: `#[repr]` hint too small for \
discriminant range of enum `{}", ty)
}
return (discr, ity.is_signed());
}
attr::ReprExtern => {
match &tcx.sess.target.target.arch[..] {
// WARNING: the ARM EABI has two variants; the one corresponding
// to `at_least == I32` appears to be used on Linux and NetBSD,
// but some systems may use the variant corresponding to no
// lower bound. However, we don't run on those yet...?
"arm" => min_from_extern = Some(I32),
_ => min_from_extern = Some(I32),
}
}
attr::ReprAny => {},
attr::ReprPacked => {
bug!("Integer::repr_discr: found #[repr(packed)] on enum `{}", ty);
}
attr::ReprSimd => {
bug!("Integer::repr_discr: found #[repr(simd)] on enum `{}", ty);
}
if let Some(ity) = repr.int {
let discr = Integer::from_attr(&tcx.data_layout, ity);
let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
if discr < fit {
bug!("Integer::repr_discr: `#[repr]` hint too small for \
discriminant range of enum `{}", ty)
}
return (discr, ity.is_signed());
}
if repr.c {
match &tcx.sess.target.target.arch[..] {
// WARNING: the ARM EABI has two variants; the one corresponding
// to `at_least == I32` appears to be used on Linux and NetBSD,
// but some systems may use the variant corresponding to no
// lower bound. However, we don't run on those yet...?
"arm" => min_from_extern = Some(I32),
_ => min_from_extern = Some(I32),
}
}
@ -568,9 +558,9 @@ enum StructKind {
impl<'a, 'gcx, 'tcx> Struct {
// FIXME(camlorn): reprs need a better representation to deal with multiple reprs on one type.
fn new(dl: &TargetDataLayout, fields: &Vec<&'a Layout>,
reprs: &[attr::ReprAttr], kind: StructKind,
repr: &ReprOptions, kind: StructKind,
scapegoat: Ty<'gcx>) -> Result<Struct, LayoutError<'gcx>> {
let packed = reprs.contains(&attr::ReprPacked);
let packed = repr.packed;
let mut ret = Struct {
align: if packed { dl.i8_align } else { dl.aggregate_align },
packed: packed,
@ -580,27 +570,16 @@ impl<'a, 'gcx, 'tcx> Struct {
min_size: Size::from_bytes(0),
};
// Anything with ReprExtern or ReprPacked doesn't optimize.
// Anything with repr(C) or repr(packed) doesn't optimize.
// Neither do 1-member and 2-member structs.
// In addition, code in trans assume that 2-element structs can become pairs.
// It's easier to just short-circuit here.
let mut can_optimize = fields.len() > 2 || StructKind::EnumVariant == kind;
if can_optimize {
// This exhaustive match makes new reprs force the adder to modify this function.
// Otherwise, things can silently break.
// Note the inversion, return true to stop optimizing.
can_optimize = !reprs.iter().any(|r| {
match *r {
attr::ReprAny | attr::ReprInt(_) => false,
attr::ReprExtern | attr::ReprPacked => true,
attr::ReprSimd => bug!("Simd vectors should be represented as layout::Vector")
}
});
}
let mut can_optimize = (fields.len() > 2 || StructKind::EnumVariant == kind)
&& ! (repr.c || repr.packed);
// Disable field reordering until we can decide what to do.
// The odd pattern here avoids a warning about the value never being read.
if can_optimize { can_optimize = false }
if can_optimize { can_optimize = false; }
let (optimize, sort_ascending) = match kind {
StructKind::AlwaysSizedUnivariant => (can_optimize, false),
@ -1092,7 +1071,7 @@ impl<'a, 'gcx, 'tcx> Layout {
// The never type.
ty::TyNever => Univariant {
variant: Struct::new(dl, &vec![], &[],
variant: Struct::new(dl, &vec![], &ReprOptions::default(),
StructKind::AlwaysSizedUnivariant, ty)?,
non_zero: false
},
@ -1135,12 +1114,12 @@ impl<'a, 'gcx, 'tcx> Layout {
ty::TyFnDef(..) => {
Univariant {
variant: Struct::new(dl, &vec![],
&[], StructKind::AlwaysSizedUnivariant, ty)?,
&ReprOptions::default(), StructKind::AlwaysSizedUnivariant, ty)?,
non_zero: false
}
}
ty::TyDynamic(..) => {
let mut unit = Struct::new(dl, &vec![], &[],
let mut unit = Struct::new(dl, &vec![], &ReprOptions::default(),
StructKind::AlwaysSizedUnivariant, ty)?;
unit.sized = false;
Univariant { variant: unit, non_zero: false }
@ -1152,7 +1131,7 @@ impl<'a, 'gcx, 'tcx> Layout {
let st = Struct::new(dl,
&tys.map(|ty| ty.layout(infcx))
.collect::<Result<Vec<_>, _>>()?,
&[],
&ReprOptions::default(),
StructKind::AlwaysSizedUnivariant, ty)?;
Univariant { variant: st, non_zero: false }
}
@ -1163,7 +1142,7 @@ impl<'a, 'gcx, 'tcx> Layout {
let st = Struct::new(dl,
&tys.iter().map(|ty| ty.layout(infcx))
.collect::<Result<Vec<_>, _>>()?,
&[], StructKind::AlwaysSizedUnivariant, ty)?;
&ReprOptions::default(), StructKind::AlwaysSizedUnivariant, ty)?;
Univariant { variant: st, non_zero: false }
}
@ -1187,16 +1166,13 @@ impl<'a, 'gcx, 'tcx> Layout {
// ADTs.
ty::TyAdt(def, substs) => {
let hints = &tcx.lookup_repr_hints(def.did)[..];
if def.variants.is_empty() {
// Uninhabitable; represent as unit
// (Typechecking will reject discriminant-sizing attrs.)
assert_eq!(hints.len(), 0);
return success(Univariant {
variant: Struct::new(dl, &vec![],
&hints[..], StructKind::AlwaysSizedUnivariant, ty)?,
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?,
non_zero: false
});
}
@ -1219,7 +1195,7 @@ impl<'a, 'gcx, 'tcx> Layout {
// FIXME: should handle i128? signed-value based impl is weird and hard to
// grok.
let (discr, signed) = Integer::repr_discr(tcx, ty, &hints[..],
let (discr, signed) = Integer::repr_discr(tcx, ty, &def.repr,
min,
max);
return success(CEnum {
@ -1232,7 +1208,7 @@ impl<'a, 'gcx, 'tcx> Layout {
});
}
if !def.is_enum() || def.variants.len() == 1 && hints.is_empty() {
if !def.is_enum() || def.variants.len() == 1 {
// Struct, or union, or univariant enum equivalent to a struct.
// (Typechecking will reject discriminant-sizing attrs.)
@ -1259,7 +1235,7 @@ impl<'a, 'gcx, 'tcx> Layout {
un.extend(dl, fields.iter().map(|&f| Ok(f)), ty)?;
UntaggedUnion { variants: un }
} else {
let st = Struct::new(dl, &fields, &hints[..],
let st = Struct::new(dl, &fields, &def.repr,
kind, ty)?;
let non_zero = Some(def.did) == tcx.lang_items.non_zero();
Univariant { variant: st, non_zero: non_zero }
@ -1282,7 +1258,7 @@ impl<'a, 'gcx, 'tcx> Layout {
v.fields.iter().map(|field| field.ty(tcx, substs)).collect::<Vec<_>>()
}).collect::<Vec<_>>();
if variants.len() == 2 && hints.is_empty() {
if variants.len() == 2 && !def.repr.c {
// Nullable pointer optimization
for discr in 0..2 {
let other_fields = variants[1 - discr].iter().map(|ty| {
@ -1315,7 +1291,7 @@ impl<'a, 'gcx, 'tcx> Layout {
let st = Struct::new(dl,
&variants[discr].iter().map(|ty| ty.layout(infcx))
.collect::<Result<Vec<_>, _>>()?,
&hints[..], StructKind::AlwaysSizedUnivariant, ty)?;
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?;
// We have to fix the last element of path here.
let mut i = *path.last().unwrap();
@ -1338,7 +1314,7 @@ impl<'a, 'gcx, 'tcx> Layout {
// The general case.
let discr_max = (variants.len() - 1) as i64;
assert!(discr_max >= 0);
let (min_ity, _) = Integer::repr_discr(tcx, ty, &hints[..], 0, discr_max);
let (min_ity, _) = Integer::repr_discr(tcx, ty, &def.repr, 0, discr_max);
let mut align = dl.aggregate_align;
let mut size = Size::from_bytes(0);
@ -1356,7 +1332,7 @@ impl<'a, 'gcx, 'tcx> Layout {
fields.insert(0, &discr);
let st = Struct::new(dl,
&fields,
&hints[..], StructKind::EnumVariant, ty)?;
&def.repr, StructKind::EnumVariant, ty)?;
// Find the first field we can't move later
// to make room for a larger discriminant.
// It is important to skip the first field.

View File

@ -1327,7 +1327,8 @@ pub struct AdtDef {
pub did: DefId,
pub variants: Vec<VariantDef>,
destructor: Cell<Option<DefId>>,
flags: Cell<AdtFlags>
flags: Cell<AdtFlags>,
pub repr: ReprOptions,
}
impl PartialEq for AdtDef {
@ -1356,11 +1357,38 @@ impl<'tcx> serialize::UseSpecializedDecodable for &'tcx AdtDef {}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum AdtKind { Struct, Union, Enum }
/// Represents the repr options provided by the user,
#[derive(Copy, Clone, Eq, PartialEq, RustcEncodable, RustcDecodable, Default)]
pub struct ReprOptions {
pub c: bool,
pub packed: bool,
pub simd: bool,
pub int: Option<attr::IntType>,
}
impl ReprOptions {
pub fn new<'a, 'gcx, 'tcx>(tcx: &TyCtxt<'a, 'gcx, 'tcx>, did: DefId) -> ReprOptions {
let mut ret = ReprOptions::default();
let attrs = tcx.lookup_repr_hints(did);
for r in attrs.iter() {
match *r {
attr::ReprExtern => ret.c = true,
attr::ReprPacked => ret.packed = true,
attr::ReprSimd => ret.simd = true,
attr::ReprInt(i) => ret.int = Some(i),
attr::ReprAny => (),
}
}
ret
}
}
impl<'a, 'gcx, 'tcx> AdtDef {
fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
did: DefId,
kind: AdtKind,
variants: Vec<VariantDef>) -> Self {
variants: Vec<VariantDef>,
repr: ReprOptions) -> Self {
let mut flags = AdtFlags::NO_ADT_FLAGS;
let attrs = tcx.get_attrs(did);
if attr::contains_name(&attrs, "fundamental") {
@ -1385,6 +1413,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
variants: variants,
flags: Cell::new(flags),
destructor: Cell::new(None),
repr: repr,
}
}

View File

@ -425,8 +425,8 @@ impl<'tcx> EntryKind<'tcx> {
EntryKind::ForeignImmStatic => Def::Static(did, false),
EntryKind::MutStatic |
EntryKind::ForeignMutStatic => Def::Static(did, true),
EntryKind::Struct(_) => Def::Struct(did),
EntryKind::Union(_) => Def::Union(did),
EntryKind::Struct(_, _) => Def::Struct(did),
EntryKind::Union(_, _) => Def::Union(did),
EntryKind::Fn(_) |
EntryKind::ForeignFn(_) => Def::Fn(did),
EntryKind::Method(_) => Def::Method(did),
@ -435,7 +435,7 @@ impl<'tcx> EntryKind<'tcx> {
EntryKind::Mod(_) => Def::Mod(did),
EntryKind::Variant(_) => Def::Variant(did),
EntryKind::Trait(_) => Def::Trait(did),
EntryKind::Enum => Def::Enum(did),
EntryKind::Enum(_) => Def::Enum(did),
EntryKind::MacroDef(_) => Def::Macro(did),
EntryKind::ForeignMod |
@ -519,8 +519,8 @@ impl<'a, 'tcx> CrateMetadata {
-> (ty::VariantDef, Option<DefIndex>) {
let data = match item.kind {
EntryKind::Variant(data) |
EntryKind::Struct(data) |
EntryKind::Union(data) => data.decode(self),
EntryKind::Struct(data, _) |
EntryKind::Union(data, _) => data.decode(self),
_ => bug!(),
};
@ -547,7 +547,7 @@ impl<'a, 'tcx> CrateMetadata {
let item = self.entry(item_id);
let did = self.local_def_id(item_id);
let mut ctor_index = None;
let variants = if let EntryKind::Enum = item.kind {
let variants = if let EntryKind::Enum(_) = item.kind {
item.children
.decode(self)
.map(|index| {
@ -561,14 +561,14 @@ impl<'a, 'tcx> CrateMetadata {
ctor_index = struct_ctor;
vec![variant]
};
let kind = match item.kind {
EntryKind::Enum => ty::AdtKind::Enum,
EntryKind::Struct(_) => ty::AdtKind::Struct,
EntryKind::Union(_) => ty::AdtKind::Union,
let (kind, repr) = match item.kind {
EntryKind::Enum(repr) => (ty::AdtKind::Enum, repr),
EntryKind::Struct(_, repr) => (ty::AdtKind::Struct, repr),
EntryKind::Union(_, repr) => (ty::AdtKind::Union, repr),
_ => bug!("get_adt_def called on a non-ADT {:?}", did),
};
let adt = tcx.alloc_adt_def(did, kind, variants);
let adt = tcx.alloc_adt_def(did, kind, variants, repr);
if let Some(ctor_index) = ctor_index {
// Make adt definition available through constructor id as well.
tcx.adt_defs.borrow_mut().insert(self.local_def_id(ctor_index), adt);
@ -881,8 +881,8 @@ impl<'a, 'tcx> CrateMetadata {
pub fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind {
match self.entry(node_id).kind {
EntryKind::Struct(data) |
EntryKind::Union(data) |
EntryKind::Struct(data, _) |
EntryKind::Union(data, _) |
EntryKind::Variant(data) => data.decode(self).ctor_kind,
_ => CtorKind::Fictive,
}
@ -890,7 +890,7 @@ impl<'a, 'tcx> CrateMetadata {
pub fn get_struct_ctor_def_id(&self, node_id: DefIndex) -> Option<DefId> {
match self.entry(node_id).kind {
EntryKind::Struct(data) => {
EntryKind::Struct(data, _) => {
data.decode(self).struct_ctor.map(|index| self.local_def_id(index))
}
_ => None,

View File

@ -20,7 +20,7 @@ use rustc::middle::dependency_format::Linkage;
use rustc::middle::lang_items;
use rustc::mir;
use rustc::traits::specialization_graph;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::{self, Ty, TyCtxt, ReprOptions};
use rustc::session::config::{self, CrateTypeProcMacro};
use rustc::util::nodemap::{FxHashMap, NodeSet};
@ -401,8 +401,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
}
let repr_options = get_repr_options(&tcx, adt_def_id);
Entry {
kind: EntryKind::Struct(self.lazy(&data)),
kind: EntryKind::Struct(self.lazy(&data), repr_options),
visibility: self.lazy(&ctor_vis),
span: self.lazy(&tcx.def_span(def_id)),
attributes: LazySeq::empty(),
@ -659,7 +661,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
hir::ItemForeignMod(_) => EntryKind::ForeignMod,
hir::ItemTy(..) => EntryKind::Type,
hir::ItemEnum(..) => EntryKind::Enum,
hir::ItemEnum(..) => EntryKind::Enum(get_repr_options(&tcx, def_id)),
hir::ItemStruct(ref struct_def, _) => {
let variant = tcx.lookup_adt_def(def_id).struct_variant();
@ -671,20 +673,24 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
} else {
None
};
let repr_options = get_repr_options(&tcx, def_id);
EntryKind::Struct(self.lazy(&VariantData {
ctor_kind: variant.ctor_kind,
disr: variant.disr_val.to_u128_unchecked(),
struct_ctor: struct_ctor,
}))
}), repr_options)
}
hir::ItemUnion(..) => {
let variant = tcx.lookup_adt_def(def_id).struct_variant();
let repr_options = get_repr_options(&tcx, def_id);
EntryKind::Union(self.lazy(&VariantData {
ctor_kind: variant.ctor_kind,
disr: variant.disr_val.to_u128_unchecked(),
struct_ctor: None,
}))
}), repr_options)
}
hir::ItemDefaultImpl(..) => {
let data = ImplData {
@ -1419,3 +1425,11 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
result
}
pub fn get_repr_options<'a, 'tcx, 'gcx>(tcx: &TyCtxt<'a, 'tcx, 'gcx>, did: DefId) -> ReprOptions {
let ty = tcx.item_type(did);
match ty.sty {
ty::TyAdt(ref def, _) => return def.repr,
_ => bug!("{} is not an ADT", ty),
}
}

View File

@ -18,7 +18,7 @@ use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary};
use rustc::middle::lang_items;
use rustc::middle::resolve_lifetime::ObjectLifetimeDefault;
use rustc::mir;
use rustc::ty::{self, Ty};
use rustc::ty::{self, Ty, ReprOptions};
use rustc_back::PanicStrategy;
use rustc_serialize as serialize;
@ -228,11 +228,11 @@ pub enum EntryKind<'tcx> {
ForeignMutStatic,
ForeignMod,
Type,
Enum,
Enum(ReprOptions),
Field,
Variant(Lazy<VariantData>),
Struct(Lazy<VariantData>),
Union(Lazy<VariantData>),
Struct(Lazy<VariantData>, ReprOptions),
Union(Lazy<VariantData>, ReprOptions),
Fn(Lazy<FnData>),
ForeignFn(Lazy<FnData>),
Mod(Lazy<ModData>),

View File

@ -65,7 +65,7 @@ use middle::const_val::ConstVal;
use rustc_const_eval::EvalHint::UncheckedExprHint;
use rustc_const_eval::{ConstContext, report_const_eval_err};
use rustc::ty::subst::Substs;
use rustc::ty::{ToPredicate, ImplContainer, AssociatedItemContainer, TraitContainer};
use rustc::ty::{ToPredicate, ImplContainer, AssociatedItemContainer, TraitContainer, ReprOptions};
use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
use rustc::ty::util::IntTypeExt;
use rustc::dep_graph::DepNode;
@ -1006,7 +1006,8 @@ fn convert_struct_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
let ctor_id = if !def.is_struct() { Some(ccx.tcx.hir.local_def_id(def.id())) } else { None };
let variants = vec![convert_struct_variant(ccx, ctor_id.unwrap_or(did), it.name,
ConstInt::Infer(0), def)];
let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Struct, variants);
let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Struct, variants,
ReprOptions::new(&ccx.tcx, did));
if let Some(ctor_id) = ctor_id {
// Make adt definition available through constructor id as well.
ccx.tcx.adt_defs.borrow_mut().insert(ctor_id, adt);
@ -1024,7 +1025,7 @@ fn convert_union_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
let did = ccx.tcx.hir.local_def_id(it.id);
let variants = vec![convert_struct_variant(ccx, did, it.name, ConstInt::Infer(0), def)];
let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Union, variants);
let adt = ccx.tcx.alloc_adt_def(did, AdtKind::Union, variants, ReprOptions::new(&ccx.tcx, did));
ccx.tcx.adt_defs.borrow_mut().insert(did, adt);
adt
}
@ -1112,7 +1113,7 @@ fn convert_enum_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
convert_struct_variant(ccx, did, v.node.name, disr, &v.node.data)
}).collect();
let adt = tcx.alloc_adt_def(did, AdtKind::Enum, variants);
let adt = tcx.alloc_adt_def(did, AdtKind::Enum, variants, ReprOptions::new(&ccx.tcx, did));
tcx.adt_defs.borrow_mut().insert(did, adt);
adt
}

View File

@ -0,0 +1,22 @@
// Copyright 2017 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.
enum X {
Y
}
struct Z {
x: X
}
fn main() {
let z = Z { x: X::Y };
let _ = &mut z.x;
}

View File

@ -0,0 +1,8 @@
error: cannot borrow immutable field `z.x` as mutable
--> $DIR/issue-39544.rs:21:18
|
21 | let _ = &mut z.x;
| ^^^
error: aborting due to previous error

View File

@ -78,6 +78,7 @@ static TARGETS: &'static [&'static str] = &[
"powerpc64-unknown-linux-gnu",
"powerpc64le-unknown-linux-gnu",
"s390x-unknown-linux-gnu",
"sparc64-unknown-linux-gnu",
"wasm32-unknown-emscripten",
"x86_64-apple-darwin",
"x86_64-apple-ios",