From 730f7366bba5abdf5ae0c2f1222795e40d48f90c Mon Sep 17 00:00:00 2001 From: Benjamin Saunders Date: Fri, 22 May 2020 20:49:20 -0700 Subject: [PATCH 01/34] Fix asinh of negative values When `x` has large magnitude, `x + ((x * x) + 1.0).sqrt()` approaches `x + x.abs()`. For negative values of `x`, this leads to catastrophic cancellation, resulting in large errors or even 0 being passed to `ln`, producing incorrect results including `-inf`. Becuase asinh is an odd function, i.e. -asinh(x) = asinh(-x) for all x, we can avoid the catastrophic cancellation and obtain correct results by taking the absolute value of `self` for the first term. `self * self` is always positive, so in effect this gives us `x.abs().asinh().copysign(x)` which as discussed above is algebraically equivalent, but is much more accurate. --- src/libstd/f32.rs | 4 +++- src/libstd/f64.rs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index 8e743ace99bfb..ab468f42b3bd0 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -835,7 +835,7 @@ impl f32 { if self == Self::NEG_INFINITY { Self::NEG_INFINITY } else { - (self + ((self * self) + 1.0).sqrt()).ln().copysign(self) + (self.abs() + ((self * self) + 1.0).sqrt()).ln().copysign(self) } } @@ -1414,6 +1414,8 @@ mod tests { assert!((-0.0f32).asinh().is_sign_negative()); // issue 63271 assert_approx_eq!(2.0f32.asinh(), 1.443635475178810342493276740273105f32); assert_approx_eq!((-2.0f32).asinh(), -1.443635475178810342493276740273105f32); + // regression test for the catastrophic cancellation fixed in 72486 + assert_approx_eq!((-3000.0f32).asinh(), -8.699514775987968673236893537700647f32); } #[test] diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index fe64d27b1efc8..c033198f021c2 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -837,7 +837,7 @@ impl f64 { if self == Self::NEG_INFINITY { Self::NEG_INFINITY } else { - (self + ((self * self) + 1.0).sqrt()).ln().copysign(self) + (self.abs() + ((self * self) + 1.0).sqrt()).ln().copysign(self) } } @@ -1443,6 +1443,8 @@ mod tests { // issue 63271 assert_approx_eq!(2.0f64.asinh(), 1.443635475178810342493276740273105f64); assert_approx_eq!((-2.0f64).asinh(), -1.443635475178810342493276740273105f64); + // regression test for the catastrophic cancellation fixed in 72486 + assert_approx_eq!((-67452098.07139316f64).asinh(), -18.72007542627454439398548429400083); } #[test] From f7d745f33d950c050e0a5a2ee2ee9f0e1269e956 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 23 May 2020 13:22:45 +0200 Subject: [PATCH 02/34] tag/niche terminology cleanup --- .../debuginfo/metadata.rs | 105 +++++++++--------- src/librustc_codegen_ssa/mir/place.rs | 44 ++++---- src/librustc_lint/types.rs | 14 +-- src/librustc_middle/ty/layout.rs | 58 +++++----- src/librustc_mir/interpret/operand.rs | 27 ++--- src/librustc_mir/interpret/place.rs | 41 +++---- src/librustc_mir/interpret/step.rs | 4 +- src/librustc_mir/interpret/validity.rs | 4 +- src/librustc_target/abi/mod.rs | 27 +++-- src/test/ui/layout/debug.stderr | 12 +- 10 files changed, 167 insertions(+), 169 deletions(-) diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 0cce0b25e5893..01f630a31a18b 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -1,4 +1,4 @@ -use self::EnumDiscriminantInfo::*; +use self::EnumTagInfo::*; use self::MemberDescriptionFactory::*; use self::RecursiveTypeDescription::*; @@ -40,7 +40,7 @@ use rustc_middle::{bug, span_bug}; use rustc_session::config::{self, DebugInfo}; use rustc_span::symbol::{Interner, Symbol}; use rustc_span::{self, SourceFile, SourceFileHash, Span}; -use rustc_target::abi::{Abi, Align, DiscriminantKind, HasDataLayout, Integer, LayoutOf}; +use rustc_target::abi::{Abi, Align, HasDataLayout, Integer, LayoutOf, TagEncoding}; use rustc_target::abi::{Int, Pointer, F32, F64}; use rustc_target::abi::{Primitive, Size, VariantIdx, Variants}; @@ -1335,7 +1335,7 @@ fn generator_layout_and_saved_local_names( struct EnumMemberDescriptionFactory<'ll, 'tcx> { enum_type: Ty<'tcx>, layout: TyAndLayout<'tcx>, - discriminant_type_metadata: Option<&'ll DIType>, + tag_type_metadata: Option<&'ll DIType>, containing_scope: &'ll DIScope, span: Span, } @@ -1385,7 +1385,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { cx, self.layout, variant_info, - NoDiscriminant, + NoTag, self_metadata, self.span, ); @@ -1409,19 +1409,19 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { }] } Variants::Multiple { - discr_kind: DiscriminantKind::Tag, - discr_index, + tag_encoding: TagEncoding::Direct, + tag_field, ref variants, .. } => { - let discriminant_info = if fallback { - RegularDiscriminant { - discr_field: Field::from(discr_index), - discr_type_metadata: self.discriminant_type_metadata.unwrap(), + let tag_info = if fallback { + RegularTag { + tag_field: Field::from(tag_field), + tag_type_metadata: self.tag_type_metadata.unwrap(), } } else { // This doesn't matter in this case. - NoDiscriminant + NoTag }; variants .iter_enumerated() @@ -1432,7 +1432,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { cx, variant, variant_info, - discriminant_info, + tag_info, self_metadata, self.span, ); @@ -1467,11 +1467,11 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { .collect() } Variants::Multiple { - discr_kind: - DiscriminantKind::Niche { ref niche_variants, niche_start, dataful_variant }, - ref discr, + tag_encoding: + TagEncoding::Niche { ref niche_variants, niche_start, dataful_variant }, + ref tag, ref variants, - discr_index, + tag_field, } => { if fallback { let variant = self.layout.for_variant(cx, dataful_variant); @@ -1480,7 +1480,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { cx, variant, variant_info_for(dataful_variant), - OptimizedDiscriminant, + OptimizedTag, self.containing_scope, self.span, ); @@ -1524,8 +1524,8 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { cx, &mut name, self.layout, - self.layout.fields.offset(discr_index), - self.layout.field(cx, discr_index).size, + self.layout.fields.offset(tag_field), + self.layout.field(cx, tag_field).size, ); variant_info_for(*niche_variants.start()).map_struct_name(|variant_name| { name.push_str(variant_name); @@ -1552,7 +1552,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { cx, variant, variant_info, - OptimizedDiscriminant, + OptimizedTag, self_metadata, self.span, ); @@ -1573,7 +1573,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { let value = (i.as_u32() as u128) .wrapping_sub(niche_variants.start().as_u32() as u128) .wrapping_add(niche_start); - let value = truncate(value, discr.value.size(cx)); + let value = truncate(value, tag.value.size(cx)); // NOTE(eddyb) do *NOT* remove this assert, until // we pass the full 128-bit value to LLVM, otherwise // truncation will be silent and remain undetected. @@ -1603,7 +1603,7 @@ struct VariantMemberDescriptionFactory<'ll, 'tcx> { /// Cloned from the `layout::Struct` describing the variant. offsets: Vec, args: Vec<(String, Ty<'tcx>)>, - discriminant_type_metadata: Option<&'ll DIType>, + tag_type_metadata: Option<&'ll DIType>, span: Span, } @@ -1617,7 +1617,7 @@ impl VariantMemberDescriptionFactory<'ll, 'tcx> { MemberDescription { name: name.to_string(), type_metadata: if use_enum_fallback(cx) { - match self.discriminant_type_metadata { + match self.tag_type_metadata { // Discriminant is always the first field of our variant // when using the enum fallback. Some(metadata) if i == 0 => metadata, @@ -1638,10 +1638,10 @@ impl VariantMemberDescriptionFactory<'ll, 'tcx> { } #[derive(Copy, Clone)] -enum EnumDiscriminantInfo<'ll> { - RegularDiscriminant { discr_field: Field, discr_type_metadata: &'ll DIType }, - OptimizedDiscriminant, - NoDiscriminant, +enum EnumTagInfo<'ll> { + RegularTag { tag_field: Field, tag_type_metadata: &'ll DIType }, + OptimizedTag, + NoTag, } #[derive(Copy, Clone)] @@ -1706,7 +1706,7 @@ fn describe_enum_variant( cx: &CodegenCx<'ll, 'tcx>, layout: layout::TyAndLayout<'tcx>, variant: VariantInfo<'_, 'tcx>, - discriminant_info: EnumDiscriminantInfo<'ll>, + discriminant_info: EnumTagInfo<'ll>, containing_scope: &'ll DIScope, span: Span, ) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) { @@ -1722,12 +1722,12 @@ fn describe_enum_variant( let (offsets, args) = if use_enum_fallback(cx) { // If this is not a univariant enum, there is also the discriminant field. let (discr_offset, discr_arg) = match discriminant_info { - RegularDiscriminant { discr_field, .. } => { + RegularTag { tag_field, .. } => { // We have the layout of an enum variant, we need the layout of the outer enum let enum_layout = cx.layout_of(layout.ty); - let offset = enum_layout.fields.offset(discr_field.as_usize()); + let offset = enum_layout.fields.offset(tag_field.as_usize()); let args = - ("RUST$ENUM$DISR".to_owned(), enum_layout.field(cx, discr_field.as_usize()).ty); + ("RUST$ENUM$DISR".to_owned(), enum_layout.field(cx, tag_field.as_usize()).ty); (Some(offset), Some(args)) } _ => (None, None), @@ -1757,8 +1757,8 @@ fn describe_enum_variant( let member_description_factory = VariantMDF(VariantMemberDescriptionFactory { offsets, args, - discriminant_type_metadata: match discriminant_info { - RegularDiscriminant { discr_type_metadata, .. } => Some(discr_type_metadata), + tag_type_metadata: match discriminant_info { + RegularTag { tag_type_metadata, .. } => Some(tag_type_metadata), _ => None, }, span, @@ -1880,18 +1880,18 @@ fn prepare_enum_metadata( if let ( &Abi::Scalar(_), - &Variants::Multiple { discr_kind: DiscriminantKind::Tag, ref discr, .. }, + &Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. }, ) = (&layout.abi, &layout.variants) { - return FinalMetadata(discriminant_type_metadata(discr.value)); + return FinalMetadata(discriminant_type_metadata(tag.value)); } if use_enum_fallback(cx) { let discriminant_type_metadata = match layout.variants { Variants::Single { .. } - | Variants::Multiple { discr_kind: DiscriminantKind::Niche { .. }, .. } => None, - Variants::Multiple { discr_kind: DiscriminantKind::Tag, ref discr, .. } => { - Some(discriminant_type_metadata(discr.value)) + | Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => None, + Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. } => { + Some(discriminant_type_metadata(tag.value)) } }; @@ -1927,7 +1927,7 @@ fn prepare_enum_metadata( EnumMDF(EnumMemberDescriptionFactory { enum_type, layout, - discriminant_type_metadata, + tag_type_metadata: discriminant_type_metadata, containing_scope, span, }), @@ -1943,16 +1943,13 @@ fn prepare_enum_metadata( Variants::Single { .. } => None, Variants::Multiple { - discr_kind: DiscriminantKind::Niche { .. }, - ref discr, - discr_index, - .. + tag_encoding: TagEncoding::Niche { .. }, ref tag, tag_field, .. } => { // Find the integer type of the correct size. - let size = discr.value.size(cx); - let align = discr.value.align(cx); + let size = tag.value.size(cx); + let align = tag.value.align(cx); - let discr_type = match discr.value { + let tag_type = match tag.value { Int(t, _) => t, F32 => Integer::I32, F64 => Integer::I64, @@ -1960,7 +1957,7 @@ fn prepare_enum_metadata( } .to_ty(cx.tcx, false); - let discr_metadata = basic_type_metadata(cx, discr_type); + let tag_metadata = basic_type_metadata(cx, tag_type); unsafe { Some(llvm::LLVMRustDIBuilderCreateMemberType( DIB(cx), @@ -1971,17 +1968,15 @@ fn prepare_enum_metadata( UNKNOWN_LINE_NUMBER, size.bits(), align.abi.bits() as u32, - layout.fields.offset(discr_index).bits(), + layout.fields.offset(tag_field).bits(), DIFlags::FlagArtificial, - discr_metadata, + tag_metadata, )) } } - Variants::Multiple { - discr_kind: DiscriminantKind::Tag, ref discr, discr_index, .. - } => { - let discr_type = discr.value.to_ty(cx.tcx); + Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, tag_field, .. } => { + let discr_type = tag.value.to_ty(cx.tcx); let (size, align) = cx.size_and_align_of(discr_type); let discr_metadata = basic_type_metadata(cx, discr_type); @@ -1995,7 +1990,7 @@ fn prepare_enum_metadata( UNKNOWN_LINE_NUMBER, size.bits(), align.bits() as u32, - layout.fields.offset(discr_index).bits(), + layout.fields.offset(tag_field).bits(), DIFlags::FlagArtificial, discr_metadata, )) @@ -2081,7 +2076,7 @@ fn prepare_enum_metadata( EnumMDF(EnumMemberDescriptionFactory { enum_type, layout, - discriminant_type_metadata: None, + tag_type_metadata: None, containing_scope, span, }), diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 2be0679382900..0c8638b673d4f 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -10,7 +10,7 @@ use rustc_middle::mir; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout}; use rustc_middle::ty::{self, Ty}; -use rustc_target::abi::{Abi, Align, DiscriminantKind, FieldsShape, Int}; +use rustc_target::abi::{Abi, Align, FieldsShape, Int, TagEncoding}; use rustc_target::abi::{LayoutOf, VariantIdx, Variants}; #[derive(Copy, Clone, Debug)] @@ -199,7 +199,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { if self.layout.abi.is_uninhabited() { return bx.cx().const_undef(cast_to); } - let (discr_scalar, discr_kind, discr_index) = match self.layout.variants { + let (tag_scalar, tag_encoding, tag_field) = match self.layout.variants { Variants::Single { index } => { let discr_val = self .layout @@ -208,33 +208,33 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { .map_or(index.as_u32() as u128, |discr| discr.val); return bx.cx().const_uint_big(cast_to, discr_val); } - Variants::Multiple { ref discr, ref discr_kind, discr_index, .. } => { - (discr, discr_kind, discr_index) + Variants::Multiple { ref tag, ref tag_encoding, tag_field, .. } => { + (tag, tag_encoding, tag_field) } }; // Read the tag/niche-encoded discriminant from memory. - let encoded_discr = self.project_field(bx, discr_index); - let encoded_discr = bx.load_operand(encoded_discr); + let tag = self.project_field(bx, tag_field); + let tag = bx.load_operand(tag); // Decode the discriminant (specifically if it's niche-encoded). - match *discr_kind { - DiscriminantKind::Tag => { - let signed = match discr_scalar.value { + match *tag_encoding { + TagEncoding::Direct => { + let signed = match tag_scalar.value { // We use `i1` for bytes that are always `0` or `1`, // e.g., `#[repr(i8)] enum E { A, B }`, but we can't // let LLVM interpret the `i1` as signed, because // then `i1 1` (i.e., `E::B`) is effectively `i8 -1`. - Int(_, signed) => !discr_scalar.is_bool() && signed, + Int(_, signed) => !tag_scalar.is_bool() && signed, _ => false, }; - bx.intcast(encoded_discr.immediate(), cast_to, signed) + bx.intcast(tag.immediate(), cast_to, signed) } - DiscriminantKind::Niche { dataful_variant, ref niche_variants, niche_start } => { + TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start } => { // Rebase from niche values to discriminants, and check // whether the result is in range for the niche variants. - let niche_llty = bx.cx().immediate_backend_type(encoded_discr.layout); - let encoded_discr = encoded_discr.immediate(); + let niche_llty = bx.cx().immediate_backend_type(tag.layout); + let tag = tag.immediate(); // We first compute the "relative discriminant" (wrt `niche_variants`), // that is, if `n = niche_variants.end() - niche_variants.start()`, @@ -248,9 +248,9 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { let relative_discr = if niche_start == 0 { // Avoid subtracting `0`, which wouldn't work for pointers. // FIXME(eddyb) check the actual primitive type here. - encoded_discr + tag } else { - bx.sub(encoded_discr, bx.cx().const_uint_big(niche_llty, niche_start)) + bx.sub(tag, bx.cx().const_uint_big(niche_llty, niche_start)) }; let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32(); let is_niche = { @@ -312,8 +312,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { Variants::Single { index } => { assert_eq!(index, variant_index); } - Variants::Multiple { discr_kind: DiscriminantKind::Tag, discr_index, .. } => { - let ptr = self.project_field(bx, discr_index); + Variants::Multiple { tag_encoding: TagEncoding::Direct, tag_field, .. } => { + let ptr = self.project_field(bx, tag_field); let to = self.layout.ty.discriminant_for_variant(bx.tcx(), variant_index).unwrap().val; bx.store( @@ -323,9 +323,9 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { ); } Variants::Multiple { - discr_kind: - DiscriminantKind::Niche { dataful_variant, ref niche_variants, niche_start }, - discr_index, + tag_encoding: + TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start }, + tag_field, .. } => { if variant_index != dataful_variant { @@ -339,7 +339,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { bx.memset(self.llval, fill_byte, size, self.align, MemFlags::empty()); } - let niche = self.project_field(bx, discr_index); + let niche = self.project_field(bx, tag_field); let niche_llty = bx.cx().immediate_backend_type(niche.layout); let niche_value = variant_index.as_u32() - niche_variants.start().as_u32(); let niche_value = (niche_value as u128).wrapping_add(niche_start); diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 703c2a7a443a9..6f4e2c69e339f 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -16,7 +16,7 @@ use rustc_middle::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; use rustc_span::source_map; use rustc_span::symbol::sym; use rustc_span::Span; -use rustc_target::abi::{DiscriminantKind, Integer, LayoutOf, VariantIdx, Variants}; +use rustc_target::abi::{Integer, LayoutOf, TagEncoding, VariantIdx, Variants}; use rustc_target::spec::abi::Abi; use log::debug; @@ -1036,15 +1036,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences { }; let (variants, tag) = match layout.variants { Variants::Multiple { - discr_kind: DiscriminantKind::Tag, - ref discr, + tag_encoding: TagEncoding::Direct, + ref tag, ref variants, .. - } => (variants, discr), + } => (variants, tag), _ => return, }; - let discr_size = tag.value.size(&cx.tcx).bytes(); + let tag_size = tag.value.size(&cx.tcx).bytes(); debug!( "enum `{}` is {} bytes large with layout:\n{:#?}", @@ -1058,8 +1058,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences { .iter() .zip(variants) .map(|(variant, variant_layout)| { - // Subtract the size of the enum discriminant. - let bytes = variant_layout.size.bytes().saturating_sub(discr_size); + // Subtract the size of the enum tag. + let bytes = variant_layout.size.bytes().saturating_sub(tag_size); debug!("- variant `{}` is {} bytes large", variant.ident, bytes); bytes diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs index 5566e187c0c5c..fde2627e29dcb 100644 --- a/src/librustc_middle/ty/layout.rs +++ b/src/librustc_middle/ty/layout.rs @@ -975,13 +975,13 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { return Ok(tcx.intern_layout(Layout { variants: Variants::Multiple { - discr: niche_scalar, - discr_kind: DiscriminantKind::Niche { + tag: niche_scalar, + tag_encoding: TagEncoding::Niche { dataful_variant: i, niche_variants, niche_start, }, - discr_index: 0, + tag_field: 0, variants: st, }, fields: FieldsShape::Arbitrary { @@ -1217,9 +1217,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { tcx.intern_layout(Layout { variants: Variants::Multiple { - discr: tag, - discr_kind: DiscriminantKind::Tag, - discr_index: 0, + tag, + tag_encoding: TagEncoding::Direct, + tag_field: 0, variants: layout_variants, }, fields: FieldsShape::Arbitrary { @@ -1400,15 +1400,15 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // Build a prefix layout, including "promoting" all ineligible // locals as part of the prefix. We compute the layout of all of // these fields at once to get optimal packing. - let discr_index = substs.as_generator().prefix_tys().count(); + let tag_index = substs.as_generator().prefix_tys().count(); // `info.variant_fields` already accounts for the reserved variants, so no need to add them. let max_discr = (info.variant_fields.len() - 1) as u128; let discr_int = Integer::fit_unsigned(max_discr); let discr_int_ty = discr_int.to_ty(tcx, false); - let discr = Scalar { value: Primitive::Int(discr_int, false), valid_range: 0..=max_discr }; - let discr_layout = self.tcx.intern_layout(Layout::scalar(self, discr.clone())); - let discr_layout = TyAndLayout { ty: discr_int_ty, layout: discr_layout }; + let tag = Scalar { value: Primitive::Int(discr_int, false), valid_range: 0..=max_discr }; + let tag_layout = self.tcx.intern_layout(Layout::scalar(self, tag.clone())); + let tag_layout = TyAndLayout { ty: discr_int_ty, layout: tag_layout }; let promoted_layouts = ineligible_locals .iter() @@ -1419,7 +1419,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { .as_generator() .prefix_tys() .map(|ty| self.layout_of(ty)) - .chain(iter::once(Ok(discr_layout))) + .chain(iter::once(Ok(tag_layout))) .chain(promoted_layouts) .collect::, _>>()?; let prefix = self.univariant_uninterned( @@ -1442,7 +1442,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // "a" (`0..b_start`) and "b" (`b_start..`) correspond to // "outer" and "promoted" fields respectively. - let b_start = (discr_index + 1) as u32; + let b_start = (tag_index + 1) as u32; let offsets_b = offsets.split_off(b_start as usize); let offsets_a = offsets; @@ -1559,9 +1559,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let layout = tcx.intern_layout(Layout { variants: Variants::Multiple { - discr, - discr_kind: DiscriminantKind::Tag, - discr_index, + tag: tag, + tag_encoding: TagEncoding::Direct, + tag_field: tag_index, variants, }, fields: outer_fields, @@ -1681,7 +1681,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } } - Variants::Multiple { ref discr, ref discr_kind, .. } => { + Variants::Multiple { ref tag, ref tag_encoding, .. } => { debug!( "print-type-size `{:#?}` adt general variants def {}", layout.ty, @@ -1703,8 +1703,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { record( adt_kind.into(), adt_packed, - match discr_kind { - DiscriminantKind::Tag => Some(discr.value.size(self)), + match tag_encoding { + TagEncoding::Direct => Some(tag.value.size(self)), _ => None, }, variant_infos, @@ -2029,11 +2029,11 @@ where fn field(this: TyAndLayout<'tcx>, cx: &C, i: usize) -> C::TyAndLayout { let tcx = cx.tcx(); - let discr_layout = |discr: &Scalar| -> C::TyAndLayout { - let layout = Layout::scalar(cx, discr.clone()); + let tag_layout = |tag: &Scalar| -> C::TyAndLayout { + let layout = Layout::scalar(cx, tag.clone()); MaybeResult::from(Ok(TyAndLayout { layout: tcx.intern_layout(layout), - ty: discr.value.to_ty(tcx), + ty: tag.value.to_ty(tcx), })) }; @@ -2110,9 +2110,9 @@ where .unwrap() .nth(i) .unwrap(), - Variants::Multiple { ref discr, discr_index, .. } => { - if i == discr_index { - return discr_layout(discr); + Variants::Multiple { ref tag, tag_field, .. } => { + if i == tag_field { + return tag_layout(tag); } substs.as_generator().prefix_tys().nth(i).unwrap() } @@ -2129,9 +2129,9 @@ where Variants::Single { index } => def.variants[index].fields[i].ty(tcx, substs), // Discriminant field for enums (where applicable). - Variants::Multiple { ref discr, .. } => { + Variants::Multiple { ref tag, .. } => { assert_eq!(i, 0); - return discr_layout(discr); + return tag_layout(tag); } } } @@ -2208,10 +2208,10 @@ where // using more niches than just null (e.g., the first page of // the address space, or unaligned pointers). Variants::Multiple { - discr_kind: DiscriminantKind::Niche { dataful_variant, .. }, - discr_index, + tag_encoding: TagEncoding::Niche { dataful_variant, .. }, + tag_field, .. - } if this.fields.offset(discr_index) == offset => { + } if this.fields.offset(tag_field) == offset => { Some(this.for_variant(cx, dataful_variant)) } _ => Some(this), diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index db4473154c471..7da50eaa3e392 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -11,7 +11,7 @@ use rustc_middle::ty::layout::{PrimitiveExt, TyAndLayout}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Printer}; use rustc_middle::ty::Ty; use rustc_middle::{mir, ty}; -use rustc_target::abi::{Abi, DiscriminantKind, HasDataLayout, LayoutOf, Size}; +use rustc_target::abi::{Abi, TagEncoding, HasDataLayout, LayoutOf, Size}; use rustc_target::abi::{VariantIdx, Variants}; use super::{ @@ -587,7 +587,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { op: OpTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx, (Scalar, VariantIdx)> { trace!("read_discriminant_value {:#?}", op.layout); - // Get type and layout of the discriminant. let discr_layout = self.layout_of(op.layout.ty.discriminant_ty(*self.tcx))?; trace!("discriminant type: {:?}", discr_layout.ty); @@ -596,10 +595,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // This is not to be confused with its "variant index", which is just determining its position in the // declared list of variants -- they can differ with explicitly assigned discriminants. // We use "tag" to refer to how the discriminant is encoded in memory, which can be either - // straight-forward (`DiscriminantKind::Tag`) or with a niche (`DiscriminantKind::Niche`). - // Unfortunately, the rest of the compiler calls the latter "discriminant", too, which makes things - // rather confusing. - let (tag_scalar_layout, tag_kind, tag_index) = match op.layout.variants { + // straight-forward (`TagEncoding::Direct`) or with a niche (`TagEncoding::Niche`). + let (tag_scalar_layout, tag_encoding, tag_field) = match op.layout.variants { Variants::Single { index } => { let discr = match op.layout.ty.discriminant_for_variant(*self.tcx, index) { Some(discr) => { @@ -615,8 +612,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; return Ok((discr, index)); } - Variants::Multiple { ref discr, ref discr_kind, discr_index, .. } => { - (discr, discr_kind, discr_index) + Variants::Multiple { ref tag, ref tag_encoding, tag_field, .. } => { + (tag, tag_encoding, tag_field) } }; @@ -633,21 +630,21 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let tag_layout = self.layout_of(tag_scalar_layout.value.to_int_ty(*self.tcx))?; // Read tag and sanity-check `tag_layout`. - let tag_val = self.read_immediate(self.operand_field(op, tag_index)?)?; + let tag_val = self.read_immediate(self.operand_field(op, tag_field)?)?; assert_eq!(tag_layout.size, tag_val.layout.size); assert_eq!(tag_layout.abi.is_signed(), tag_val.layout.abi.is_signed()); let tag_val = tag_val.to_scalar()?; trace!("tag value: {:?}", tag_val); // Figure out which discriminant and variant this corresponds to. - Ok(match *tag_kind { - DiscriminantKind::Tag => { + Ok(match *tag_encoding { + TagEncoding::Direct => { let tag_bits = self .force_bits(tag_val, tag_layout.size) .map_err(|_| err_ub!(InvalidDiscriminant(tag_val.erase_tag())))?; // Cast bits from tag layout to discriminant layout. - let discr_val_cast = self.cast_from_scalar(tag_bits, tag_layout, discr_layout.ty); - let discr_bits = discr_val_cast.assert_bits(discr_layout.size); + let discr_val = self.cast_from_scalar(tag_bits, tag_layout, discr_layout.ty); + let discr_bits = discr_val.assert_bits(discr_layout.size); // Convert discriminant to variant index, and catch invalid discriminants. let index = match op.layout.ty.kind { ty::Adt(adt, _) => { @@ -663,9 +660,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } .ok_or_else(|| err_ub!(InvalidDiscriminant(tag_val.erase_tag())))?; // Return the cast value, and the index. - (discr_val_cast, index.0) + (discr_val, index.0) } - DiscriminantKind::Niche { dataful_variant, ref niche_variants, niche_start } => { + TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start } => { // Compute the variant this niche value/"tag" corresponds to. With niche layout, // discriminant (encoded in niche/tag) and variant index are the same. let variants_start = niche_variants.start().as_u32(); diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 3f0800b12b549..1e6335c871e7c 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -9,7 +9,7 @@ use rustc_macros::HashStable; use rustc_middle::mir; use rustc_middle::ty::layout::{PrimitiveExt, TyAndLayout}; use rustc_middle::ty::{self, Ty}; -use rustc_target::abi::{Abi, Align, DiscriminantKind, FieldsShape}; +use rustc_target::abi::{Abi, Align, FieldsShape, TagEncoding}; use rustc_target::abi::{HasDataLayout, LayoutOf, Size, VariantIdx, Variants}; use super::{ @@ -1031,7 +1031,8 @@ where MPlaceTy { mplace, layout } } - pub fn write_discriminant_index( + /// Writes the discriminant of the given variant. + pub fn write_discriminant( &mut self, variant_index: VariantIdx, dest: PlaceTy<'tcx, M::PointerTag>, @@ -1047,9 +1048,9 @@ where assert_eq!(index, variant_index); } Variants::Multiple { - discr_kind: DiscriminantKind::Tag, - discr: ref discr_layout, - discr_index, + tag_encoding: TagEncoding::Direct, + tag: ref tag_layout, + tag_field, .. } => { // No need to validate that the discriminant here because the @@ -1061,17 +1062,17 @@ where // raw discriminants for enums are isize or bigger during // their computation, but the in-memory tag is the smallest possible // representation - let size = discr_layout.value.size(self); - let discr_val = truncate(discr_val, size); + let size = tag_layout.value.size(self); + let tag_val = truncate(discr_val, size); - let discr_dest = self.place_field(dest, discr_index)?; - self.write_scalar(Scalar::from_uint(discr_val, size), discr_dest)?; + let tag_dest = self.place_field(dest, tag_field)?; + self.write_scalar(Scalar::from_uint(tag_val, size), tag_dest)?; } Variants::Multiple { - discr_kind: - DiscriminantKind::Niche { dataful_variant, ref niche_variants, niche_start }, - discr: ref discr_layout, - discr_index, + tag_encoding: + TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start }, + tag: ref tag_layout, + tag_field, .. } => { // No need to validate that the discriminant here because the @@ -1084,19 +1085,19 @@ where .checked_sub(variants_start) .expect("overflow computing relative variant idx"); // We need to use machine arithmetic when taking into account `niche_start`: - // discr_val = variant_index_relative + niche_start_val - let discr_layout = self.layout_of(discr_layout.value.to_int_ty(*self.tcx))?; - let niche_start_val = ImmTy::from_uint(niche_start, discr_layout); + // tag_val = variant_index_relative + niche_start_val + let tag_layout = self.layout_of(tag_layout.value.to_int_ty(*self.tcx))?; + let niche_start_val = ImmTy::from_uint(niche_start, tag_layout); let variant_index_relative_val = - ImmTy::from_uint(variant_index_relative, discr_layout); - let discr_val = self.binary_op( + ImmTy::from_uint(variant_index_relative, tag_layout); + let tag_val = self.binary_op( mir::BinOp::Add, variant_index_relative_val, niche_start_val, )?; // Write result. - let niche_dest = self.place_field(dest, discr_index)?; - self.write_immediate(*discr_val, niche_dest)?; + let niche_dest = self.place_field(dest, tag_field)?; + self.write_immediate(*tag_val, niche_dest)?; } } } diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index bd4df788057e2..029b83492d593 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -89,7 +89,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { SetDiscriminant { place, variant_index } => { let dest = self.eval_place(**place)?; - self.write_discriminant_index(*variant_index, dest)?; + self.write_discriminant(*variant_index, dest)?; } // Mark locals as alive @@ -174,7 +174,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Aggregate(ref kind, ref operands) => { let (dest, active_field_index) = match **kind { mir::AggregateKind::Adt(adt_def, variant_index, _, _, active_field_index) => { - self.write_discriminant_index(variant_index, dest)?; + self.write_discriminant(variant_index, dest)?; if adt_def.is_enum() { (self.place_downcast(dest, variant_index)?, active_field_index) } else { diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index e962dfb2b3e86..f21a96a979092 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -208,8 +208,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' fn aggregate_field_path_elem(&mut self, layout: TyAndLayout<'tcx>, field: usize) -> PathElem { // First, check if we are projecting to a variant. match layout.variants { - Variants::Multiple { discr_index, .. } => { - if discr_index == field { + Variants::Multiple { tag_field, .. } => { + if tag_field == field { return match layout.ty.kind { ty::Adt(def, ..) if def.is_enum() => PathElem::EnumTag, ty::Generator(..) => PathElem::GeneratorTag, diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index dcf181cb59f4a..c79e9bb289008 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -809,25 +809,30 @@ pub enum Variants { /// Single enum variants, structs/tuples, unions, and all non-ADTs. Single { index: VariantIdx }, - /// Enum-likes with more than one inhabited variant: for each case there is - /// a struct, and they all have space reserved for the discriminant. - /// For enums this is the sole field of the layout. + /// Enum-likes with more than one inhabited variant: each variant comes with + /// a *discriminant* (usually the same as the variant index but the user can + /// assign explicit discriminant values). That discriminant is encoded + /// as a *tag* on the machine. The layout of each variant is + /// a struct, and they all have space reserved for the tag. + /// For enums, the tag is the sole field of the layout. Multiple { - discr: Scalar, - discr_kind: DiscriminantKind, - discr_index: usize, + tag: Scalar, + tag_encoding: TagEncoding, + tag_field: usize, variants: IndexVec, }, } #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] -pub enum DiscriminantKind { - /// Integer tag holding the discriminant value itself. - Tag, +pub enum TagEncoding { + /// The tag directly stores the discriminant, but possibly with a smaller layout + /// (so converting the tag to the discriminant can require sign extension). + Direct, /// Niche (values invalid for a type) encoding the discriminant: - /// the variant `dataful_variant` contains a niche at an arbitrary - /// offset (field `discr_index` of the enum), which for a variant with + /// Discriminant and variant index coincide. + /// The variant `dataful_variant` contains a niche at an arbitrary + /// offset (field `tag_field` of the enum), which for a variant with /// discriminant `d` is set to /// `(d - niche_variants.start).wrapping_add(niche_start)`. /// diff --git a/src/test/ui/layout/debug.stderr b/src/test/ui/layout/debug.stderr index cd8ebdffb730b..1a371c6b17000 100644 --- a/src/test/ui/layout/debug.stderr +++ b/src/test/ui/layout/debug.stderr @@ -10,15 +10,15 @@ error: layout_of(E) = Layout { ], }, variants: Multiple { - discr: Scalar { + tag: Scalar { value: Int( I32, false, ), valid_range: 0..=0, }, - discr_kind: Tag, - discr_index: 0, + tag_encoding: Direct, + tag_field: 0, variants: [ Layout { fields: Arbitrary { @@ -202,15 +202,15 @@ error: layout_of(std::result::Result) = Layout { ], }, variants: Multiple { - discr: Scalar { + tag: Scalar { value: Int( I32, false, ), valid_range: 0..=1, }, - discr_kind: Tag, - discr_index: 0, + tag_encoding: Direct, + tag_field: 0, variants: [ Layout { fields: Arbitrary { From 7a6d03c2699787644b44f7bc3e8252d1508880b8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 30 May 2020 14:21:56 +0200 Subject: [PATCH 03/34] miri errors: rename InvalidDiscriminant -> InvalidTag --- src/librustc_middle/mir/interpret/error.rs | 6 +++--- src/librustc_mir/interpret/operand.rs | 8 ++++---- src/librustc_mir/interpret/validity.rs | 4 ++-- src/test/ui/consts/const-eval/double_check2.stderr | 2 +- src/test/ui/consts/const-eval/ub-enum.stderr | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/librustc_middle/mir/interpret/error.rs b/src/librustc_middle/mir/interpret/error.rs index fc588e049d7d8..6646aad6fc740 100644 --- a/src/librustc_middle/mir/interpret/error.rs +++ b/src/librustc_middle/mir/interpret/error.rs @@ -390,8 +390,8 @@ pub enum UndefinedBehaviorInfo<'tcx> { InvalidBool(u8), /// Using a non-character `u32` as character. InvalidChar(u32), - /// An enum discriminant was set to a value which was outside the range of valid values. - InvalidDiscriminant(Scalar), + /// The tag of an enum does not encode an actual discriminant. + InvalidTag(Scalar), /// Using a pointer-not-to-a-function as function pointer. InvalidFunctionPointer(Pointer), /// Using a string that is not valid UTF-8, @@ -463,7 +463,7 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> { InvalidChar(c) => { write!(f, "interpreting an invalid 32-bit value as a char: 0x{:08x}", c) } - InvalidDiscriminant(val) => write!(f, "enum value has invalid discriminant: {}", val), + InvalidTag(val) => write!(f, "enum value has invalid tag: {}", val), InvalidFunctionPointer(p) => { write!(f, "using {} as function pointer but it does not point to a function", p) } diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 7da50eaa3e392..fb08e83b76942 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -11,7 +11,7 @@ use rustc_middle::ty::layout::{PrimitiveExt, TyAndLayout}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Printer}; use rustc_middle::ty::Ty; use rustc_middle::{mir, ty}; -use rustc_target::abi::{Abi, TagEncoding, HasDataLayout, LayoutOf, Size}; +use rustc_target::abi::{Abi, HasDataLayout, LayoutOf, Size, TagEncoding}; use rustc_target::abi::{VariantIdx, Variants}; use super::{ @@ -641,7 +641,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { TagEncoding::Direct => { let tag_bits = self .force_bits(tag_val, tag_layout.size) - .map_err(|_| err_ub!(InvalidDiscriminant(tag_val.erase_tag())))?; + .map_err(|_| err_ub!(InvalidTag(tag_val.erase_tag())))?; // Cast bits from tag layout to discriminant layout. let discr_val = self.cast_from_scalar(tag_bits, tag_layout, discr_layout.ty); let discr_bits = discr_val.assert_bits(discr_layout.size); @@ -658,7 +658,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } _ => bug!("tagged layout for non-adt non-generator"), } - .ok_or_else(|| err_ub!(InvalidDiscriminant(tag_val.erase_tag())))?; + .ok_or_else(|| err_ub!(InvalidTag(tag_val.erase_tag())))?; // Return the cast value, and the index. (discr_val, index.0) } @@ -674,7 +674,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { && variants_start == variants_end && !self.memory.ptr_may_be_null(ptr); if !ptr_valid { - throw_ub!(InvalidDiscriminant(tag_val.erase_tag())) + throw_ub!(InvalidTag(tag_val.erase_tag())) } dataful_variant } diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index f21a96a979092..8dea811d8bcd4 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -696,8 +696,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> try_validation!( self.walk_value(op), self.path, - err_ub!(InvalidDiscriminant(val)) => - { "{}", val } expected { "a valid enum discriminant" }, + err_ub!(InvalidTag(val)) => + { "{}", val } expected { "a valid enum tag" }, err_unsup!(ReadPointerAsBytes) => { "a pointer" } expected { "plain (non-pointer) bytes" }, ); diff --git a/src/test/ui/consts/const-eval/double_check2.stderr b/src/test/ui/consts/const-eval/double_check2.stderr index 81fa5c0df13f6..93dd9a53ec99f 100644 --- a/src/test/ui/consts/const-eval/double_check2.stderr +++ b/src/test/ui/consts/const-eval/double_check2.stderr @@ -5,7 +5,7 @@ LL | / static FOO: (&Foo, &Bar) = unsafe {( LL | | Union { u8: &BAR }.foo, LL | | Union { u8: &BAR }.bar, LL | | )}; - | |___^ type validation failed: encountered 0x05 at .1., but expected a valid enum discriminant + | |___^ type validation failed: encountered 0x05 at .1., but expected a valid enum tag | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.stderr index d8dafac3e70a1..d40073fb18fb0 100644 --- a/src/test/ui/consts/const-eval/ub-enum.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:24:1 | LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x00000001, but expected a valid enum discriminant + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x00000001, but expected a valid enum tag | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -26,7 +26,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:42:1 | LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x00000000, but expected a valid enum discriminant + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x00000000, but expected a valid enum tag | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. From 20abc70e04eefa252e5a8bfe934cb54c51c1da37 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 3 Jun 2020 13:45:56 +0200 Subject: [PATCH 04/34] Don't intern memory in const prop. This isn't sound without validation. We don't want to report errors in case of failure to intern and validate, we just don't want to const prop. Interning and const prop is not built for this, let's not do it until we have a clearer picture on aggregate propagation. --- src/librustc_mir/interpret/intern.rs | 12 ++++++------ src/librustc_mir/transform/const_prop.rs | 12 ++++-------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index 02a7f24a1e351..4c1cf1b56ae66 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -294,7 +294,6 @@ pub enum InternKind { Static(hir::Mutability), Constant, Promoted, - ConstProp, } /// Intern `ret` and everything it references. @@ -315,9 +314,7 @@ pub fn intern_const_alloc_recursive>( let base_intern_mode = match intern_kind { InternKind::Static(mutbl) => InternMode::Static(mutbl), // FIXME: what about array lengths, array initializers? - InternKind::Constant | InternKind::ConstProp | InternKind::Promoted => { - InternMode::ConstBase - } + InternKind::Constant | InternKind::Promoted => InternMode::ConstBase, }; // Type based interning. @@ -359,7 +356,10 @@ pub fn intern_const_alloc_recursive>( Err(error) => { ecx.tcx.sess.delay_span_bug( ecx.tcx.span, - "error during interning should later cause validation failure", + &format!( + "error during interning should later cause validation failure: {}", + error + ), ); // Some errors shouldn't come up because creating them causes // an allocation, which we should avoid. When that happens, @@ -400,7 +400,7 @@ pub fn intern_const_alloc_recursive>( // immutability is so important. alloc.mutability = Mutability::Not; } - InternKind::Constant | InternKind::ConstProp => { + InternKind::Constant => { // If it's a constant, we should not have any "leftovers" as everything // is tracked by const-checking. // FIXME: downgrade this to a warning? It rejects some legitimate consts, diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 92000e6411354..97e5b8bc047f0 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -27,9 +27,9 @@ use rustc_trait_selection::traits; use crate::const_eval::error_to_const_error; use crate::interpret::{ - self, compile_time_machine, intern_const_alloc_recursive, AllocId, Allocation, Frame, ImmTy, - Immediate, InternKind, InterpCx, LocalState, LocalValue, Memory, MemoryKind, OpTy, - Operand as InterpOperand, PlaceTy, Pointer, ScalarMaybeUninit, StackPopCleanup, + self, compile_time_machine, AllocId, Allocation, Frame, ImmTy, Immediate, InterpCx, LocalState, + LocalValue, Memory, MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, Pointer, + ScalarMaybeUninit, StackPopCleanup, }; use crate::transform::{MirPass, MirSource}; @@ -707,11 +707,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { ScalarMaybeUninit::Scalar(l), ScalarMaybeUninit::Scalar(r), )) => l.is_bits() && r.is_bits(), - interpret::Operand::Indirect(_) if mir_opt_level >= 2 => { - let mplace = op.assert_mem_place(&self.ecx); - intern_const_alloc_recursive(&mut self.ecx, InternKind::ConstProp, mplace, false); - true - } + interpret::Operand::Indirect(_) if mir_opt_level >= 2 => true, _ => false, } } From 1e88f130a347f8b223031eafe75c0772ccfec00c Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Mon, 8 Jun 2020 08:14:45 -0400 Subject: [PATCH 05/34] Stop allowing `Indirect(..)` values to be propagated Closes #72679 Closes #72372 Closes #72285 --- src/librustc_mir/transform/const_prop.rs | 1 - src/test/mir-opt/const_prop/discriminant.rs | 5 ++ .../32bit/rustc.main.ConstProp.diff | 75 +++++++++---------- .../64bit/rustc.main.ConstProp.diff | 75 +++++++++---------- 4 files changed, 73 insertions(+), 83 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 97e5b8bc047f0..39548d8a535f7 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -707,7 +707,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { ScalarMaybeUninit::Scalar(l), ScalarMaybeUninit::Scalar(r), )) => l.is_bits() && r.is_bits(), - interpret::Operand::Indirect(_) if mir_opt_level >= 2 => true, _ => false, } } diff --git a/src/test/mir-opt/const_prop/discriminant.rs b/src/test/mir-opt/const_prop/discriminant.rs index 04541b94ad780..13e8eb3e44e1a 100644 --- a/src/test/mir-opt/const_prop/discriminant.rs +++ b/src/test/mir-opt/const_prop/discriminant.rs @@ -1,5 +1,10 @@ // compile-flags: -O +// FIXME(wesleywiser): Ideally, we could const-prop away all of this and just be left with +// `let x = 42` but that doesn't work because const-prop doesn't support `Operand::Indirect` +// and `InterpCx::eval_place()` always forces an allocation which creates the `Indirect`. +// Fixing either of those will allow us to const-prop this away. + // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR rustc.main.ConstProp.diff fn main() { diff --git a/src/test/mir-opt/const_prop/discriminant/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/discriminant/32bit/rustc.main.ConstProp.diff index 9979ea9549891..1c873f53f378a 100644 --- a/src/test/mir-opt/const_prop/discriminant/32bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/discriminant/32bit/rustc.main.ConstProp.diff @@ -2,100 +2,93 @@ + // MIR for `main` after ConstProp fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/discriminant.rs:5:11: 5:11 - let _1: i32; // in scope 0 at $DIR/discriminant.rs:6:9: 6:10 - let mut _2: i32; // in scope 0 at $DIR/discriminant.rs:6:13: 6:64 - let mut _3: std::option::Option; // in scope 0 at $DIR/discriminant.rs:6:34: 6:44 - let mut _4: isize; // in scope 0 at $DIR/discriminant.rs:6:21: 6:31 + let mut _0: (); // return place in scope 0 at $DIR/discriminant.rs:10:11: 10:11 + let _1: i32; // in scope 0 at $DIR/discriminant.rs:11:9: 11:10 + let mut _2: i32; // in scope 0 at $DIR/discriminant.rs:11:13: 11:64 + let mut _3: std::option::Option; // in scope 0 at $DIR/discriminant.rs:11:34: 11:44 + let mut _4: isize; // in scope 0 at $DIR/discriminant.rs:11:21: 11:31 scope 1 { - debug x => _1; // in scope 1 at $DIR/discriminant.rs:6:9: 6:10 + debug x => _1; // in scope 1 at $DIR/discriminant.rs:11:9: 11:10 } bb0: { - StorageLive(_1); // scope 0 at $DIR/discriminant.rs:6:9: 6:10 - StorageLive(_2); // scope 0 at $DIR/discriminant.rs:6:13: 6:64 - StorageLive(_3); // scope 0 at $DIR/discriminant.rs:6:34: 6:44 -- _3 = std::option::Option::::Some(const true); // scope 0 at $DIR/discriminant.rs:6:34: 6:44 -+ _3 = const std::option::Option::::Some(true); // scope 0 at $DIR/discriminant.rs:6:34: 6:44 + StorageLive(_1); // scope 0 at $DIR/discriminant.rs:11:9: 11:10 + StorageLive(_2); // scope 0 at $DIR/discriminant.rs:11:13: 11:64 + StorageLive(_3); // scope 0 at $DIR/discriminant.rs:11:34: 11:44 +- _3 = std::option::Option::::Some(const true); // scope 0 at $DIR/discriminant.rs:11:34: 11:44 ++ _3 = const std::option::Option::::Some(true); // scope 0 at $DIR/discriminant.rs:11:34: 11:44 // ty::Const - // + ty: bool + // + ty: std::option::Option // + val: Value(Scalar(0x01)) // mir::Constant -- // + span: $DIR/discriminant.rs:6:39: 6:43 +- // + span: $DIR/discriminant.rs:11:39: 11:43 - // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } -- _4 = discriminant(_3); // scope 0 at $DIR/discriminant.rs:6:21: 6:31 -- switchInt(move _4) -> [1isize: bb2, otherwise: bb1]; // scope 0 at $DIR/discriminant.rs:6:21: 6:31 -+ // + span: $DIR/discriminant.rs:6:34: 6:44 +- _4 = discriminant(_3); // scope 0 at $DIR/discriminant.rs:11:21: 11:31 +- switchInt(move _4) -> [1isize: bb2, otherwise: bb1]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31 ++ // + span: $DIR/discriminant.rs:11:34: 11:44 + // + literal: Const { ty: std::option::Option, val: Value(Scalar(0x01)) } -+ _4 = const 1isize; // scope 0 at $DIR/discriminant.rs:6:21: 6:31 ++ _4 = const 1isize; // scope 0 at $DIR/discriminant.rs:11:21: 11:31 + // ty::Const + // + ty: isize + // + val: Value(Scalar(0x00000001)) + // mir::Constant -+ // + span: $DIR/discriminant.rs:6:21: 6:31 ++ // + span: $DIR/discriminant.rs:11:21: 11:31 + // + literal: Const { ty: isize, val: Value(Scalar(0x00000001)) } -+ switchInt(const 1isize) -> [1isize: bb2, otherwise: bb1]; // scope 0 at $DIR/discriminant.rs:6:21: 6:31 ++ switchInt(const 1isize) -> [1isize: bb2, otherwise: bb1]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31 + // ty::Const + // + ty: isize + // + val: Value(Scalar(0x00000001)) + // mir::Constant -+ // + span: $DIR/discriminant.rs:6:21: 6:31 ++ // + span: $DIR/discriminant.rs:11:21: 11:31 + // + literal: Const { ty: isize, val: Value(Scalar(0x00000001)) } } bb1: { - _2 = const 10i32; // scope 0 at $DIR/discriminant.rs:6:59: 6:61 + _2 = const 10i32; // scope 0 at $DIR/discriminant.rs:11:59: 11:61 // ty::Const // + ty: i32 // + val: Value(Scalar(0x0000000a)) // mir::Constant - // + span: $DIR/discriminant.rs:6:59: 6:61 + // + span: $DIR/discriminant.rs:11:59: 11:61 // + literal: Const { ty: i32, val: Value(Scalar(0x0000000a)) } - goto -> bb4; // scope 0 at $DIR/discriminant.rs:6:13: 6:64 + goto -> bb4; // scope 0 at $DIR/discriminant.rs:11:13: 11:64 } bb2: { -- switchInt(((_3 as Some).0: bool)) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:6:26: 6:30 -+ switchInt(const true) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:6:26: 6:30 -+ // ty::Const -+ // + ty: bool -+ // + val: Value(Scalar(0x01)) -+ // mir::Constant -+ // + span: $DIR/discriminant.rs:6:26: 6:30 -+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } + switchInt(((_3 as Some).0: bool)) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30 } bb3: { - _2 = const 42i32; // scope 0 at $DIR/discriminant.rs:6:47: 6:49 + _2 = const 42i32; // scope 0 at $DIR/discriminant.rs:11:47: 11:49 // ty::Const // + ty: i32 // + val: Value(Scalar(0x0000002a)) // mir::Constant - // + span: $DIR/discriminant.rs:6:47: 6:49 + // + span: $DIR/discriminant.rs:11:47: 11:49 // + literal: Const { ty: i32, val: Value(Scalar(0x0000002a)) } - goto -> bb4; // scope 0 at $DIR/discriminant.rs:6:13: 6:64 + goto -> bb4; // scope 0 at $DIR/discriminant.rs:11:13: 11:64 } bb4: { - _1 = Add(move _2, const 0i32); // scope 0 at $DIR/discriminant.rs:6:13: 6:68 + _1 = Add(move _2, const 0i32); // scope 0 at $DIR/discriminant.rs:11:13: 11:68 // ty::Const // + ty: i32 // + val: Value(Scalar(0x00000000)) // mir::Constant - // + span: $DIR/discriminant.rs:6:67: 6:68 + // + span: $DIR/discriminant.rs:11:67: 11:68 // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) } - StorageDead(_2); // scope 0 at $DIR/discriminant.rs:6:67: 6:68 - StorageDead(_3); // scope 0 at $DIR/discriminant.rs:6:68: 6:69 - _0 = const (); // scope 0 at $DIR/discriminant.rs:5:11: 7:2 + StorageDead(_2); // scope 0 at $DIR/discriminant.rs:11:67: 11:68 + StorageDead(_3); // scope 0 at $DIR/discriminant.rs:11:68: 11:69 + _0 = const (); // scope 0 at $DIR/discriminant.rs:10:11: 12:2 // ty::Const // + ty: () // + val: Value(Scalar()) // mir::Constant - // + span: $DIR/discriminant.rs:5:11: 7:2 + // + span: $DIR/discriminant.rs:10:11: 12:2 // + literal: Const { ty: (), val: Value(Scalar()) } - StorageDead(_1); // scope 0 at $DIR/discriminant.rs:7:1: 7:2 - return; // scope 0 at $DIR/discriminant.rs:7:2: 7:2 + StorageDead(_1); // scope 0 at $DIR/discriminant.rs:12:1: 12:2 + return; // scope 0 at $DIR/discriminant.rs:12:2: 12:2 } } diff --git a/src/test/mir-opt/const_prop/discriminant/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/discriminant/64bit/rustc.main.ConstProp.diff index ec0341e3de251..75b4b7e5a62ba 100644 --- a/src/test/mir-opt/const_prop/discriminant/64bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/discriminant/64bit/rustc.main.ConstProp.diff @@ -2,100 +2,93 @@ + // MIR for `main` after ConstProp fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/discriminant.rs:5:11: 5:11 - let _1: i32; // in scope 0 at $DIR/discriminant.rs:6:9: 6:10 - let mut _2: i32; // in scope 0 at $DIR/discriminant.rs:6:13: 6:64 - let mut _3: std::option::Option; // in scope 0 at $DIR/discriminant.rs:6:34: 6:44 - let mut _4: isize; // in scope 0 at $DIR/discriminant.rs:6:21: 6:31 + let mut _0: (); // return place in scope 0 at $DIR/discriminant.rs:10:11: 10:11 + let _1: i32; // in scope 0 at $DIR/discriminant.rs:11:9: 11:10 + let mut _2: i32; // in scope 0 at $DIR/discriminant.rs:11:13: 11:64 + let mut _3: std::option::Option; // in scope 0 at $DIR/discriminant.rs:11:34: 11:44 + let mut _4: isize; // in scope 0 at $DIR/discriminant.rs:11:21: 11:31 scope 1 { - debug x => _1; // in scope 1 at $DIR/discriminant.rs:6:9: 6:10 + debug x => _1; // in scope 1 at $DIR/discriminant.rs:11:9: 11:10 } bb0: { - StorageLive(_1); // scope 0 at $DIR/discriminant.rs:6:9: 6:10 - StorageLive(_2); // scope 0 at $DIR/discriminant.rs:6:13: 6:64 - StorageLive(_3); // scope 0 at $DIR/discriminant.rs:6:34: 6:44 -- _3 = std::option::Option::::Some(const true); // scope 0 at $DIR/discriminant.rs:6:34: 6:44 -+ _3 = const std::option::Option::::Some(true); // scope 0 at $DIR/discriminant.rs:6:34: 6:44 + StorageLive(_1); // scope 0 at $DIR/discriminant.rs:11:9: 11:10 + StorageLive(_2); // scope 0 at $DIR/discriminant.rs:11:13: 11:64 + StorageLive(_3); // scope 0 at $DIR/discriminant.rs:11:34: 11:44 +- _3 = std::option::Option::::Some(const true); // scope 0 at $DIR/discriminant.rs:11:34: 11:44 ++ _3 = const std::option::Option::::Some(true); // scope 0 at $DIR/discriminant.rs:11:34: 11:44 // ty::Const - // + ty: bool + // + ty: std::option::Option // + val: Value(Scalar(0x01)) // mir::Constant -- // + span: $DIR/discriminant.rs:6:39: 6:43 +- // + span: $DIR/discriminant.rs:11:39: 11:43 - // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } -- _4 = discriminant(_3); // scope 0 at $DIR/discriminant.rs:6:21: 6:31 -- switchInt(move _4) -> [1isize: bb2, otherwise: bb1]; // scope 0 at $DIR/discriminant.rs:6:21: 6:31 -+ // + span: $DIR/discriminant.rs:6:34: 6:44 +- _4 = discriminant(_3); // scope 0 at $DIR/discriminant.rs:11:21: 11:31 +- switchInt(move _4) -> [1isize: bb2, otherwise: bb1]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31 ++ // + span: $DIR/discriminant.rs:11:34: 11:44 + // + literal: Const { ty: std::option::Option, val: Value(Scalar(0x01)) } -+ _4 = const 1isize; // scope 0 at $DIR/discriminant.rs:6:21: 6:31 ++ _4 = const 1isize; // scope 0 at $DIR/discriminant.rs:11:21: 11:31 + // ty::Const + // + ty: isize + // + val: Value(Scalar(0x0000000000000001)) + // mir::Constant -+ // + span: $DIR/discriminant.rs:6:21: 6:31 ++ // + span: $DIR/discriminant.rs:11:21: 11:31 + // + literal: Const { ty: isize, val: Value(Scalar(0x0000000000000001)) } -+ switchInt(const 1isize) -> [1isize: bb2, otherwise: bb1]; // scope 0 at $DIR/discriminant.rs:6:21: 6:31 ++ switchInt(const 1isize) -> [1isize: bb2, otherwise: bb1]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31 + // ty::Const + // + ty: isize + // + val: Value(Scalar(0x0000000000000001)) + // mir::Constant -+ // + span: $DIR/discriminant.rs:6:21: 6:31 ++ // + span: $DIR/discriminant.rs:11:21: 11:31 + // + literal: Const { ty: isize, val: Value(Scalar(0x0000000000000001)) } } bb1: { - _2 = const 10i32; // scope 0 at $DIR/discriminant.rs:6:59: 6:61 + _2 = const 10i32; // scope 0 at $DIR/discriminant.rs:11:59: 11:61 // ty::Const // + ty: i32 // + val: Value(Scalar(0x0000000a)) // mir::Constant - // + span: $DIR/discriminant.rs:6:59: 6:61 + // + span: $DIR/discriminant.rs:11:59: 11:61 // + literal: Const { ty: i32, val: Value(Scalar(0x0000000a)) } - goto -> bb4; // scope 0 at $DIR/discriminant.rs:6:13: 6:64 + goto -> bb4; // scope 0 at $DIR/discriminant.rs:11:13: 11:64 } bb2: { -- switchInt(((_3 as Some).0: bool)) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:6:26: 6:30 -+ switchInt(const true) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:6:26: 6:30 -+ // ty::Const -+ // + ty: bool -+ // + val: Value(Scalar(0x01)) -+ // mir::Constant -+ // + span: $DIR/discriminant.rs:6:26: 6:30 -+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } + switchInt(((_3 as Some).0: bool)) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30 } bb3: { - _2 = const 42i32; // scope 0 at $DIR/discriminant.rs:6:47: 6:49 + _2 = const 42i32; // scope 0 at $DIR/discriminant.rs:11:47: 11:49 // ty::Const // + ty: i32 // + val: Value(Scalar(0x0000002a)) // mir::Constant - // + span: $DIR/discriminant.rs:6:47: 6:49 + // + span: $DIR/discriminant.rs:11:47: 11:49 // + literal: Const { ty: i32, val: Value(Scalar(0x0000002a)) } - goto -> bb4; // scope 0 at $DIR/discriminant.rs:6:13: 6:64 + goto -> bb4; // scope 0 at $DIR/discriminant.rs:11:13: 11:64 } bb4: { - _1 = Add(move _2, const 0i32); // scope 0 at $DIR/discriminant.rs:6:13: 6:68 + _1 = Add(move _2, const 0i32); // scope 0 at $DIR/discriminant.rs:11:13: 11:68 // ty::Const // + ty: i32 // + val: Value(Scalar(0x00000000)) // mir::Constant - // + span: $DIR/discriminant.rs:6:67: 6:68 + // + span: $DIR/discriminant.rs:11:67: 11:68 // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) } - StorageDead(_2); // scope 0 at $DIR/discriminant.rs:6:67: 6:68 - StorageDead(_3); // scope 0 at $DIR/discriminant.rs:6:68: 6:69 - _0 = const (); // scope 0 at $DIR/discriminant.rs:5:11: 7:2 + StorageDead(_2); // scope 0 at $DIR/discriminant.rs:11:67: 11:68 + StorageDead(_3); // scope 0 at $DIR/discriminant.rs:11:68: 11:69 + _0 = const (); // scope 0 at $DIR/discriminant.rs:10:11: 12:2 // ty::Const // + ty: () // + val: Value(Scalar()) // mir::Constant - // + span: $DIR/discriminant.rs:5:11: 7:2 + // + span: $DIR/discriminant.rs:10:11: 12:2 // + literal: Const { ty: (), val: Value(Scalar()) } - StorageDead(_1); // scope 0 at $DIR/discriminant.rs:7:1: 7:2 - return; // scope 0 at $DIR/discriminant.rs:7:2: 7:2 + StorageDead(_1); // scope 0 at $DIR/discriminant.rs:12:1: 12:2 + return; // scope 0 at $DIR/discriminant.rs:12:2: 12:2 } } From 9ceb9bb20324630380153c1db5aeb56a433ab8d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Tue, 2 Jun 2020 22:35:31 +0200 Subject: [PATCH 06/34] Move copying of self-contained objects to new function --- src/bootstrap/compile.rs | 88 ++++++++++++++++++++++++++++------------ 1 file changed, 63 insertions(+), 25 deletions(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index c09b73b042013..56d72d72b6109 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -74,6 +74,7 @@ impl Step for Std { // Even if we're not building std this stage, the new sysroot must // still contain the third party objects needed by various targets. copy_third_party_objects(builder, &compiler, target); + copy_self_contained_objects(builder, &compiler, target); builder.ensure(StdLink { compiler: compiler_to_use, @@ -84,6 +85,7 @@ impl Step for Std { } target_deps.extend(copy_third_party_objects(builder, &compiler, target).into_iter()); + target_deps.extend(copy_self_contained_objects(builder, &compiler, target)); let mut cargo = builder.cargo(compiler, Mode::Std, target, "build"); std_cargo(builder, target, compiler.stage, &mut cargo); @@ -109,6 +111,19 @@ impl Step for Std { } } +fn copy_and_stamp( + builder: &Builder<'_>, + libdir: &Path, + sourcedir: &Path, + name: &str, + target_deps: &mut Vec, +) { + let target = libdir.join(name); + builder.copy(&sourcedir.join(name), &target); + + target_deps.push((target, dependency_type)); +} + /// Copies third party objects needed by various targets. fn copy_third_party_objects( builder: &Builder<'_>, @@ -116,32 +131,8 @@ fn copy_third_party_objects( target: Interned, ) -> Vec { let libdir = builder.sysroot_libdir(*compiler, target); - let mut target_deps = vec![]; - let mut copy_and_stamp = |sourcedir: &Path, name: &str| { - let target = libdir.join(name); - builder.copy(&sourcedir.join(name), &target); - target_deps.push(target); - }; - - // Copies the CRT objects. - // - // rustc historically provides a more self-contained installation for musl targets - // not requiring the presence of a native musl toolchain. For example, it can fall back - // to using gcc from a glibc-targeting toolchain for linking. - // To do that we have to distribute musl startup objects as a part of Rust toolchain - // and link with them manually in the self-contained mode. - if target.contains("musl") { - let srcdir = builder.musl_root(target).unwrap().join("lib"); - for &obj in &["crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] { - copy_and_stamp(&srcdir, obj); - } - } else if target.ends_with("-wasi") { - let srcdir = builder.wasi_root(target).unwrap().join("lib/wasm32-wasi"); - copy_and_stamp(&srcdir, "crt1.o"); - } - // Copies libunwind.a compiled to be linked with x86_64-fortanix-unknown-sgx. // // This target needs to be linked to Fortanix's port of llvm's libunwind. @@ -151,7 +142,13 @@ fn copy_third_party_objects( let src_path_env = "X86_FORTANIX_SGX_LIBS"; let src = env::var(src_path_env).unwrap_or_else(|_| panic!("{} not found in env", src_path_env)); - copy_and_stamp(Path::new(&src), "libunwind.a"); + copy_and_stamp( + builder, + &*libdir, + Path::new(&src), + "libunwind.a", + &mut target_deps, + ); } if builder.config.sanitizers && compiler.stage != 0 { @@ -163,6 +160,47 @@ fn copy_third_party_objects( target_deps } +/// Copies third party objects needed by various targets for self-contained linkage. +fn copy_self_contained_objects( + builder: &Builder<'_>, + compiler: &Compiler, + target: Interned, +) -> Vec { + let libdir = builder.sysroot_libdir(*compiler, target); + let mut target_deps = vec![]; + + // Copies the CRT objects. + // + // rustc historically provides a more self-contained installation for musl targets + // not requiring the presence of a native musl toolchain. For example, it can fall back + // to using gcc from a glibc-targeting toolchain for linking. + // To do that we have to distribute musl startup objects as a part of Rust toolchain + // and link with them manually in the self-contained mode. + if target.contains("musl") { + let srcdir = builder.musl_root(target).unwrap().join("lib"); + for &obj in &["crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] { + copy_and_stamp( + builder, + &libdir_self_contained, + &srcdir, + obj, + &mut target_deps, + ); + } + } else if target.ends_with("-wasi") { + let srcdir = builder.wasi_root(target).unwrap().join("lib/wasm32-wasi"); + copy_and_stamp( + builder, + &libdir_self_contained, + &srcdir, + "crt1.o", + &mut target_deps, + ); + } + + target_deps +} + /// Configure cargo to compile the standard library, adding appropriate env vars /// and such. pub fn std_cargo(builder: &Builder<'_>, target: Interned, stage: u32, cargo: &mut Cargo) { From 638ebbc5859a38794408a988ffec6f54e0dc0f0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Tue, 2 Jun 2020 23:18:41 +0200 Subject: [PATCH 07/34] Move copying of MinGW CRT to the better location --- src/bootstrap/compile.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 56d72d72b6109..4f58e55f21401 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -196,6 +196,13 @@ fn copy_self_contained_objects( "crt1.o", &mut target_deps, ); + } else if target.contains("windows-gnu") { + for obj in ["crt2.o", "dllcrt2.o"].iter() { + let src = compiler_file(builder, builder.cc(target), target, obj); + let target = libdir.join(obj); + builder.copy(&src, &target); + target_deps.push(target); + } } target_deps @@ -419,13 +426,6 @@ impl Step for StartupObjects { target_deps.push(target); } - for obj in ["crt2.o", "dllcrt2.o"].iter() { - let src = compiler_file(builder, builder.cc(target), target, obj); - let target = sysroot_dir.join(obj); - builder.copy(&src, &target); - target_deps.push(target); - } - target_deps } } From 961974fe0348f479255f9e95b5924419c2c15a77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Wed, 3 Jun 2020 00:56:27 +0200 Subject: [PATCH 08/34] Use enum to distinguish dependency type --- src/bootstrap/compile.rs | 52 ++++++++++++++++++++++++---------------- src/bootstrap/dist.rs | 6 ++--- src/bootstrap/lib.rs | 22 ++++++++++++++--- 3 files changed, 54 insertions(+), 26 deletions(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 4f58e55f21401..5fae7277149d2 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -23,7 +23,7 @@ use crate::builder::Cargo; use crate::dist; use crate::native; use crate::util::{exe, is_dylib, symlink_dir}; -use crate::{Compiler, GitRepo, Mode}; +use crate::{Compiler, DependencyType, GitRepo, Mode}; use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; @@ -84,7 +84,7 @@ impl Step for Std { return; } - target_deps.extend(copy_third_party_objects(builder, &compiler, target).into_iter()); + target_deps.extend(copy_third_party_objects(builder, &compiler, target)); target_deps.extend(copy_self_contained_objects(builder, &compiler, target)); let mut cargo = builder.cargo(compiler, Mode::Std, target, "build"); @@ -116,7 +116,8 @@ fn copy_and_stamp( libdir: &Path, sourcedir: &Path, name: &str, - target_deps: &mut Vec, + target_deps: &mut Vec<(PathBuf, DependencyType)>, + dependency_type: DependencyType, ) { let target = libdir.join(name); builder.copy(&sourcedir.join(name), &target); @@ -129,7 +130,7 @@ fn copy_third_party_objects( builder: &Builder<'_>, compiler: &Compiler, target: Interned, -) -> Vec { +) -> Vec<(PathBuf, DependencyType)> { let libdir = builder.sysroot_libdir(*compiler, target); let mut target_deps = vec![]; @@ -148,13 +149,18 @@ fn copy_third_party_objects( Path::new(&src), "libunwind.a", &mut target_deps, + DependencyType::Target, ); } if builder.config.sanitizers && compiler.stage != 0 { // The sanitizers are only copied in stage1 or above, // to avoid creating dependency on LLVM. - target_deps.extend(copy_sanitizers(builder, &compiler, target)); + target_deps.extend( + copy_sanitizers(builder, &compiler, target) + .into_iter() + .map(|d| (d, DependencyType::Target)), + ); } target_deps @@ -165,7 +171,7 @@ fn copy_self_contained_objects( builder: &Builder<'_>, compiler: &Compiler, target: Interned, -) -> Vec { +) -> Vec<(PathBuf, DependencyType)> { let libdir = builder.sysroot_libdir(*compiler, target); let mut target_deps = vec![]; @@ -185,6 +191,7 @@ fn copy_self_contained_objects( &srcdir, obj, &mut target_deps, + DependencyType::TargetSelfContained, ); } } else if target.ends_with("-wasi") { @@ -195,13 +202,14 @@ fn copy_self_contained_objects( &srcdir, "crt1.o", &mut target_deps, + DependencyType::TargetSelfContained, ); } else if target.contains("windows-gnu") { for obj in ["crt2.o", "dllcrt2.o"].iter() { let src = compiler_file(builder, builder.cc(target), target, obj); let target = libdir.join(obj); builder.copy(&src, &target); - target_deps.push(target); + target_deps.push((target, DependencyType::TargetSelfContained)); } } @@ -370,7 +378,7 @@ pub struct StartupObjects { } impl Step for StartupObjects { - type Output = Vec; + type Output = Vec<(PathBuf, DependencyType)>; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { run.path("src/rtstartup") @@ -389,7 +397,7 @@ impl Step for StartupObjects { /// They don't require any library support as they're just plain old object /// files, so we just use the nightly snapshot compiler to always build them (as /// no other compilers are guaranteed to be available). - fn run(self, builder: &Builder<'_>) -> Vec { + fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> { let for_compiler = self.compiler; let target = self.target; if !target.contains("windows-gnu") { @@ -423,7 +431,7 @@ impl Step for StartupObjects { let target = sysroot_dir.join((*file).to_string() + ".o"); builder.copy(dst_file, &target); - target_deps.push(target); + target_deps.push((target, DependencyType::Target)); } target_deps @@ -838,8 +846,8 @@ pub fn add_to_sysroot( ) { t!(fs::create_dir_all(&sysroot_dst)); t!(fs::create_dir_all(&sysroot_host_dst)); - for (path, host) in builder.read_stamp_file(stamp) { - if host { + for (path, dependency_type) in builder.read_stamp_file(stamp) { + if dependency_type == DependencyType::Host { builder.copy(&path, &sysroot_host_dst.join(path.file_name().unwrap())); } else { builder.copy(&path, &sysroot_dst.join(path.file_name().unwrap())); @@ -852,7 +860,7 @@ pub fn run_cargo( cargo: Cargo, tail_args: Vec, stamp: &Path, - additional_target_deps: Vec, + additional_target_deps: Vec<(PathBuf, DependencyType)>, is_check: bool, ) -> Vec { if builder.config.dry_run { @@ -903,7 +911,7 @@ pub fn run_cargo( if filename.starts_with(&host_root_dir) { // Unless it's a proc macro used in the compiler if crate_types.iter().any(|t| t == "proc-macro") { - deps.push((filename.to_path_buf(), true)); + deps.push((filename.to_path_buf(), DependencyType::Host)); } continue; } @@ -911,7 +919,7 @@ pub fn run_cargo( // If this was output in the `deps` dir then this is a precise file // name (hash included) so we start tracking it. if filename.starts_with(&target_deps_dir) { - deps.push((filename.to_path_buf(), false)); + deps.push((filename.to_path_buf(), DependencyType::Target)); continue; } @@ -963,17 +971,21 @@ pub fn run_cargo( let candidate = format!("{}.lib", path_to_add); let candidate = PathBuf::from(candidate); if candidate.exists() { - deps.push((candidate, false)); + deps.push((candidate, DependencyType::Target)); } } - deps.push((path_to_add.into(), false)); + deps.push((path_to_add.into(), DependencyType::Target)); } - deps.extend(additional_target_deps.into_iter().map(|d| (d, false))); + deps.extend(additional_target_deps); deps.sort(); let mut new_contents = Vec::new(); - for (dep, proc_macro) in deps.iter() { - new_contents.extend(if *proc_macro { b"h" } else { b"t" }); + for (dep, dependency_type) in deps.iter() { + new_contents.extend(match *dependency_type { + DependencyType::Host => b"h", + DependencyType::Target => b"t", + DependencyType::TargetSelfContained => b"s", + }); new_contents.extend(dep.to_str().unwrap().as_bytes()); new_contents.extend(b"\0"); } diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 5e966d7055bf3..77dd9c784badf 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -22,7 +22,7 @@ use crate::channel; use crate::compile; use crate::tool::{self, Tool}; use crate::util::{exe, is_dylib, timeit}; -use crate::{Compiler, Mode, LLVM_TOOLS}; +use crate::{Compiler, DependencyType, Mode, LLVM_TOOLS}; use time::{self, Timespec}; pub fn pkgname(builder: &Builder<'_>, component: &str) -> String { @@ -651,8 +651,8 @@ fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool { fn copy_target_libs(builder: &Builder<'_>, target: &str, image: &Path, stamp: &Path) { let dst = image.join("lib/rustlib").join(target).join("lib"); t!(fs::create_dir_all(&dst)); - for (path, host) in builder.read_stamp_file(stamp) { - if !host || builder.config.build == target { + for (path, dependency_type) in builder.read_stamp_file(stamp) { + if dependency_type != DependencyType::Host || builder.config.build == target { builder.copy(&path, &dst.join(path.file_name().unwrap())); } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 8d8a036caef88..db861cb701371 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -280,6 +280,17 @@ impl Crate { } } +/// When building Rust various objects are handled differently. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub enum DependencyType { + /// Libraries originating from proc-macros. + Host, + /// Typical Rust libraries. + Target, + /// Non Rust libraries and objects shipped to ease usage of certain targets. + TargetSelfContained, +} + /// The various "modes" of invoking Cargo. /// /// These entries currently correspond to the various output directories of the @@ -1097,7 +1108,7 @@ impl Build { ret } - fn read_stamp_file(&self, stamp: &Path) -> Vec<(PathBuf, bool)> { + fn read_stamp_file(&self, stamp: &Path) -> Vec<(PathBuf, DependencyType)> { if self.config.dry_run { return Vec::new(); } @@ -1110,9 +1121,14 @@ impl Build { if part.is_empty() { continue; } - let host = part[0] as char == 'h'; + let dependency_type = match part[0] as char { + 'h' => DependencyType::Host, + 's' => DependencyType::TargetSelfContained, + 't' => DependencyType::Target, + _ => unreachable!(), + }; let path = PathBuf::from(t!(str::from_utf8(&part[1..]))); - paths.push((path, host)); + paths.push((path, dependency_type)); } paths } From 5d298836f2254144f80e56ee37af44ac79f3eb2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Thu, 11 Jun 2020 18:12:19 +0200 Subject: [PATCH 09/34] Move some libs to self-contained directory --- src/bootstrap/compile.rs | 24 +++++++++++++++++------- src/bootstrap/dist.rs | 13 +++++++++++-- src/librustc_codegen_ssa/back/link.rs | 7 +++++++ 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 5fae7277149d2..4b739da91ce13 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -172,7 +172,14 @@ fn copy_self_contained_objects( compiler: &Compiler, target: Interned, ) -> Vec<(PathBuf, DependencyType)> { - let libdir = builder.sysroot_libdir(*compiler, target); + // cfg(bootstrap) + // Remove when upgrading bootstrap compiler. + let libdir_self_contained = if compiler.stage == 0 { + builder.sysroot_libdir(*compiler, target).to_path_buf() + } else { + builder.sysroot_libdir(*compiler, target).join("self-contained") + }; + t!(fs::create_dir_all(&libdir_self_contained)); let mut target_deps = vec![]; // Copies the CRT objects. @@ -207,7 +214,7 @@ fn copy_self_contained_objects( } else if target.contains("windows-gnu") { for obj in ["crt2.o", "dllcrt2.o"].iter() { let src = compiler_file(builder, builder.cc(target), target, obj); - let target = libdir.join(obj); + let target = libdir_self_contained.join(obj); builder.copy(&src, &target); target_deps.push((target, DependencyType::TargetSelfContained)); } @@ -844,14 +851,17 @@ pub fn add_to_sysroot( sysroot_host_dst: &Path, stamp: &Path, ) { + let self_contained_dst = &sysroot_dst.join("self-contained"); t!(fs::create_dir_all(&sysroot_dst)); t!(fs::create_dir_all(&sysroot_host_dst)); + t!(fs::create_dir_all(&self_contained_dst)); for (path, dependency_type) in builder.read_stamp_file(stamp) { - if dependency_type == DependencyType::Host { - builder.copy(&path, &sysroot_host_dst.join(path.file_name().unwrap())); - } else { - builder.copy(&path, &sysroot_dst.join(path.file_name().unwrap())); - } + let dst = match dependency_type { + DependencyType::Host => sysroot_host_dst, + DependencyType::Target => sysroot_dst, + DependencyType::TargetSelfContained => self_contained_dst, + }; + builder.copy(&path, &dst.join(path.file_name().unwrap())); } } diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 77dd9c784badf..08737d9a0474e 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -321,7 +321,12 @@ fn make_win_dist( ); //Copy platform libs to platform-specific lib directory - let target_lib_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("lib"); + let target_lib_dir = plat_root + .join("lib") + .join("rustlib") + .join(target_triple) + .join("lib") + .join("self-contained"); fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed"); for src in target_libs { builder.copy_to_folder(&src, &target_lib_dir); @@ -650,9 +655,13 @@ fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool { /// Copy stamped files into an image's `target/lib` directory. fn copy_target_libs(builder: &Builder<'_>, target: &str, image: &Path, stamp: &Path) { let dst = image.join("lib/rustlib").join(target).join("lib"); + let self_contained_dst = dst.join("self-contained"); t!(fs::create_dir_all(&dst)); + t!(fs::create_dir_all(&self_contained_dst)); for (path, dependency_type) in builder.read_stamp_file(stamp) { - if dependency_type != DependencyType::Host || builder.config.build == target { + if dependency_type == DependencyType::TargetSelfContained { + builder.copy(&path, &self_contained_dst.join(path.file_name().unwrap())); + } else if dependency_type == DependencyType::Target || builder.config.build == target { builder.copy(&path, &dst.join(path.file_name().unwrap())); } } diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 53e3da3c0baf0..c57b01dff2801 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1075,6 +1075,10 @@ fn get_object_file_path(sess: &Session, name: &str) -> PathBuf { if file_path.exists() { return file_path; } + let file_path = fs.get_lib_path().join("self-contained").join(name); + if file_path.exists() { + return file_path; + } for search_path in fs.search_paths() { let file_path = search_path.dir.join(name); if file_path.exists() { @@ -1470,6 +1474,9 @@ fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session) { // The location of crates will be determined as needed. let lib_path = sess.target_filesearch(PathKind::All).get_lib_path(); cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); + + let lib_path = sess.target_filesearch(PathKind::All).get_lib_path().join("self-contained"); + cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); } /// Add options making relocation sections in the produced ELF files read-only From e9ac01a9beeae77a15badcec094a7a4da0bebecb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Mon, 8 Jun 2020 12:47:56 +0200 Subject: [PATCH 10/34] Get self-contained directory path via dedicated function --- src/librustc_codegen_ssa/back/link.rs | 4 ++-- src/librustc_session/filesearch.rs | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index c57b01dff2801..1eef86f6c931c 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1075,7 +1075,7 @@ fn get_object_file_path(sess: &Session, name: &str) -> PathBuf { if file_path.exists() { return file_path; } - let file_path = fs.get_lib_path().join("self-contained").join(name); + let file_path = fs.get_selfcontained_lib_path().join(name); if file_path.exists() { return file_path; } @@ -1475,7 +1475,7 @@ fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session) { let lib_path = sess.target_filesearch(PathKind::All).get_lib_path(); cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); - let lib_path = sess.target_filesearch(PathKind::All).get_lib_path().join("self-contained"); + let lib_path = sess.target_filesearch(PathKind::All).get_selfcontained_lib_path(); cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); } diff --git a/src/librustc_session/filesearch.rs b/src/librustc_session/filesearch.rs index e98746231fb30..37d7b0c7e1f71 100644 --- a/src/librustc_session/filesearch.rs +++ b/src/librustc_session/filesearch.rs @@ -41,6 +41,10 @@ impl<'a> FileSearch<'a> { make_target_lib_path(self.sysroot, self.triple) } + pub fn get_selfcontained_lib_path(&self) -> PathBuf { + self.get_lib_path().join("self-contained") + } + pub fn search(&self, mut pick: F) where F: FnMut(&SearchPathFile, PathKind) -> FileMatch, From 43905cd7501fd37090cb9de6069faaba761e514a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Mon, 8 Jun 2020 13:20:26 +0200 Subject: [PATCH 11/34] Move shipped MinGW linker to self-contained dir --- src/bootstrap/dist.rs | 7 ++++++- src/librustc_session/filesearch.rs | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 08737d9a0474e..df1253f3f9e7c 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -306,7 +306,12 @@ fn make_win_dist( } //Copy platform tools to platform-specific bin directory - let target_bin_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("bin"); + let target_bin_dir = plat_root + .join("lib") + .join("rustlib") + .join(target_triple) + .join("bin") + .join("self-contained"); fs::create_dir_all(&target_bin_dir).expect("creating target_bin_dir failed"); for src in target_tools { builder.copy_to_folder(&src, &target_bin_dir); diff --git a/src/librustc_session/filesearch.rs b/src/librustc_session/filesearch.rs index 37d7b0c7e1f71..5586b82b0edc0 100644 --- a/src/librustc_session/filesearch.rs +++ b/src/librustc_session/filesearch.rs @@ -98,7 +98,7 @@ impl<'a> FileSearch<'a> { p.push(RUST_LIB_DIR); p.push(&self.triple); p.push("bin"); - vec![p] + vec![p.clone(), p.join("self-contained")] } } From d5ea0e9f8def9a3ec0eb2dd88f0465d4d1a81c21 Mon Sep 17 00:00:00 2001 From: oddg Date: Thu, 14 May 2020 19:58:43 -0700 Subject: [PATCH 12/34] Report error when casting an C-like enum implementing Drop --- src/librustc_session/lint/builtin.rs | 11 ++++++++++ src/librustc_typeck/check/cast.rs | 30 +++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/librustc_session/lint/builtin.rs b/src/librustc_session/lint/builtin.rs index 58388bafbeddf..5a8f5c1b9fbca 100644 --- a/src/librustc_session/lint/builtin.rs +++ b/src/librustc_session/lint/builtin.rs @@ -534,6 +534,16 @@ declare_lint! { @feature_gate = sym::unsafe_block_in_unsafe_fn; } +declare_lint! { + pub CENUM_IMPL_DROP_CAST, + Warn, + "a C-like enum implementing Drop is cast", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #73333 ", + edition: None, + }; +} + declare_lint_pass! { /// Does nothing as a lint pass, but registers some `Lint`s /// that are used by other parts of the compiler. @@ -607,6 +617,7 @@ declare_lint_pass! { ASM_SUB_REGISTER, UNSAFE_OP_IN_UNSAFE_FN, INCOMPLETE_INCLUDE, + CENUM_IMPL_DROP_CAST, ] } diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 46d6706cbf429..bea5e0e996658 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -609,7 +609,10 @@ impl<'a, 'tcx> CastCheck<'tcx> { (FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt), // prim -> prim - (Int(CEnum), Int(_)) => Ok(CastKind::EnumCast), + (Int(CEnum), Int(_)) => { + self.cenum_impl_drop_lint(fcx); + Ok(CastKind::EnumCast) + } (Int(Char) | Int(Bool), Int(_)) => Ok(CastKind::PrimIntCast), (Int(_) | Float, Int(_) | Float) => Ok(CastKind::NumericCast), @@ -706,11 +709,13 @@ impl<'a, 'tcx> CastCheck<'tcx> { // Coerce to a raw pointer so that we generate AddressOf in MIR. let array_ptr_type = fcx.tcx.mk_ptr(m_expr); fcx.try_coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No) - .unwrap_or_else(|_| bug!( + .unwrap_or_else(|_| { + bug!( "could not cast from reference to array to pointer to array ({:?} to {:?})", self.expr_ty, array_ptr_type, - )); + ) + }); // this will report a type mismatch if needed fcx.demand_eqtype(self.span, ety, m_cast.ty); @@ -740,6 +745,25 @@ impl<'a, 'tcx> CastCheck<'tcx> { Err(err) => Err(err), } } + + fn cenum_impl_drop_lint(&self, fcx: &FnCtxt<'a, 'tcx>) { + if let ty::Adt(d, _) = self.expr_ty.kind { + if d.has_dtor(fcx.tcx) { + fcx.tcx.struct_span_lint_hir( + lint::builtin::CENUM_IMPL_DROP_CAST, + self.expr.hir_id, + self.span, + |err| { + err.build(&format!( + "Cast `enum` implementing `Drop` `{}` to integer `{}`", + self.expr_ty, self.cast_ty + )) + .emit(); + }, + ); + } + } + } } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { From e32db8458457849f5d894ffa4a1672b9071708f0 Mon Sep 17 00:00:00 2001 From: asrar Date: Sun, 14 Jun 2020 21:44:11 +0530 Subject: [PATCH 13/34] Add rust features to print target features `crt-static` is a rust specific target feature that's absent from llvm feature table, adding it there. --- src/rustllvm/PassWrapper.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 3d252fe70afeb..7586dd91ab68b 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -425,6 +425,9 @@ extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef TM) { for (auto &Feature : FeatTable) printf(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc); printf("\n"); + // Rust specific target features + printf(" %-*s - %s.\n", MaxFeatLen, "crt-static", "Enables libraries with C Run-time Libraries(CRT) to be statically linked"); + printf("\n"); printf("Use +feature to enable a feature, or -feature to disable it.\n" "For example, rustc -C -target-cpu=mycpu -C " From a40156e5b7053dcc36ba1ad65fb567b183c4e1fb Mon Sep 17 00:00:00 2001 From: oddg Date: Sun, 14 Jun 2020 15:49:20 -0700 Subject: [PATCH 14/34] UI test for deprecation warning of casting enum implementing Drop --- src/test/ui/cenum_impl_drop_cast.rs | 18 ++++++++++++++++++ src/test/ui/cenum_impl_drop_cast.stderr | 16 ++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 src/test/ui/cenum_impl_drop_cast.rs create mode 100644 src/test/ui/cenum_impl_drop_cast.stderr diff --git a/src/test/ui/cenum_impl_drop_cast.rs b/src/test/ui/cenum_impl_drop_cast.rs new file mode 100644 index 0000000000000..623460673bfa2 --- /dev/null +++ b/src/test/ui/cenum_impl_drop_cast.rs @@ -0,0 +1,18 @@ +#![deny(cenum_impl_drop_cast)] + +enum E { + A = 0, +} + +impl Drop for E { + fn drop(&mut self) { + println!("Drop"); + } +} + +fn main() { + let e = E::A; + let i = e as u32; + //~^ ERROR Cast `enum` implementing `Drop` `E` to integer `u32` + //~| WARN this was previously accepted +} diff --git a/src/test/ui/cenum_impl_drop_cast.stderr b/src/test/ui/cenum_impl_drop_cast.stderr new file mode 100644 index 0000000000000..5c8f86ffd72ad --- /dev/null +++ b/src/test/ui/cenum_impl_drop_cast.stderr @@ -0,0 +1,16 @@ +error: Cast `enum` implementing `Drop` `E` to integer `u32` + --> $DIR/cenum_impl_drop_cast.rs:15:13 + | +LL | let i = e as u32; + | ^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/cenum_impl_drop_cast.rs:1:9 + | +LL | #![deny(cenum_impl_drop_cast)] + | ^^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #73333 + +error: aborting due to previous error + From 0906066ae7d8a5e217e8cbf7f17de78a00d4ed83 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Mon, 15 Jun 2020 00:50:56 -0400 Subject: [PATCH 15/34] Test that bounds checks are elided when slice len is checked up-front --- src/test/codegen/issue-69101-bounds-check.rs | 26 ++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/test/codegen/issue-69101-bounds-check.rs diff --git a/src/test/codegen/issue-69101-bounds-check.rs b/src/test/codegen/issue-69101-bounds-check.rs new file mode 100644 index 0000000000000..cdbe51da03cc2 --- /dev/null +++ b/src/test/codegen/issue-69101-bounds-check.rs @@ -0,0 +1,26 @@ +// no-system-llvm +// compile-flags: -O +#![crate_type = "lib"] + +// CHECK-LABEL: @already_sliced_no_bounds_check +#[no_mangle] +pub fn already_sliced_no_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) { + // CHECK: slice_index_len_fail + // CHECK-NOT: panic_bounds_check + let _ = (&a[..2048], &b[..2048], &mut c[..2048]); + for i in 0..1024 { + c[i] = a[i] ^ b[i]; + } +} + +// make sure we're checking for the right thing: there can be a panic if the slice is too small +// CHECK-LABEL: @already_sliced_bounds_check +#[no_mangle] +pub fn already_sliced_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) { + // CHECK: slice_index_len_fail + // CHECK: panic_bounds_check + let _ = (&a[..1023], &b[..2048], &mut c[..2048]); + for i in 0..1024 { + c[i] = a[i] ^ b[i]; + } +} From d3ca6fd71ed3003e58c6b58d7beb0505d0c8adc3 Mon Sep 17 00:00:00 2001 From: Harald Hoyer Date: Mon, 15 Jun 2020 13:23:38 +0200 Subject: [PATCH 16/34] Enable static-pie for the x86_64-unknown-linux-musl target Fixes: https://github.com/rust-lang/rust/issues/70693 --- .../spec/x86_64_unknown_linux_musl.rs | 1 + src/test/run-make/static-pie/Makefile | 15 +++++++ src/test/run-make/static-pie/test-aslr.rs | 43 +++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 src/test/run-make/static-pie/Makefile create mode 100644 src/test/run-make/static-pie/test-aslr.rs diff --git a/src/librustc_target/spec/x86_64_unknown_linux_musl.rs b/src/librustc_target/spec/x86_64_unknown_linux_musl.rs index 34c628e8f67bd..3a22290da6858 100644 --- a/src/librustc_target/spec/x86_64_unknown_linux_musl.rs +++ b/src/librustc_target/spec/x86_64_unknown_linux_musl.rs @@ -6,6 +6,7 @@ pub fn target() -> TargetResult { base.max_atomic_width = Some(64); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); base.stack_probes = true; + base.static_position_independent_executables = true; Ok(Target { llvm_target: "x86_64-unknown-linux-musl".to_string(), diff --git a/src/test/run-make/static-pie/Makefile b/src/test/run-make/static-pie/Makefile new file mode 100644 index 0000000000000..1d3cc82138927 --- /dev/null +++ b/src/test/run-make/static-pie/Makefile @@ -0,0 +1,15 @@ +-include ../../run-make-fulldeps/tools.mk + +# only-x86_64-unknown-linux-musl + +# How to manually run this +# $ ./x.py test --target x86_64-unknown-linux-musl src/test/run-make/static-pie + +all: + $(RUSTC) --target $(TARGET) -C target-feature=+crt-static test-aslr.rs + # Check that no dynamic interpreter is set + ! readelf -l $(call RUN_BINFILE,test-aslr) | $(CGREP) INTERP + # Check that we have a dynamic executable + readelf -l $(call RUN_BINFILE,test-aslr) | $(CGREP) DYNAMIC + # Check for address space layout randomization + $(call RUN,test-aslr) --test-aslr diff --git a/src/test/run-make/static-pie/test-aslr.rs b/src/test/run-make/static-pie/test-aslr.rs new file mode 100644 index 0000000000000..f28e00f7f4cf9 --- /dev/null +++ b/src/test/run-make/static-pie/test-aslr.rs @@ -0,0 +1,43 @@ +const NUM_RUNS: usize = 10; + +fn run_self(exe: &str) -> usize { + use std::process::Command; + let mut set = std::collections::HashSet::new(); + + let mut cmd = Command::new(exe); + cmd.arg("--report"); + (0..NUM_RUNS).for_each(|_| { + set.insert(cmd.output().expect("failed to execute process").stdout); + }); + set.len() +} + +fn main() { + let mut args = std::env::args(); + let arg0 = args.next().unwrap(); + match args.next() { + Some(s) if s.eq("--report") => { + println!("main = {:#?}", &main as *const _); + } + Some(s) if s.eq("--test-no-aslr") => { + let cnt = run_self(&arg0); + if cnt != 1 { + eprintln!("FAIL: {} most likely ASLR", arg0); + std::process::exit(1); + } + println!("PASS: {} does no ASLR", arg0); + } + Some(s) if s.eq("--test-aslr") => { + let cnt = run_self(&arg0); + if cnt != NUM_RUNS { + eprintln!("FAIL: {} most likely no ASLR", arg0); + std::process::exit(1); + } + println!("PASS: {} does ASLR", arg0); + } + Some(_) | None => { + println!("Usage: {} --test-no-aslr | --test-aslr", arg0); + std::process::exit(1); + } + } +} From b5809b027262cb9404519862ccbe06a13cae408b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 15 Jun 2020 12:12:22 -0400 Subject: [PATCH 17/34] Update src/librustc_typeck/check/cast.rs Co-authored-by: lzutao --- src/librustc_typeck/check/cast.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index bea5e0e996658..fa10851abd4f6 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -755,7 +755,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { self.span, |err| { err.build(&format!( - "Cast `enum` implementing `Drop` `{}` to integer `{}`", + "cannot cast enum `{}` into integer `{}` because it implements `Drop`", self.expr_ty, self.cast_ty )) .emit(); From 10c8d2afb8b90e03e2d1563df021146150338c45 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 15 Jun 2020 19:12:14 +0200 Subject: [PATCH 18/34] add FIXME to EnumTagInfo --- src/librustc_codegen_llvm/debuginfo/metadata.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 01f630a31a18b..b7e7489cba0ab 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -1637,6 +1637,9 @@ impl VariantMemberDescriptionFactory<'ll, 'tcx> { } } +// FIXME: terminology here should be aligned with `abi::TagEncoding`. +// `OptimizedTag` is `TagEncoding::Niche`, `RegularTag` is `TagEncoding::Direct`. +// `NoTag` should be removed; users should use `Option` instead. #[derive(Copy, Clone)] enum EnumTagInfo<'ll> { RegularTag { tag_field: Field, tag_type_metadata: &'ll DIType }, From e0975b9b0150118d376ea19908cc9bfdf400bfd5 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Mon, 15 Jun 2020 18:19:54 -0400 Subject: [PATCH 19/34] elaborate, add check for exact bounds --- src/test/codegen/issue-69101-bounds-check.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/test/codegen/issue-69101-bounds-check.rs b/src/test/codegen/issue-69101-bounds-check.rs index cdbe51da03cc2..cf062b6ad7588 100644 --- a/src/test/codegen/issue-69101-bounds-check.rs +++ b/src/test/codegen/issue-69101-bounds-check.rs @@ -2,6 +2,12 @@ // compile-flags: -O #![crate_type = "lib"] +// Make sure no bounds checks are emitted in the loop when upfront slicing +// ensures that the slices are big enough. +// In particular, bounds checks were not always optimized out if the upfront +// check was for a greater len than the loop requires. +// (i.e. `already_sliced_no_bounds_check` was not always optimized even when +// `already_sliced_no_bounds_check_exact` was) // CHECK-LABEL: @already_sliced_no_bounds_check #[no_mangle] pub fn already_sliced_no_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) { @@ -13,7 +19,18 @@ pub fn already_sliced_no_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) { } } -// make sure we're checking for the right thing: there can be a panic if the slice is too small +// CHECK-LABEL: @already_sliced_no_bounds_check_exact +#[no_mangle] +pub fn already_sliced_no_bounds_check_exact(a: &[u8], b: &[u8], c: &mut [u8]) { + // CHECK: slice_index_len_fail + // CHECK-NOT: panic_bounds_check + let _ = (&a[..1024], &b[..1024], &mut c[..1024]); + for i in 0..1024 { + c[i] = a[i] ^ b[i]; + } +} + +// Make sure we're checking for the right thing: there can be a panic if the slice is too small. // CHECK-LABEL: @already_sliced_bounds_check #[no_mangle] pub fn already_sliced_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) { From f3dfe80ee1d13ec923082487e73c6d5d5833eef0 Mon Sep 17 00:00:00 2001 From: oddg Date: Mon, 15 Jun 2020 21:28:50 -0700 Subject: [PATCH 20/34] Adjust error message --- src/test/ui/cenum_impl_drop_cast.rs | 2 +- src/test/ui/cenum_impl_drop_cast.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/cenum_impl_drop_cast.rs b/src/test/ui/cenum_impl_drop_cast.rs index 623460673bfa2..96e3d967e2c61 100644 --- a/src/test/ui/cenum_impl_drop_cast.rs +++ b/src/test/ui/cenum_impl_drop_cast.rs @@ -13,6 +13,6 @@ impl Drop for E { fn main() { let e = E::A; let i = e as u32; - //~^ ERROR Cast `enum` implementing `Drop` `E` to integer `u32` + //~^ ERROR cannot cast enum `E` into integer `u32` because it implements `Drop` //~| WARN this was previously accepted } diff --git a/src/test/ui/cenum_impl_drop_cast.stderr b/src/test/ui/cenum_impl_drop_cast.stderr index 5c8f86ffd72ad..8d847a0c80b16 100644 --- a/src/test/ui/cenum_impl_drop_cast.stderr +++ b/src/test/ui/cenum_impl_drop_cast.stderr @@ -1,4 +1,4 @@ -error: Cast `enum` implementing `Drop` `E` to integer `u32` +error: cannot cast enum `E` into integer `u32` because it implements `Drop` --> $DIR/cenum_impl_drop_cast.rs:15:13 | LL | let i = e as u32; From 1990f9777f137ad7d7a69dfd23425d4337c06358 Mon Sep 17 00:00:00 2001 From: Charles Lew Date: Sat, 13 Jun 2020 13:27:22 +0800 Subject: [PATCH 21/34] Disallow loading crates with non-ascii identifier name. --- src/librustc_metadata/creader.rs | 8 ++++++++ .../rfc-2457/crate_name_nonascii_forbidden-1.rs | 6 ++++++ .../crate_name_nonascii_forbidden-1.stderr | 15 +++++++++++++++ .../rfc-2457/crate_name_nonascii_forbidden-2.rs | 9 +++++++++ .../crate_name_nonascii_forbidden-2.stderr | 15 +++++++++++++++ 5 files changed, 53 insertions(+) create mode 100644 src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs create mode 100644 src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr create mode 100644 src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs create mode 100644 src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 7e902f0ade2ef..c40b76d62a05d 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -452,6 +452,14 @@ impl<'a> CrateLoader<'a> { if dep.is_none() { self.used_extern_options.insert(name); } + if !name.as_str().is_ascii() { + self.sess + .struct_span_err( + span, + &format!("cannot load a crate with a non-ascii name `{}`", name,), + ) + .emit(); + } self.maybe_resolve_crate(name, span, dep_kind, dep).unwrap_or_else(|err| err.report()) } diff --git a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs new file mode 100644 index 0000000000000..3fb1cf9f557b2 --- /dev/null +++ b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs @@ -0,0 +1,6 @@ +#![feature(non_ascii_idents)] + +extern crate ьаг; //~ ERROR cannot load a crate with a non-ascii name `ьаг` +//~| ERROR can't find crate for `ьаг` + +fn main() {} diff --git a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr new file mode 100644 index 0000000000000..1e424237fd238 --- /dev/null +++ b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr @@ -0,0 +1,15 @@ +error: cannot load a crate with a non-ascii name `ьаг` + --> $DIR/crate_name_nonascii_forbidden-1.rs:3:1 + | +LL | extern crate ьаг; + | ^^^^^^^^^^^^^^^^^ + +error[E0463]: can't find crate for `ьаг` + --> $DIR/crate_name_nonascii_forbidden-1.rs:3:1 + | +LL | extern crate ьаг; + | ^^^^^^^^^^^^^^^^^ can't find crate + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0463`. diff --git a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs new file mode 100644 index 0000000000000..e1acdbff06189 --- /dev/null +++ b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs @@ -0,0 +1,9 @@ +// compile-flags:--extern му_сгате +// edition:2018 +#![feature(non_ascii_idents)] + +use му_сгате::baz; //~ ERROR cannot load a crate with a non-ascii name `му_сгате` + //~| can't find crate for `му_сгате` + + +fn main() {} diff --git a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr new file mode 100644 index 0000000000000..c06405ebb37ec --- /dev/null +++ b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr @@ -0,0 +1,15 @@ +error: cannot load a crate with a non-ascii name `му_сгате` + --> $DIR/crate_name_nonascii_forbidden-2.rs:5:5 + | +LL | use му_сгате::baz; + | ^^^^^^^^ + +error[E0463]: can't find crate for `му_сгате` + --> $DIR/crate_name_nonascii_forbidden-2.rs:5:5 + | +LL | use му_сгате::baz; + | ^^^^^^^^ can't find crate + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0463`. From 4506a358ca4be0b3f7a1f320a677168d964ca9f7 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 16 Jun 2020 17:36:04 +0000 Subject: [PATCH 22/34] add header for rust specific feature --- src/rustllvm/PassWrapper.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 7586dd91ab68b..47c03069182a5 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -424,8 +424,7 @@ extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef TM) { printf("Available features for this target:\n"); for (auto &Feature : FeatTable) printf(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc); - printf("\n"); - // Rust specific target features + printf("Rust-specific features:\n"); printf(" %-*s - %s.\n", MaxFeatLen, "crt-static", "Enables libraries with C Run-time Libraries(CRT) to be statically linked"); printf("\n"); From 9f50f84ef106c7f521d1322ec39562610339f74d Mon Sep 17 00:00:00 2001 From: root Date: Tue, 16 Jun 2020 18:14:32 +0000 Subject: [PATCH 23/34] break long line for formatting --- src/rustllvm/PassWrapper.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 47c03069182a5..16c2ac3322787 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -425,7 +425,11 @@ extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef TM) { for (auto &Feature : FeatTable) printf(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc); printf("Rust-specific features:\n"); - printf(" %-*s - %s.\n", MaxFeatLen, "crt-static", "Enables libraries with C Run-time Libraries(CRT) to be statically linked"); + printf(" %-*s - %s.\n", + MaxFeatLen, + "crt-static", + "Enables libraries with C Run-time Libraries(CRT) to be statically linked" + ); printf("\n"); printf("Use +feature to enable a feature, or -feature to disable it.\n" From 457acbd5a80153fc06bca12663405c175fd9453f Mon Sep 17 00:00:00 2001 From: root Date: Tue, 16 Jun 2020 18:53:30 +0000 Subject: [PATCH 24/34] trim whitespace --- src/rustllvm/PassWrapper.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 16c2ac3322787..28caf61a0197e 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -425,9 +425,9 @@ extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef TM) { for (auto &Feature : FeatTable) printf(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc); printf("Rust-specific features:\n"); - printf(" %-*s - %s.\n", - MaxFeatLen, - "crt-static", + printf(" %-*s - %s.\n", + MaxFeatLen, + "crt-static", "Enables libraries with C Run-time Libraries(CRT) to be statically linked" ); printf("\n"); From caffb28ece818ce87f1c7573992cae4210544015 Mon Sep 17 00:00:00 2001 From: asrar Date: Wed, 17 Jun 2020 10:31:46 +0530 Subject: [PATCH 25/34] add blank line bw sections Separate target features from rust ones with a blank line Co-authored-by: Josh Stone --- src/rustllvm/PassWrapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 28caf61a0197e..323bd26c698a3 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -424,7 +424,7 @@ extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef TM) { printf("Available features for this target:\n"); for (auto &Feature : FeatTable) printf(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc); - printf("Rust-specific features:\n"); + printf("\nRust-specific features:\n"); printf(" %-*s - %s.\n", MaxFeatLen, "crt-static", From 6351850d8fc89c8150d6503ab6dc8524650e359d Mon Sep 17 00:00:00 2001 From: erikdesjardins Date: Wed, 17 Jun 2020 13:10:49 -0400 Subject: [PATCH 26/34] ignore-debug: debug assertions in slice indexing prevent the optimization --- src/test/codegen/issue-69101-bounds-check.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/codegen/issue-69101-bounds-check.rs b/src/test/codegen/issue-69101-bounds-check.rs index cf062b6ad7588..8ade583b57127 100644 --- a/src/test/codegen/issue-69101-bounds-check.rs +++ b/src/test/codegen/issue-69101-bounds-check.rs @@ -1,5 +1,6 @@ // no-system-llvm // compile-flags: -O +// ignore-debug: the debug assertions get in the way #![crate_type = "lib"] // Make sure no bounds checks are emitted in the loop when upfront slicing From a7c2cf8f510788040c4a8a721582a3533d0bf35a Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 17 Jun 2020 16:30:27 -0700 Subject: [PATCH 27/34] Reduce pointer casts in Box::into_boxed_slice We only need to cast the pointer once to change `Box` to an array `Box<[T; 1]>`, then we can let unsized coercion return `Box<[T]>`. --- src/liballoc/boxed.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 22c344323a2ed..ab0dde0ada660 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -248,7 +248,7 @@ impl Box { #[unstable(feature = "box_into_boxed_slice", issue = "71582")] pub fn into_boxed_slice(boxed: Box) -> Box<[T]> { // *mut T and *mut [T; 1] have the same size and alignment - unsafe { Box::from_raw(Box::into_raw(boxed) as *mut [T; 1] as *mut [T]) } + unsafe { Box::from_raw(Box::into_raw(boxed) as *mut [T; 1]) } } } From d134870bd4bedefaeb07c88a8d24a520bce639cf Mon Sep 17 00:00:00 2001 From: qy3u <65523321+qy3u@users.noreply.github.com> Date: Thu, 18 Jun 2020 10:13:35 +0800 Subject: [PATCH 28/34] Document format correction --- src/libstd/sys/unix/ext/fs.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index 732cd677a1859..e4d714936047e 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -242,7 +242,8 @@ pub trait PermissionsExt { /// let permissions = metadata.permissions(); /// /// println!("permissions: {:o}", permissions.mode()); - /// Ok(()) } + /// Ok(()) + /// } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn mode(&self) -> u32; @@ -262,7 +263,8 @@ pub trait PermissionsExt { /// /// permissions.set_mode(0o644); // Read/write for owner and read for others. /// assert_eq!(permissions.mode(), 0o644); - /// Ok(()) } + /// Ok(()) + /// } /// ``` #[stable(feature = "fs_ext", since = "1.1.0")] fn set_mode(&mut self, mode: u32); From abb5800dd5b05a1b0b3e1c840866389f05548ed5 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 8 Jun 2020 09:09:21 -0700 Subject: [PATCH 29/34] Ensure std benchmarks get tested. --- src/liballoc/Cargo.toml | 1 + src/libcore/Cargo.toml | 1 + src/libstd/Cargo.toml | 5 +++++ 3 files changed, 7 insertions(+) diff --git a/src/liballoc/Cargo.toml b/src/liballoc/Cargo.toml index d1119f7b7c0a7..914195f015b5a 100644 --- a/src/liballoc/Cargo.toml +++ b/src/liballoc/Cargo.toml @@ -25,6 +25,7 @@ path = "../liballoc/tests/lib.rs" [[bench]] name = "collectionsbenches" path = "../liballoc/benches/lib.rs" +test = true [[bench]] name = "vec_deque_append_bench" diff --git a/src/libcore/Cargo.toml b/src/libcore/Cargo.toml index ac07ffb14febd..42c555cafac86 100644 --- a/src/libcore/Cargo.toml +++ b/src/libcore/Cargo.toml @@ -19,6 +19,7 @@ path = "../libcore/tests/lib.rs" [[bench]] name = "corebenches" path = "../libcore/benches/lib.rs" +test = true [dev-dependencies] rand = "0.7" diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 83029a8642097..490afb5a0438f 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -74,3 +74,8 @@ std_detect_dlsym_getauxval = [] threads = 125 # Maximum heap size heap_size = 0x8000000 + +[[bench]] +name = "stdbenches" +path = "benches/lib.rs" +test = true From 8aecafe8e8c375168baac42f7fdc038048089e8f Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Fri, 19 Jun 2020 00:33:24 +0800 Subject: [PATCH 30/34] Fix liballoc doc spelling --- src/liballoc/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 06462fd96d9a9..13dfb8b332d49 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1639,7 +1639,7 @@ impl Vec { } } -// This code generalises `extend_with_{element,default}`. +// This code generalizes `extend_with_{element,default}`. trait ExtendWith { fn next(&mut self) -> T; fn last(self) -> T; From ec8ff1cc242a447e9bef6ba908ce1fdd233a0367 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Fri, 19 Jun 2020 00:34:20 +0800 Subject: [PATCH 31/34] Liballoc clean up macro_rules style --- src/liballoc/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 13dfb8b332d49..31cadbd84bfc5 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1837,7 +1837,7 @@ unsafe trait IsZero { } macro_rules! impl_is_zero { - ($t: ty, $is_zero: expr) => { + ($t:ty, $is_zero:expr) => { unsafe impl IsZero for $t { #[inline] fn is_zero(&self) -> bool { From 111c2d27f501ad935daa2ba22001dceb92113a0e Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Fri, 19 Jun 2020 00:34:49 +0800 Subject: [PATCH 32/34] Rearrange liballoc __impl_slice_eq1 --- src/liballoc/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 31cadbd84bfc5..f16cac05ea039 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2362,9 +2362,9 @@ macro_rules! __impl_slice_eq1 { __impl_slice_eq1! { [] Vec, Vec, } __impl_slice_eq1! { [] Vec, &[B], } __impl_slice_eq1! { [] Vec, &mut [B], } +__impl_slice_eq1! { [] Cow<'_, [A]>, Vec, A: Clone } __impl_slice_eq1! { [] Cow<'_, [A]>, &[B], A: Clone } __impl_slice_eq1! { [] Cow<'_, [A]>, &mut [B], A: Clone } -__impl_slice_eq1! { [] Cow<'_, [A]>, Vec, A: Clone } __impl_slice_eq1! { [const N: usize] Vec, [B; N], [B; N]: LengthAtMost32 } __impl_slice_eq1! { [const N: usize] Vec, &[B; N], [B; N]: LengthAtMost32 } From 5a9ff052b4879e4ef6748c2f85563a7db0548c0b Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 18 Jun 2020 14:45:19 -0700 Subject: [PATCH 33/34] Disable core benches on wasm (benches not supported). --- src/libcore/benches/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libcore/benches/lib.rs b/src/libcore/benches/lib.rs index 570fc4ab93390..de4ef7949f344 100644 --- a/src/libcore/benches/lib.rs +++ b/src/libcore/benches/lib.rs @@ -1,3 +1,5 @@ +// wasm32 does not support benches (no time). +#![cfg(not(target_arch = "wasm32"))] #![feature(flt2dec)] #![feature(test)] From 35a2915bf3f24edbbee2d6a9c8f2318304b99df3 Mon Sep 17 00:00:00 2001 From: Benjamin Saunders Date: Thu, 18 Jun 2020 18:52:26 -0700 Subject: [PATCH 34/34] Remove now-redundant branch --- src/libstd/f32.rs | 6 +----- src/libstd/f64.rs | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index ab468f42b3bd0..7899c422da62d 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -832,11 +832,7 @@ impl f32 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asinh(self) -> f32 { - if self == Self::NEG_INFINITY { - Self::NEG_INFINITY - } else { - (self.abs() + ((self * self) + 1.0).sqrt()).ln().copysign(self) - } + (self.abs() + ((self * self) + 1.0).sqrt()).ln().copysign(self) } /// Inverse hyperbolic cosine function. diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index c033198f021c2..c663c5ffc9beb 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -834,11 +834,7 @@ impl f64 { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn asinh(self) -> f64 { - if self == Self::NEG_INFINITY { - Self::NEG_INFINITY - } else { - (self.abs() + ((self * self) + 1.0).sqrt()).ln().copysign(self) - } + (self.abs() + ((self * self) + 1.0).sqrt()).ln().copysign(self) } /// Inverse hyperbolic cosine function.