From 235741f1506275eb642dc6876d29f35e4d59f761 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-S=C3=A9bastien=20P=C3=A9dron?= Date: Mon, 6 Feb 2017 23:50:06 +0100 Subject: [PATCH 1/7] liblibc: Update to include aarch64-unknown-freebsd support --- src/liblibc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liblibc b/src/liblibc index cb7f66732175e..8d8264b967a31 160000 --- a/src/liblibc +++ b/src/liblibc @@ -1 +1 @@ -Subproject commit cb7f66732175e6171587ed69656b7aae7dd2e6ec +Subproject commit 8d8264b967a31a1a8cebe2a05110564106b6e909 From df73bc9c9d550c2517edc3cf49164d9e93c5b152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 6 Feb 2017 15:41:28 -0800 Subject: [PATCH 2/7] Fix ICE when accessing mutably an immutable enum --- src/librustc/middle/mem_categorization.rs | 4 +++- src/test/ui/did_you_mean/issue-39544.rs | 22 +++++++++++++++++++++ src/test/ui/did_you_mean/issue-39544.stderr | 8 ++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/did_you_mean/issue-39544.rs create mode 100644 src/test/ui/did_you_mean/issue-39544.stderr diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 9d1bcb8164a9e..627753039bae3 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -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 { diff --git a/src/test/ui/did_you_mean/issue-39544.rs b/src/test/ui/did_you_mean/issue-39544.rs new file mode 100644 index 0000000000000..bcdafefa2472b --- /dev/null +++ b/src/test/ui/did_you_mean/issue-39544.rs @@ -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 or the MIT license +// , 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; +} diff --git a/src/test/ui/did_you_mean/issue-39544.stderr b/src/test/ui/did_you_mean/issue-39544.stderr new file mode 100644 index 0000000000000..c0088f39ad3e1 --- /dev/null +++ b/src/test/ui/did_you_mean/issue-39544.stderr @@ -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 + From 541aa8a27039b196df626193886f39373dd09b0b Mon Sep 17 00:00:00 2001 From: Austin Hicks Date: Mon, 6 Feb 2017 15:26:32 -0500 Subject: [PATCH 3/7] Introduce ReprOptions, a struct for holding info from the repr attributes. This effectively deprecates lookup_repr_hints. --- src/librustc/ty/context.rs | 6 ++++-- src/librustc/ty/mod.rs | 33 ++++++++++++++++++++++++++++++-- src/librustc_metadata/decoder.rs | 28 +++++++++++++-------------- src/librustc_metadata/encoder.rs | 24 ++++++++++++++++++----- src/librustc_metadata/schema.rs | 8 ++++---- src/librustc_typeck/collect.rs | 9 +++++---- 6 files changed, 77 insertions(+), 31 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index a0eae33c4402b..6203679a51058 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -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) + variants: Vec, + 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) } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 4d9514b1473c7..beb286108a034 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1327,7 +1327,8 @@ pub struct AdtDef { pub did: DefId, pub variants: Vec, destructor: Cell>, - flags: Cell + flags: Cell, + 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, +} + +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) -> Self { + variants: Vec, + 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, } } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index f4a35ea5fd0cf..bb99be20f64d3 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -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) { 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 { 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, diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 69e1bbd77662b..f4ff5f4626f35 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -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), + } +} diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index d13628e9ce7a3..10aa4784aa2e1 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -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), - Struct(Lazy), - Union(Lazy), + Struct(Lazy, ReprOptions), + Union(Lazy, ReprOptions), Fn(Lazy), ForeignFn(Lazy), Mod(Lazy), diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 1981e7c3a3d12..7936db65c44ac 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -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 } From 2ba0b65c27724b99f2624c4245698e8ef36a2cf2 Mon Sep 17 00:00:00 2001 From: Son Date: Tue, 7 Feb 2017 20:58:34 +1100 Subject: [PATCH 4/7] Improve fmt float * Move to a separate float mod * Add more tests for f64 f32 lower exp upper exp * Use assert_eq for a clearer error message --- src/libcore/fmt/float.rs | 94 ++++++++++++++++++++++++++++++++++++ src/libcore/fmt/mod.rs | 87 ++------------------------------- src/libcoretest/fmt/float.rs | 32 +++++++++--- 3 files changed, 123 insertions(+), 90 deletions(-) create mode 100644 src/libcore/fmt/float.rs diff --git a/src/libcore/fmt/float.rs b/src/libcore/fmt/float.rs new file mode 100644 index 0000000000000..50248fabfcd45 --- /dev/null +++ b/src/libcore/fmt/float.rs @@ -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 or the MIT license +// , 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(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(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 } diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index a989f914db616..eb086c201812a 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -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(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(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")] diff --git a/src/libcoretest/fmt/float.rs b/src/libcoretest/fmt/float.rs index 16cd2feddc0b8..695001312e4d5 100644 --- a/src/libcoretest/fmt/float.rs +++ b/src/libcoretest/fmt/float.rs @@ -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)); } From c3b64cf702552d7d7a68c8b2b4b6290b19b40f73 Mon Sep 17 00:00:00 2001 From: Austin Hicks Date: Tue, 7 Feb 2017 12:35:06 -0500 Subject: [PATCH 5/7] Refactor layout to use the new ReprOptions --- src/librustc/ty/layout.rs | 102 +++++++++++++++----------------------- 1 file changed, 39 insertions(+), 63 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index ff3ac3586a787..3a463e981a627 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -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> { - 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::, _>>()?, - &[], + &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::, _>>()?, - &[], 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::>() }).collect::>(); - 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::, _>>()?, - &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. From 8bb4718200e3603c6dd704868fa061d4e7c96767 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Wed, 8 Feb 2017 10:31:19 -0500 Subject: [PATCH 6/7] build std for sparc64-unknown-linux-gnu --- src/ci/docker/cross/Dockerfile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ci/docker/cross/Dockerfile b/src/ci/docker/cross/Dockerfile index 8f947caf2cbf5..29a5e7bcafb7a 100644 --- a/src/ci/docker/cross/Dockerfile +++ b/src/ci/docker/cross/Dockerfile @@ -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 From 499717820d129355bdc3d1b832e0d3e382b6021c Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Wed, 8 Feb 2017 11:50:27 -0500 Subject: [PATCH 7/7] build-manifest: update TARGETS --- src/tools/build-manifest/src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 8c15a6630a33c..f50205d457405 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -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",