From dee3d27d9d69aa66429cec5fb8ca7cdd46ab6019 Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Sun, 23 Jun 2019 14:19:18 -0400 Subject: [PATCH 01/22] allow clippy::unreadable_literal in unicode tables Also modifies the generation script to emit 2018 edition paths. --- src/libcore/unicode/tables.rs | 2 +- src/libcore/unicode/unicode.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/unicode/tables.rs b/src/libcore/unicode/tables.rs index 758cdb0b7cfba..2659ba61e0ccb 100644 --- a/src/libcore/unicode/tables.rs +++ b/src/libcore/unicode/tables.rs @@ -1,6 +1,6 @@ // NOTE: The following code was generated by "./unicode.py", do not edit directly -#![allow(missing_docs, non_upper_case_globals, non_snake_case)] +#![allow(missing_docs, non_upper_case_globals, non_snake_case, clippy::unreadable_literal)] use crate::unicode::version::UnicodeVersion; use crate::unicode::bool_trie::{BoolTrie, SmallBoolTrie}; diff --git a/src/libcore/unicode/unicode.py b/src/libcore/unicode/unicode.py index a0539cd9ca9b6..5389d1cf80383 100755 --- a/src/libcore/unicode/unicode.py +++ b/src/libcore/unicode/unicode.py @@ -79,10 +79,10 @@ class UnicodeFiles(object): PREAMBLE = """\ // NOTE: The following code was generated by "./unicode.py", do not edit directly -#![allow(missing_docs, non_upper_case_globals, non_snake_case)] +#![allow(missing_docs, non_upper_case_globals, non_snake_case, clippy::unreadable_literal)] -use unicode::version::UnicodeVersion; -use unicode::bool_trie::{{BoolTrie, SmallBoolTrie}}; +use crate::unicode::version::UnicodeVersion; +use crate::unicode::bool_trie::{{BoolTrie, SmallBoolTrie}}; """.format(year=datetime.datetime.now().year) # Mapping taken from Table 12 from: From 8c050fc805e601783765d0a58b2dbe3d948b6cd6 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 Jul 2019 20:01:29 +0300 Subject: [PATCH 02/22] rustc: compute `ty::layout::Niche`'s `available` on the fly. --- src/librustc/ty/layout.rs | 72 +++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 29 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 4ed52a1e96638..bf48b9ead05d7 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -2225,24 +2225,50 @@ where struct Niche { offset: Size, scalar: Scalar, - available: u128, } impl Niche { - fn reserve<'tcx>( - &self, - cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, - count: u128, - ) -> Option<(u128, Scalar)> { - if count > self.available { - return None; - } + fn available(&self, cx: &C) -> u128 { + let Scalar { value, valid_range: ref v } = self.scalar; + let bits = value.size(cx).bits(); + assert!(bits <= 128); + let max_value = !0u128 >> (128 - bits); + + // Find out how many values are outside the valid range. + let niche = v.end().wrapping_add(1)..*v.start(); + niche.end.wrapping_sub(niche.start) & max_value + } + + fn reserve(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> { + assert!(count > 0); + let Scalar { value, valid_range: ref v } = self.scalar; let bits = value.size(cx).bits(); assert!(bits <= 128); let max_value = !0u128 >> (128 - bits); + + if count > max_value { + return None; + } + + // Compute the range of invalid values being reserved. let start = v.end().wrapping_add(1) & max_value; let end = v.end().wrapping_add(count) & max_value; + + // If the `end` of our range is inside the valid range, + // then we ran out of invalid values. + // FIXME(eddyb) abstract this with a wraparound range type. + let valid_range_contains = |x| { + if v.start() <= v.end() { + *v.start() <= x && x <= *v.end() + } else { + *v.start() <= x || x <= *v.end() + } + }; + if valid_range_contains(end) { + return None; + } + Some((start, Scalar { value, valid_range: *v.start()..=end })) } } @@ -2253,25 +2279,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // FIXME(eddyb) traverse already optimized enums. fn find_niche(&self, layout: TyLayout<'tcx>) -> Result, LayoutError<'tcx>> { let scalar_niche = |scalar: &Scalar, offset| { - let Scalar { value, valid_range: ref v } = *scalar; - - let bits = value.size(self).bits(); - assert!(bits <= 128); - let max_value = !0u128 >> (128 - bits); - - // Find out how many values are outside the valid range. - let available = if v.start() <= v.end() { - v.start() + (max_value - v.end()) + let niche = Niche { offset, scalar: scalar.clone() }; + if niche.available(self) > 0 { + Some(niche) } else { - v.start() - v.end() - 1 - }; - - // Give up if there is no niche value available. - if available == 0 { - return None; + None } - - Some(Niche { offset, scalar: scalar.clone(), available }) }; // Locals variables which live across yields are stored @@ -2293,7 +2306,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { ) .chain(iter::once((a, Size::ZERO))) .filter_map(|(scalar, offset)| scalar_niche(scalar, offset)) - .max_by_key(|niche| niche.available); + .max_by_key(|niche| niche.available(self)); return Ok(niche); } Abi::Vector { ref element, .. } => { @@ -2325,8 +2338,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let mut available = 0; for i in 0..layout.fields.count() { if let Some(mut c) = self.find_niche(layout.field(self, i)?)? { - if c.available > available { - available = c.available; + let c_available = c.available(self); + if c_available > available { + available = c_available; c.offset += layout.fields.offset(i); niche = Some(c); } From dfbf4646f74a120fe736599faa81643a78aaf029 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 12 Jul 2019 11:55:29 +0300 Subject: [PATCH 03/22] rustc_target: move abi::Niche from rustc::ty::layout. --- src/librustc/ty/layout.rs | 51 ---------------------------------- src/librustc_target/abi/mod.rs | 51 ++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index bf48b9ead05d7..a60842f568165 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -2222,57 +2222,6 @@ where } } -struct Niche { - offset: Size, - scalar: Scalar, -} - -impl Niche { - fn available(&self, cx: &C) -> u128 { - let Scalar { value, valid_range: ref v } = self.scalar; - let bits = value.size(cx).bits(); - assert!(bits <= 128); - let max_value = !0u128 >> (128 - bits); - - // Find out how many values are outside the valid range. - let niche = v.end().wrapping_add(1)..*v.start(); - niche.end.wrapping_sub(niche.start) & max_value - } - - fn reserve(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> { - assert!(count > 0); - - let Scalar { value, valid_range: ref v } = self.scalar; - let bits = value.size(cx).bits(); - assert!(bits <= 128); - let max_value = !0u128 >> (128 - bits); - - if count > max_value { - return None; - } - - // Compute the range of invalid values being reserved. - let start = v.end().wrapping_add(1) & max_value; - let end = v.end().wrapping_add(count) & max_value; - - // If the `end` of our range is inside the valid range, - // then we ran out of invalid values. - // FIXME(eddyb) abstract this with a wraparound range type. - let valid_range_contains = |x| { - if v.start() <= v.end() { - *v.start() <= x && x <= *v.end() - } else { - *v.start() <= x || x <= *v.end() - } - }; - if valid_range_contains(end) { - return None; - } - - Some((start, Scalar { value, valid_range: *v.start()..=end })) - } -} - impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { /// Find the offset of a niche leaf field, starting from /// the given type and recursing through aggregates. diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 01586e92aeb1c..b70ea916f0ba0 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -878,6 +878,57 @@ pub enum DiscriminantKind { }, } +pub struct Niche { + pub offset: Size, + pub scalar: Scalar, +} + +impl Niche { + pub fn available(&self, cx: &C) -> u128 { + let Scalar { value, valid_range: ref v } = self.scalar; + let bits = value.size(cx).bits(); + assert!(bits <= 128); + let max_value = !0u128 >> (128 - bits); + + // Find out how many values are outside the valid range. + let niche = v.end().wrapping_add(1)..*v.start(); + niche.end.wrapping_sub(niche.start) & max_value + } + + pub fn reserve(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> { + assert!(count > 0); + + let Scalar { value, valid_range: ref v } = self.scalar; + let bits = value.size(cx).bits(); + assert!(bits <= 128); + let max_value = !0u128 >> (128 - bits); + + if count > max_value { + return None; + } + + // Compute the range of invalid values being reserved. + let start = v.end().wrapping_add(1) & max_value; + let end = v.end().wrapping_add(count) & max_value; + + // If the `end` of our range is inside the valid range, + // then we ran out of invalid values. + // FIXME(eddyb) abstract this with a wraparound range type. + let valid_range_contains = |x| { + if v.start() <= v.end() { + *v.start() <= x && x <= *v.end() + } else { + *v.start() <= x || x <= *v.end() + } + }; + if valid_range_contains(end) { + return None; + } + + Some((start, Scalar { value, valid_range: *v.start()..=end })) + } +} + #[derive(PartialEq, Eq, Hash, Debug)] pub struct LayoutDetails { pub variants: Variants, From 88eced596199548a7653aaf835cda0a93fec36fd Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 15 Jul 2019 18:21:01 +0300 Subject: [PATCH 04/22] rustc: precompute the largest Niche and store it in LayoutDetails. --- src/librustc/ty/layout.rs | 190 +++++++++++++++++---------------- src/librustc_target/abi/mod.rs | 20 ++++ 2 files changed, 120 insertions(+), 90 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index a60842f568165..3b4b814c92a90 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -246,6 +246,14 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let align = a.value.align(dl).max(b_align).max(dl.aggregate_align); let b_offset = a.value.size(dl).align_to(b_align.abi); let size = (b_offset + b.value.size(dl)).align_to(align.abi); + + // HACK(nox): We iter on `b` and then `a` because `max_by_key` + // returns the last maximum. + let largest_niche = Niche::from_scalar(dl, b_offset, b.clone()) + .into_iter() + .chain(Niche::from_scalar(dl, Size::ZERO, a.clone())) + .max_by_key(|niche| niche.available(dl)); + LayoutDetails { variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldPlacement::Arbitrary { @@ -253,6 +261,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { memory_index: vec![0, 1] }, abi: Abi::ScalarPair(a, b), + largest_niche, align, size } @@ -321,6 +330,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let mut offset = Size::ZERO; + let mut largest_niche = None; + let mut largest_niche_available = 0; if let StructKind::Prefixed(prefix_size, prefix_align) = kind { let prefix_align = if packed { @@ -355,6 +366,15 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { debug!("univariant offset: {:?} field: {:#?}", offset, field); offsets[i as usize] = offset; + if let Some(mut niche) = field.largest_niche.clone() { + let available = niche.available(dl); + if available > largest_niche_available { + largest_niche_available = available; + niche.offset += offset; + largest_niche = Some(niche); + } + } + offset = offset.checked_add(field.size, dl) .ok_or(LayoutError::SizeOverflow(ty))?; } @@ -466,6 +486,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { memory_index }, abi, + largest_niche, align, size }) @@ -525,6 +546,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldPlacement::Union(0), abi: Abi::Uninhabited, + largest_niche: None, align: dl.i8_align, size: Size::ZERO }) @@ -583,6 +605,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { Abi::Aggregate { sized: true } }; + let largest_niche = if count != 0 { + element.largest_niche.clone() + } else { + None + }; + tcx.intern_layout(LayoutDetails { variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldPlacement::Array { @@ -590,6 +618,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { count }, abi, + largest_niche, align: element.align, size }) @@ -603,6 +632,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { count: 0 }, abi: Abi::Aggregate { sized: false }, + largest_niche: None, align: element.align, size: Size::ZERO }) @@ -615,6 +645,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { count: 0 }, abi: Abi::Aggregate { sized: false }, + largest_niche: None, align: dl.i8_align, size: Size::ZERO }) @@ -683,6 +714,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { element: scalar, count }, + largest_niche: element.largest_niche.clone(), size, align, }) @@ -768,6 +800,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { variants: Variants::Single { index }, fields: FieldPlacement::Union(variants[index].len()), abi, + largest_niche: None, align, size: size.align_to(align.abi) })); @@ -829,14 +862,38 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // `#[rustc_layout_scalar_valid_range(n)]` // attribute to widen the range of anything as that would probably // result in UB somewhere + // FIXME(eddyb) the asserts are probably not needed, + // as larger validity ranges would result in missed + // optimizations, *not* wrongly assuming the inner + // value is valid. e.g. unions enlarge validity ranges, + // because the values may be uninitialized. if let Bound::Included(start) = start { + // FIXME(eddyb) this might be incorrect - it doesn't + // account for wrap-around (end < start) ranges. assert!(*scalar.valid_range.start() <= start); scalar.valid_range = start..=*scalar.valid_range.end(); } if let Bound::Included(end) = end { + // FIXME(eddyb) this might be incorrect - it doesn't + // account for wrap-around (end < start) ranges. assert!(*scalar.valid_range.end() >= end); scalar.valid_range = *scalar.valid_range.start()..=end; } + + // Update `largest_niche` if we have introduced a larger niche. + let niche = Niche::from_scalar(dl, Size::ZERO, scalar.clone()); + if let Some(niche) = niche { + match &st.largest_niche { + Some(largest_niche) => { + // Replace the existing niche even if they're equal, + // because this one is at a lower offset. + if largest_niche.available(dl) <= niche.available(dl) { + st.largest_niche = Some(niche); + } + } + None => st.largest_niche = Some(niche), + } + } } _ => assert!( start == Bound::Unbounded && end == Bound::Unbounded, @@ -845,6 +902,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { st, ), } + return Ok(tcx.intern_layout(st)); } @@ -886,8 +944,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let count = ( niche_variants.end().as_u32() - niche_variants.start().as_u32() + 1 ) as u128; + // FIXME(#62691) use the largest niche across all fields, + // not just the first one. for (field_index, &field) in variants[i].iter().enumerate() { - let niche = match self.find_niche(field)? { + let niche = match &field.largest_niche { Some(niche) => niche, _ => continue, }; @@ -937,6 +997,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { abi = Abi::Uninhabited; } + + let largest_niche = + Niche::from_scalar(dl, offset, niche_scalar.clone()); + return Ok(tcx.intern_layout(LayoutDetails { variants: Variants::Multiple { discr: niche_scalar, @@ -953,6 +1017,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { memory_index: vec![0] }, abi, + largest_niche, size, align, })); @@ -1164,6 +1229,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { abi = Abi::Uninhabited; } + let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag.clone()); + tcx.intern_layout(LayoutDetails { variants: Variants::Multiple { discr: tag, @@ -1175,6 +1242,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { offsets: vec![Size::ZERO], memory_index: vec![0] }, + largest_niche, abi, align, size @@ -1332,16 +1400,31 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // 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.prefix_tys(def_id, tcx).count(); - let promoted_tys = - ineligible_locals.iter().map(|local| subst_field(info.field_tys[local])); - let prefix_tys = substs.prefix_tys(def_id, tcx) - .chain(iter::once(substs.discr_ty(tcx))) - .chain(promoted_tys); - let prefix = self.univariant_uninterned( + // FIXME(eddyb) set the correct vaidity range for the discriminant. + let discr_layout = self.layout_of(substs.discr_ty(tcx))?; + let discr = match &discr_layout.abi { + Abi::Scalar(s) => s.clone(), + _ => bug!(), + }; + // FIXME(eddyb) wrap each promoted type in `MaybeUninit` so that they + // don't poison the `largest_niche` or `abi` fields of `prefix`. + let promoted_layouts = ineligible_locals.iter() + .map(|local| subst_field(info.field_tys[local])) + .map(|ty| self.layout_of(ty)); + let prefix_layouts = substs.prefix_tys(def_id, tcx) + .map(|ty| self.layout_of(ty)) + .chain(iter::once(Ok(discr_layout))) + .chain(promoted_layouts) + .collect::, _>>()?; + let mut prefix = self.univariant_uninterned( ty, - &prefix_tys.map(|ty| self.layout_of(ty)).collect::, _>>()?, + &prefix_layouts, &ReprOptions::default(), - StructKind::AlwaysSized)?; + StructKind::AlwaysSized, + )?; + // FIXME(eddyb) need `MaybeUninit` around promoted types (see above). + prefix.largest_niche = None; + let (prefix_size, prefix_align) = (prefix.size, prefix.align); // Split the prefix layout into the "outer" fields (upvars and @@ -1463,10 +1546,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } else { Abi::Aggregate { sized: true } }; - let discr = match &self.layout_of(substs.discr_ty(tcx))?.abi { - Abi::Scalar(s) => s.clone(), - _ => bug!(), - }; let layout = tcx.intern_layout(LayoutDetails { variants: Variants::Multiple { @@ -1477,6 +1556,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { }, fields: outer_fields, abi, + largest_niche: prefix.largest_niche, size, align, }); @@ -1950,6 +2030,7 @@ where variants: Variants::Single { index: variant_index }, fields: FieldPlacement::Union(fields), abi: Abi::Uninhabited, + largest_niche: None, align: tcx.data_layout.i8_align, size: Size::ZERO }) @@ -2222,83 +2303,6 @@ where } } -impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { - /// Find the offset of a niche leaf field, starting from - /// the given type and recursing through aggregates. - // FIXME(eddyb) traverse already optimized enums. - fn find_niche(&self, layout: TyLayout<'tcx>) -> Result, LayoutError<'tcx>> { - let scalar_niche = |scalar: &Scalar, offset| { - let niche = Niche { offset, scalar: scalar.clone() }; - if niche.available(self) > 0 { - Some(niche) - } else { - None - } - }; - - // Locals variables which live across yields are stored - // in the generator type as fields. These may be uninitialized - // so we don't look for niches there. - if let ty::Generator(..) = layout.ty.sty { - return Ok(None); - } - - match layout.abi { - Abi::Scalar(ref scalar) => { - return Ok(scalar_niche(scalar, Size::ZERO)); - } - Abi::ScalarPair(ref a, ref b) => { - // HACK(nox): We iter on `b` and then `a` because `max_by_key` - // returns the last maximum. - let niche = iter::once( - (b, a.value.size(self).align_to(b.value.align(self).abi)) - ) - .chain(iter::once((a, Size::ZERO))) - .filter_map(|(scalar, offset)| scalar_niche(scalar, offset)) - .max_by_key(|niche| niche.available(self)); - return Ok(niche); - } - Abi::Vector { ref element, .. } => { - return Ok(scalar_niche(element, Size::ZERO)); - } - _ => {} - } - - // Perhaps one of the fields is non-zero, let's recurse and find out. - if let FieldPlacement::Union(_) = layout.fields { - // Only Rust enums have safe-to-inspect fields - // (a discriminant), other unions are unsafe. - if let Variants::Single { .. } = layout.variants { - return Ok(None); - } - } - if let FieldPlacement::Array { count: original_64_bit_count, .. } = layout.fields { - // rust-lang/rust#57038: avoid ICE within FieldPlacement::count when count too big - if original_64_bit_count > usize::max_value() as u64 { - return Err(LayoutError::SizeOverflow(layout.ty)); - } - if layout.fields.count() > 0 { - return self.find_niche(layout.field(self, 0)?); - } else { - return Ok(None); - } - } - let mut niche = None; - let mut available = 0; - for i in 0..layout.fields.count() { - if let Some(mut c) = self.find_niche(layout.field(self, i)?)? { - let c_available = c.available(self); - if c_available > available { - available = c_available; - c.offset += layout.fields.offset(i); - niche = Some(c); - } - } - } - Ok(niche) - } -} - impl<'a> HashStable> for Variants { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, @@ -2419,10 +2423,16 @@ impl<'a> HashStable> for Scalar { } } +impl_stable_hash_for!(struct crate::ty::layout::Niche { + offset, + scalar +}); + impl_stable_hash_for!(struct crate::ty::layout::LayoutDetails { variants, fields, abi, + largest_niche, size, align }); diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index b70ea916f0ba0..4a4c6799c005e 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -878,12 +878,25 @@ pub enum DiscriminantKind { }, } +#[derive(Clone, PartialEq, Eq, Hash, Debug)] pub struct Niche { pub offset: Size, pub scalar: Scalar, } impl Niche { + pub fn from_scalar(cx: &C, offset: Size, scalar: Scalar) -> Option { + let niche = Niche { + offset, + scalar, + }; + if niche.available(cx) > 0 { + Some(niche) + } else { + None + } + } + pub fn available(&self, cx: &C) -> u128 { let Scalar { value, valid_range: ref v } = self.scalar; let bits = value.size(cx).bits(); @@ -934,18 +947,25 @@ pub struct LayoutDetails { pub variants: Variants, pub fields: FieldPlacement, pub abi: Abi, + + /// The leaf scalar with the largest number of invalid values + /// (i.e. outside of its `valid_range`), if it exists. + pub largest_niche: Option, + pub align: AbiAndPrefAlign, pub size: Size } impl LayoutDetails { pub fn scalar(cx: &C, scalar: Scalar) -> Self { + let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar.clone()); let size = scalar.value.size(cx); let align = scalar.value.align(cx); LayoutDetails { variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldPlacement::Union(0), abi: Abi::Scalar(scalar), + largest_niche, size, align, } From d1aca3aea5cd7b1a96f27c0d1843ea4132a39232 Mon Sep 17 00:00:00 2001 From: Brad Gibson Date: Mon, 1 Apr 2019 12:08:19 -0700 Subject: [PATCH 05/22] renamed `inner_deref` feature's `deref*()` methods `as_deref*()` as per discussion https://github.com/rust-lang/rust/issues/50264 --- src/libcore/option.rs | 15 +- src/libcore/result.rs | 63 ++++-- src/libcore/tests/option.rs | 30 ++- src/libcore/tests/result.rs | 185 +++++++++++++++--- .../option-as_deref.rs | 6 + .../option-as_deref.stderr | 12 ++ .../option-as_deref_mut.rs | 6 + .../option-as_deref_mut.stderr | 12 ++ .../option-deref.rs | 6 - .../option-deref.stderr | 12 -- .../result-as_deref.rs | 6 + .../result-as_deref.stderr | 12 ++ .../result-as_deref_err.rs | 6 + .../result-as_deref_err.stderr | 12 ++ .../result-as_deref_mut.rs | 6 + .../result-as_deref_mut.stderr | 12 ++ .../result-as_deref_mut_err.rs | 6 + .../result-as_deref_mut_err.stderr | 12 ++ .../result-as_deref_mut_ok.rs | 6 + .../result-as_deref_mut_ok.stderr | 12 ++ .../result-as_deref_ok.rs | 6 + .../result-as_deref_ok.stderr | 12 ++ .../result-deref-err.rs | 6 - .../result-deref-err.stderr | 12 -- .../result-deref-ok.rs | 6 - .../result-deref-ok.stderr | 12 -- .../result-deref.rs | 6 - .../result-deref.stderr | 12 -- 28 files changed, 383 insertions(+), 126 deletions(-) create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr delete mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/option-deref.rs delete mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/option-deref.stderr create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.rs create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.rs create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.rs create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.rs create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.rs create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.stderr create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.rs create mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.stderr delete mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.rs delete mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.stderr delete mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-ok.rs delete mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-ok.stderr delete mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result-deref.rs delete mode 100644 src/test/ui/issues/issue-50264-inner-deref-trait/result-deref.stderr diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 33d6afdc975ee..afc64c54bba87 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1104,17 +1104,28 @@ impl Option { #[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] impl Option { - /// Converts from `&Option` to `Option<&T::Target>`. + /// Converts from `Option` (or `&Option`) to `Option<&T::Target>`. /// /// Leaves the original Option in-place, creating a new one with a reference /// to the original one, additionally coercing the contents via [`Deref`]. /// /// [`Deref`]: ../../std/ops/trait.Deref.html - pub fn deref(&self) -> Option<&T::Target> { + pub fn as_deref(&self) -> Option<&T::Target> { self.as_ref().map(|t| t.deref()) } } +#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] +impl Option { + /// Converts from `Option` (or `&mut Option`) to `Option<&mut T::Target>`. + /// + /// Leaves the original `Option` in-place, creating a new one containing a mutable reference to + /// the inner type's `Deref::Target` type. + pub fn as_deref_mut(&mut self) -> Option<&mut T::Target> { + self.as_mut().map(|t| t.deref_mut()) + } +} + impl Option> { /// Transposes an `Option` of a [`Result`] into a [`Result`] of an `Option`. /// diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 3a38b66ad0150..167e14eae4310 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -981,24 +981,22 @@ impl Result { #[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] impl Result { - /// Converts from `&Result` to `Result<&T::Target, &E>`. + /// Converts from `Result` (or `&Result`) to `Result<&T::Target, &E>`. /// - /// Leaves the original Result in-place, creating a new one with a reference - /// to the original one, additionally coercing the `Ok` arm of the Result via - /// `Deref`. - pub fn deref_ok(&self) -> Result<&T::Target, &E> { + /// Leaves the original `Result` in-place, creating a new one containing a reference to the + /// `Ok` type's `Deref::Target` type. + pub fn as_deref_ok(&self) -> Result<&T::Target, &E> { self.as_ref().map(|t| t.deref()) } } #[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] impl Result { - /// Converts from `&Result` to `Result<&T, &E::Target>`. + /// Converts from `Result` (or `&Result`) to `Result<&T, &E::Target>`. /// - /// Leaves the original Result in-place, creating a new one with a reference - /// to the original one, additionally coercing the `Err` arm of the Result via - /// `Deref`. - pub fn deref_err(&self) -> Result<&T, &E::Target> + /// Leaves the original `Result` in-place, creating a new one containing a reference to the + /// `Err` type's `Deref::Target` type. + pub fn as_deref_err(&self) -> Result<&T, &E::Target> { self.as_ref().map_err(|e| e.deref()) } @@ -1006,17 +1004,52 @@ impl Result { #[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] impl Result { - /// Converts from `&Result` to `Result<&T::Target, &E::Target>`. + /// Converts from `Result` (or `&Result`) to `Result<&T::Target, &E::Target>`. /// - /// Leaves the original Result in-place, creating a new one with a reference - /// to the original one, additionally coercing both the `Ok` and `Err` arms - /// of the Result via `Deref`. - pub fn deref(&self) -> Result<&T::Target, &E::Target> + /// Leaves the original `Result` in-place, creating a new one containing a reference to both + /// the `Ok` and `Err` types' `Deref::Target` types. + pub fn as_deref(&self) -> Result<&T::Target, &E::Target> { self.as_ref().map(|t| t.deref()).map_err(|e| e.deref()) } } +#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] +impl Result { + /// Converts from `Result` (or `&mut Result`) to `Result<&mut T::Target, &mut E>`. + /// + /// Leaves the original `Result` in-place, creating a new one containing a mutable reference to + /// the `Ok` type's `Deref::Target` type. + pub fn as_deref_mut_ok(&mut self) -> Result<&mut T::Target, &mut E> { + self.as_mut().map(|t| t.deref_mut()) + } +} + +#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] +impl Result { + /// Converts from `Result` (or `&mut Result`) to `Result<&mut T, &mut E::Target>`. + /// + /// Leaves the original `Result` in-place, creating a new one containing a mutable reference to + /// the `Err` type's `Deref::Target` type. + pub fn as_deref_mut_err(&mut self) -> Result<&mut T, &mut E::Target> + { + self.as_mut().map_err(|e| e.deref_mut()) + } +} + +#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] +impl Result { + /// Converts from `Result` (or `&mut Result`) to + /// `Result<&mut T::Target, &mut E::Target>`. + /// + /// Leaves the original `Result` in-place, creating a new one containing a mutable reference to + /// both the `Ok` and `Err` types' `Deref::Target` types. + pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E::Target> + { + self.as_mut().map(|t| t.deref_mut()).map_err(|e| e.deref_mut()) + } +} + impl Result, E> { /// Transposes a `Result` of an `Option` into an `Option` of a `Result`. /// diff --git a/src/libcore/tests/option.rs b/src/libcore/tests/option.rs index b059b134868d9..ff43fc49f71e3 100644 --- a/src/libcore/tests/option.rs +++ b/src/libcore/tests/option.rs @@ -1,6 +1,8 @@ use core::option::*; use core::mem; use core::clone::Clone; +use core::array::FixedSizeArray; +use core::ops::DerefMut; #[test] fn test_get_ptr() { @@ -310,20 +312,38 @@ fn test_try() { } #[test] -fn test_option_deref() { +fn test_option_as_deref() { // Some: &Option::Some(T) -> Option<&T::Deref::Target>::Some(&*T) let ref_option = &Some(&42); - assert_eq!(ref_option.deref(), Some(&42)); + assert_eq!(ref_option.as_deref(), Some(&42)); let ref_option = &Some(String::from("a result")); - assert_eq!(ref_option.deref(), Some("a result")); + assert_eq!(ref_option.as_deref(), Some("a result")); let ref_option = &Some(vec![1, 2, 3, 4, 5]); - assert_eq!(ref_option.deref(), Some(&[1, 2, 3, 4, 5][..])); + assert_eq!(ref_option.as_deref(), Some([1, 2, 3, 4, 5].as_slice())); // None: &Option>::None -> None let ref_option: &Option<&i32> = &None; - assert_eq!(ref_option.deref(), None); + assert_eq!(ref_option.as_deref(), None); +} + +#[test] +fn test_option_as_deref_mut() { + // Some: &mut Option::Some(T) -> Option<&mut T::Deref::Target>::Some(&mut *T) + let mut val = 42; + let ref_option = &mut Some(&mut val); + assert_eq!(ref_option.as_deref_mut(), Some(&mut 42)); + + let ref_option = &mut Some(String::from("a result")); + assert_eq!(ref_option.as_deref_mut(), Some(String::from("a result").deref_mut())); + + let ref_option = &mut Some(vec![1, 2, 3, 4, 5]); + assert_eq!(ref_option.as_deref_mut(), Some([1, 2, 3, 4, 5].as_mut_slice())); + + // None: &mut Option>::None -> None + let ref_option: &mut Option<&mut i32> = &mut None; + assert_eq!(ref_option.as_deref_mut(), None); } #[test] diff --git a/src/libcore/tests/result.rs b/src/libcore/tests/result.rs index 1fab07526a07f..163f8d0ab3797 100644 --- a/src/libcore/tests/result.rs +++ b/src/libcore/tests/result.rs @@ -1,4 +1,6 @@ use core::option::*; +use core::array::FixedSizeArray; +use core::ops::DerefMut; fn op1() -> Result { Ok(666) } fn op2() -> Result { Err("sadface") } @@ -225,94 +227,213 @@ fn test_try() { } #[test] -fn test_result_deref() { - // &Result::Ok(T).deref_ok() -> +fn test_result_as_deref() { + // &Result::Ok(T).as_deref_ok() -> // Result<&T::Deref::Target, &E>::Ok(&*T) let ref_ok = &Result::Ok::<&i32, u8>(&42); let expected_result = Result::Ok::<&i32, &u8>(&42); - assert_eq!(ref_ok.deref_ok(), expected_result); + assert_eq!(ref_ok.as_deref_ok(), expected_result); let ref_ok = &Result::Ok::(String::from("a result")); let expected_result = Result::Ok::<&str, &u32>("a result"); - assert_eq!(ref_ok.deref_ok(), expected_result); + assert_eq!(ref_ok.as_deref_ok(), expected_result); let ref_ok = &Result::Ok::, u32>(vec![1, 2, 3, 4, 5]); - let expected_result = Result::Ok::<&[i32], &u32>(&[1, 2, 3, 4, 5][..]); - assert_eq!(ref_ok.deref_ok(), expected_result); + let expected_result = Result::Ok::<&[i32], &u32>([1, 2, 3, 4, 5].as_slice()); + assert_eq!(ref_ok.as_deref_ok(), expected_result); - // &Result::Ok(T).deref() -> + // &Result::Ok(T).as_deref() -> // Result<&T::Deref::Target, &E::Deref::Target>::Ok(&*T) let ref_ok = &Result::Ok::<&i32, &u8>(&42); let expected_result = Result::Ok::<&i32, &u8>(&42); - assert_eq!(ref_ok.deref(), expected_result); + assert_eq!(ref_ok.as_deref(), expected_result); let ref_ok = &Result::Ok::(String::from("a result")); let expected_result = Result::Ok::<&str, &u32>("a result"); - assert_eq!(ref_ok.deref(), expected_result); + assert_eq!(ref_ok.as_deref(), expected_result); let ref_ok = &Result::Ok::, &u32>(vec![1, 2, 3, 4, 5]); - let expected_result = Result::Ok::<&[i32], &u32>(&[1, 2, 3, 4, 5][..]); - assert_eq!(ref_ok.deref(), expected_result); + let expected_result = Result::Ok::<&[i32], &u32>([1, 2, 3, 4, 5].as_slice()); + assert_eq!(ref_ok.as_deref(), expected_result); - // &Result::Err(T).deref_err() -> + // &Result::Err(T).as_deref_err() -> // Result<&T, &E::Deref::Target>::Err(&*E) let ref_err = &Result::Err::(&41); let expected_result = Result::Err::<&u8, &i32>(&41); - assert_eq!(ref_err.deref_err(), expected_result); + assert_eq!(ref_err.as_deref_err(), expected_result); let ref_err = &Result::Err::(String::from("an error")); let expected_result = Result::Err::<&u32, &str>("an error"); - assert_eq!(ref_err.deref_err(), expected_result); + assert_eq!(ref_err.as_deref_err(), expected_result); let ref_err = &Result::Err::>(vec![5, 4, 3, 2, 1]); - let expected_result = Result::Err::<&u32, &[i32]>(&[5, 4, 3, 2, 1][..]); - assert_eq!(ref_err.deref_err(), expected_result); + let expected_result = Result::Err::<&u32, &[i32]>([5, 4, 3, 2, 1].as_slice()); + assert_eq!(ref_err.as_deref_err(), expected_result); - // &Result::Err(T).deref_err() -> + // &Result::Err(T).as_deref_err() -> // Result<&T, &E::Deref::Target>::Err(&*E) let ref_err = &Result::Err::<&u8, &i32>(&41); let expected_result = Result::Err::<&u8, &i32>(&41); - assert_eq!(ref_err.deref(), expected_result); + assert_eq!(ref_err.as_deref(), expected_result); let ref_err = &Result::Err::<&u32, String>(String::from("an error")); let expected_result = Result::Err::<&u32, &str>("an error"); - assert_eq!(ref_err.deref(), expected_result); + assert_eq!(ref_err.as_deref(), expected_result); let ref_err = &Result::Err::<&u32, Vec>(vec![5, 4, 3, 2, 1]); - let expected_result = Result::Err::<&u32, &[i32]>(&[5, 4, 3, 2, 1][..]); - assert_eq!(ref_err.deref(), expected_result); + let expected_result = Result::Err::<&u32, &[i32]>([5, 4, 3, 2, 1].as_slice()); + assert_eq!(ref_err.as_deref(), expected_result); - // The following cases test calling deref_* with the wrong variant (i.e. - // `deref_ok()` with a `Result::Err()`, or `deref_err()` with a `Result::Ok()`. - // While unusual, these cases are supported to ensure that an `inner_deref` + // The following cases test calling `as_deref_*` with the wrong variant (i.e. + // `as_deref_ok()` with a `Result::Err()`, or `as_deref_err()` with a `Result::Ok()`. + // While uncommon, these cases are supported to ensure that an `as_deref_*` // call can still be made even when one of the Result types does not implement // `Deref` (for example, std::io::Error). - // &Result::Ok(T).deref_err() -> + // &Result::Ok(T).as_deref_err() -> // Result<&T, &E::Deref::Target>::Ok(&T) let ref_ok = &Result::Ok::(42); let expected_result = Result::Ok::<&i32, &u8>(&42); - assert_eq!(ref_ok.deref_err(), expected_result); + assert_eq!(ref_ok.as_deref_err(), expected_result); let ref_ok = &Result::Ok::<&str, &u32>("a result"); let expected_result = Result::Ok::<&&str, &u32>(&"a result"); - assert_eq!(ref_ok.deref_err(), expected_result); + assert_eq!(ref_ok.as_deref_err(), expected_result); let ref_ok = &Result::Ok::<[i32; 5], &u32>([1, 2, 3, 4, 5]); let expected_result = Result::Ok::<&[i32; 5], &u32>(&[1, 2, 3, 4, 5]); - assert_eq!(ref_ok.deref_err(), expected_result); + assert_eq!(ref_ok.as_deref_err(), expected_result); - // &Result::Err(E).deref_ok() -> + // &Result::Err(E).as_deref_ok() -> // Result<&T::Deref::Target, &E>::Err(&E) let ref_err = &Result::Err::<&u8, i32>(41); let expected_result = Result::Err::<&u8, &i32>(&41); - assert_eq!(ref_err.deref_ok(), expected_result); + assert_eq!(ref_err.as_deref_ok(), expected_result); let ref_err = &Result::Err::<&u32, &str>("an error"); let expected_result = Result::Err::<&u32, &&str>(&"an error"); - assert_eq!(ref_err.deref_ok(), expected_result); + assert_eq!(ref_err.as_deref_ok(), expected_result); let ref_err = &Result::Err::<&u32, [i32; 5]>([5, 4, 3, 2, 1]); let expected_result = Result::Err::<&u32, &[i32; 5]>(&[5, 4, 3, 2, 1]); - assert_eq!(ref_err.deref_ok(), expected_result); + assert_eq!(ref_err.as_deref_ok(), expected_result); +} + +#[test] +fn test_result_as_deref_mut() { + // &mut Result::Ok(T).as_deref_mut_ok() -> + // Result<&mut T::Deref::Target, &mut E>::Ok(&mut *T) + let mut val = 42; + let mut expected_val = 42; + let mut_ok = &mut Result::Ok::<&mut i32, u8>(&mut val); + let expected_result = Result::Ok::<&mut i32, &mut u8>(&mut expected_val); + assert_eq!(mut_ok.as_deref_mut_ok(), expected_result); + + let mut expected_string = String::from("a result"); + let mut_ok = &mut Result::Ok::(expected_string.clone()); + let expected_result = Result::Ok::<&mut str, &mut u32>(expected_string.deref_mut()); + assert_eq!(mut_ok.as_deref_mut_ok(), expected_result); + + let mut expected_vec = vec![1, 2, 3, 4, 5]; + let mut_ok = &mut Result::Ok::, u32>(expected_vec.clone()); + let expected_result = Result::Ok::<&mut [i32], &mut u32>(expected_vec.as_mut_slice()); + assert_eq!(mut_ok.as_deref_mut_ok(), expected_result); + + // &mut Result::Ok(T).as_deref_mut() -> + // Result<&mut T::Deref::Target, &mut E::Deref::Target>::Ok(&mut *T) + let mut val = 42; + let mut expected_val = 42; + let mut_ok = &mut Result::Ok::<&mut i32, &mut u8>(&mut val); + let expected_result = Result::Ok::<&mut i32, &mut u8>(&mut expected_val); + assert_eq!(mut_ok.as_deref_mut(), expected_result); + + let mut expected_string = String::from("a result"); + let mut_ok = &mut Result::Ok::(expected_string.clone()); + let expected_result = Result::Ok::<&mut str, &mut u32>(expected_string.deref_mut()); + assert_eq!(mut_ok.as_deref_mut(), expected_result); + + let mut expected_vec = vec![1, 2, 3, 4, 5]; + let mut_ok = &mut Result::Ok::, &mut u32>(expected_vec.clone()); + let expected_result = Result::Ok::<&mut [i32], &mut u32>(expected_vec.as_mut_slice()); + assert_eq!(mut_ok.as_deref_mut(), expected_result); + + // &mut Result::Err(T).as_deref_mut_err() -> + // Result<&mut T, &mut E::Deref::Target>::Err(&mut *E) + let mut val = 41; + let mut expected_val = 41; + let mut_err = &mut Result::Err::(&mut val); + let expected_result = Result::Err::<&mut u8, &mut i32>(&mut expected_val); + assert_eq!(mut_err.as_deref_mut_err(), expected_result); + + let mut expected_string = String::from("an error"); + let mut_err = &mut Result::Err::(expected_string.clone()); + let expected_result = Result::Err::<&mut u32, &mut str>(expected_string.deref_mut()); + assert_eq!(mut_err.as_deref_mut_err(), expected_result); + + let mut expected_vec = vec![5, 4, 3, 2, 1]; + let mut_err = &mut Result::Err::>(expected_vec.clone()); + let expected_result = Result::Err::<&mut u32, &mut [i32]>(expected_vec.as_mut_slice()); + assert_eq!(mut_err.as_deref_mut_err(), expected_result); + + // &mut Result::Err(T).as_deref_mut_err() -> + // Result<&mut T, &mut E::Deref::Target>::Err(&mut *E) + let mut val = 41; + let mut expected_val = 41; + let mut_err = &mut Result::Err::<&mut u8, &mut i32>(&mut val); + let expected_result = Result::Err::<&mut u8, &mut i32>(&mut expected_val); + assert_eq!(mut_err.as_deref_mut(), expected_result); + + let mut expected_string = String::from("an error"); + let mut_err = &mut Result::Err::<&mut u32, String>(expected_string.clone()); + let expected_result = Result::Err::<&mut u32, &mut str>(expected_string.as_mut_str()); + assert_eq!(mut_err.as_deref_mut(), expected_result); + + let mut expected_vec = vec![5, 4, 3, 2, 1]; + let mut_err = &mut Result::Err::<&mut u32, Vec>(expected_vec.clone()); + let expected_result = Result::Err::<&mut u32, &mut [i32]>(expected_vec.as_mut_slice()); + assert_eq!(mut_err.as_deref_mut(), expected_result); + + // The following cases test calling `as_deref_mut_*` with the wrong variant (i.e. + // `as_deref_mut_ok()` with a `Result::Err()`, or `as_deref_mut_err()` with a `Result::Ok()`. + // While uncommon, these cases are supported to ensure that an `as_deref_mut_*` + // call can still be made even when one of the Result types does not implement + // `Deref` (for example, std::io::Error). + + // &mut Result::Ok(T).as_deref_mut_err() -> + // Result<&mut T, &mut E::Deref::Target>::Ok(&mut T) + let mut expected_val = 42; + let mut_ok = &mut Result::Ok::(expected_val.clone()); + let expected_result = Result::Ok::<&mut i32, &mut u8>(&mut expected_val); + assert_eq!(mut_ok.as_deref_mut_err(), expected_result); + + let string = String::from("a result"); + let expected_string = string.clone(); + let mut ref_str = expected_string.as_ref(); + let mut_ok = &mut Result::Ok::<&str, &mut u32>(string.as_str()); + let expected_result = Result::Ok::<&mut &str, &mut u32>(&mut ref_str); + assert_eq!(mut_ok.as_deref_mut_err(), expected_result); + + let mut expected_arr = [1, 2, 3, 4, 5]; + let mut_ok = &mut Result::Ok::<[i32; 5], &mut u32>(expected_arr.clone()); + let expected_result = Result::Ok::<&mut [i32; 5], &mut u32>(&mut expected_arr); + assert_eq!(mut_ok.as_deref_mut_err(), expected_result); + + // &mut Result::Err(E).as_deref_mut_ok() -> + // Result<&mut T::Deref::Target, &mut E>::Err(&mut E) + let mut expected_val = 41; + let mut_err = &mut Result::Err::<&mut u8, i32>(expected_val.clone()); + let expected_result = Result::Err::<&mut u8, &mut i32>(&mut expected_val); + assert_eq!(mut_err.as_deref_mut_ok(), expected_result); + + let string = String::from("an error"); + let expected_string = string.clone(); + let mut ref_str = expected_string.as_ref(); + let mut_err = &mut Result::Err::<&mut u32, &str>(string.as_str()); + let expected_result = Result::Err::<&mut u32, &mut &str>(&mut ref_str); + assert_eq!(mut_err.as_deref_mut_ok(), expected_result); + + let mut expected_arr = [5, 4, 3, 2, 1]; + let mut_err = &mut Result::Err::<&mut u32, [i32; 5]>(expected_arr.clone()); + let expected_result = Result::Err::<&mut u32, &mut [i32; 5]>(&mut expected_arr); + assert_eq!(mut_err.as_deref_mut_ok(), expected_result); } diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs new file mode 100644 index 0000000000000..67feb3ff6aec3 --- /dev/null +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs @@ -0,0 +1,6 @@ +#![feature(inner_deref)] + +fn main() { + let _result = &Some(42).as_deref(); +//~^ ERROR no method named `as_deref` found for type `std::option::Option<{integer}>` +} diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr new file mode 100644 index 0000000000000..54efcfd045ae9 --- /dev/null +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr @@ -0,0 +1,12 @@ +error[E0599]: no method named `as_deref` found for type `std::option::Option<{integer}>` in the current scope + --> $DIR/option-as_deref.rs:4:29 + | +LL | let _result = &Some(42).as_deref(); + | ^^^^^^^^ help: did you mean: `as_ref` + | + = note: the method `as_deref` exists but the following trait bounds were not satisfied: + `{integer} : std::ops::Deref` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs new file mode 100644 index 0000000000000..56aead8d0e00d --- /dev/null +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs @@ -0,0 +1,6 @@ +#![feature(inner_deref)] + +fn main() { + let _result = &mut Some(42).as_deref_mut(); +//~^ ERROR no method named `as_deref_mut` found for type `std::option::Option<{integer}>` +} diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr new file mode 100644 index 0000000000000..2c3a18be67c8f --- /dev/null +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr @@ -0,0 +1,12 @@ +error[E0599]: no method named `as_deref_mut` found for type `std::option::Option<{integer}>` in the current scope + --> $DIR/option-as_deref_mut.rs:4:33 + | +LL | let _result = &mut Some(42).as_deref_mut(); + | ^^^^^^^^^^^^ + | + = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied: + `{integer} : std::ops::DerefMut` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-deref.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/option-deref.rs deleted file mode 100644 index f82eafcaffa9a..0000000000000 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-deref.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![feature(inner_deref)] - -fn main() { - let _result = &Some(42).deref(); -//~^ ERROR no method named `deref` found for type `std::option::Option<{integer}>` -} diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-deref.stderr deleted file mode 100644 index e916b7d7d3447..0000000000000 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-deref.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0599]: no method named `deref` found for type `std::option::Option<{integer}>` in the current scope - --> $DIR/option-deref.rs:4:29 - | -LL | let _result = &Some(42).deref(); - | ^^^^^ - | - = note: the method `deref` exists but the following trait bounds were not satisfied: - `{integer} : std::ops::Deref` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.rs new file mode 100644 index 0000000000000..1d5eabd6170b7 --- /dev/null +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.rs @@ -0,0 +1,6 @@ +#![feature(inner_deref)] + +fn main() { + let _result = &Ok(42).as_deref(); +//~^ ERROR no method named `as_deref` found +} diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr new file mode 100644 index 0000000000000..6007f29e566e5 --- /dev/null +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr @@ -0,0 +1,12 @@ +error[E0599]: no method named `as_deref` found for type `std::result::Result<{integer}, _>` in the current scope + --> $DIR/result-as_deref.rs:4:27 + | +LL | let _result = &Ok(42).as_deref(); + | ^^^^^^^^ help: did you mean: `as_ref` + | + = note: the method `as_deref` exists but the following trait bounds were not satisfied: + `{integer} : std::ops::Deref` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.rs new file mode 100644 index 0000000000000..104aa3bcadff2 --- /dev/null +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.rs @@ -0,0 +1,6 @@ +#![feature(inner_deref)] + +fn main() { + let _result = &Err(41).as_deref_err(); +//~^ ERROR no method named `as_deref_err` found +} diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr new file mode 100644 index 0000000000000..2e918b6835b5a --- /dev/null +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr @@ -0,0 +1,12 @@ +error[E0599]: no method named `as_deref_err` found for type `std::result::Result<_, {integer}>` in the current scope + --> $DIR/result-as_deref_err.rs:4:28 + | +LL | let _result = &Err(41).as_deref_err(); + | ^^^^^^^^^^^^ help: did you mean: `as_deref_ok` + | + = note: the method `as_deref_err` exists but the following trait bounds were not satisfied: + `{integer} : std::ops::Deref` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.rs new file mode 100644 index 0000000000000..c897ab3531f0e --- /dev/null +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.rs @@ -0,0 +1,6 @@ +#![feature(inner_deref)] + +fn main() { + let _result = &mut Ok(42).as_deref_mut(); +//~^ ERROR no method named `as_deref_mut` found +} diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr new file mode 100644 index 0000000000000..3d10cad201ec4 --- /dev/null +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr @@ -0,0 +1,12 @@ +error[E0599]: no method named `as_deref_mut` found for type `std::result::Result<{integer}, _>` in the current scope + --> $DIR/result-as_deref_mut.rs:4:31 + | +LL | let _result = &mut Ok(42).as_deref_mut(); + | ^^^^^^^^^^^^ help: did you mean: `as_deref_err` + | + = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied: + `{integer} : std::ops::DerefMut` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.rs new file mode 100644 index 0000000000000..b7849ecb6d242 --- /dev/null +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.rs @@ -0,0 +1,6 @@ +#![feature(inner_deref)] + +fn main() { + let _result = &mut Err(41).as_deref_mut_err(); +//~^ ERROR no method named `as_deref_mut_err` found +} diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr new file mode 100644 index 0000000000000..99f941d1bedad --- /dev/null +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr @@ -0,0 +1,12 @@ +error[E0599]: no method named `as_deref_mut_err` found for type `std::result::Result<_, {integer}>` in the current scope + --> $DIR/result-as_deref_mut_err.rs:4:32 + | +LL | let _result = &mut Err(41).as_deref_mut_err(); + | ^^^^^^^^^^^^^^^^ help: did you mean: `as_deref_mut_ok` + | + = note: the method `as_deref_mut_err` exists but the following trait bounds were not satisfied: + `{integer} : std::ops::DerefMut` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.rs new file mode 100644 index 0000000000000..54b695a0865f1 --- /dev/null +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.rs @@ -0,0 +1,6 @@ +#![feature(inner_deref)] + +fn main() { + let _result = &mut Ok(42).as_deref_mut_ok(); +//~^ ERROR no method named `as_deref_mut_ok` found +} diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.stderr new file mode 100644 index 0000000000000..6d2b019541ad0 --- /dev/null +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.stderr @@ -0,0 +1,12 @@ +error[E0599]: no method named `as_deref_mut_ok` found for type `std::result::Result<{integer}, _>` in the current scope + --> $DIR/result-as_deref_mut_ok.rs:4:31 + | +LL | let _result = &mut Ok(42).as_deref_mut_ok(); + | ^^^^^^^^^^^^^^^ help: did you mean: `as_deref_mut_err` + | + = note: the method `as_deref_mut_ok` exists but the following trait bounds were not satisfied: + `{integer} : std::ops::DerefMut` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.rs new file mode 100644 index 0000000000000..ebb0500e8190f --- /dev/null +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.rs @@ -0,0 +1,6 @@ +#![feature(inner_deref)] + +fn main() { + let _result = &Ok(42).as_deref_ok(); +//~^ ERROR no method named `as_deref_ok` found +} diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.stderr new file mode 100644 index 0000000000000..5800bd37f9f7f --- /dev/null +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.stderr @@ -0,0 +1,12 @@ +error[E0599]: no method named `as_deref_ok` found for type `std::result::Result<{integer}, _>` in the current scope + --> $DIR/result-as_deref_ok.rs:4:27 + | +LL | let _result = &Ok(42).as_deref_ok(); + | ^^^^^^^^^^^ help: did you mean: `as_deref_err` + | + = note: the method `as_deref_ok` exists but the following trait bounds were not satisfied: + `{integer} : std::ops::Deref` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.rs deleted file mode 100644 index 4be2000f058a5..0000000000000 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![feature(inner_deref)] - -fn main() { - let _result = &Err(41).deref_err(); -//~^ ERROR no method named `deref_err` found -} diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.stderr deleted file mode 100644 index 333036127eadb..0000000000000 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-err.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0599]: no method named `deref_err` found for type `std::result::Result<_, {integer}>` in the current scope - --> $DIR/result-deref-err.rs:4:28 - | -LL | let _result = &Err(41).deref_err(); - | ^^^^^^^^^ help: there is a method with a similar name: `deref_ok` - | - = note: the method `deref_err` exists but the following trait bounds were not satisfied: - `{integer} : std::ops::Deref` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-ok.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-ok.rs deleted file mode 100644 index a706cde734805..0000000000000 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-ok.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![feature(inner_deref)] - -fn main() { - let _result = &Ok(42).deref_ok(); -//~^ ERROR no method named `deref_ok` found -} diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-ok.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-ok.stderr deleted file mode 100644 index 593705123540c..0000000000000 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref-ok.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0599]: no method named `deref_ok` found for type `std::result::Result<{integer}, _>` in the current scope - --> $DIR/result-deref-ok.rs:4:27 - | -LL | let _result = &Ok(42).deref_ok(); - | ^^^^^^^^ - | - = note: the method `deref_ok` exists but the following trait bounds were not satisfied: - `{integer} : std::ops::Deref` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref.rs deleted file mode 100644 index 43a68e37dd0c3..0000000000000 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref.rs +++ /dev/null @@ -1,6 +0,0 @@ -#![feature(inner_deref)] - -fn main() { - let _result = &Ok(42).deref(); -//~^ ERROR no method named `deref` found -} diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref.stderr deleted file mode 100644 index 05baa7907fae0..0000000000000 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-deref.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0599]: no method named `deref` found for type `std::result::Result<{integer}, _>` in the current scope - --> $DIR/result-deref.rs:4:27 - | -LL | let _result = &Ok(42).deref(); - | ^^^^^ - | - = note: the method `deref` exists but the following trait bounds were not satisfied: - `{integer} : std::ops::Deref` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0599`. From 6a9d749b924b703227355a6c1d9878543fb05b73 Mon Sep 17 00:00:00 2001 From: Brad Gibson Date: Mon, 1 Apr 2019 20:08:27 -0700 Subject: [PATCH 06/22] fixed breaking changes --- src/librustdoc/html/render.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 3cd520fd4b50b..5db82b23614fc 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1173,7 +1173,7 @@ themePicker.onblur = handleThemeButtonsBlur; title: "Index of crates", css_class: "mod", root_path: "./", - static_root_path: cx.shared.static_root_path.deref(), + static_root_path: cx.shared.static_root_path.as_deref(), description: "List of crates", keywords: BASIC_KEYWORDS, resource_suffix: &cx.shared.resource_suffix, @@ -1513,7 +1513,7 @@ impl<'a> SourceCollector<'a> { title: &title, css_class: "source", root_path: &root_path, - static_root_path: self.scx.static_root_path.deref(), + static_root_path: self.scx.static_root_path.as_deref(), description: &desc, keywords: BASIC_KEYWORDS, resource_suffix: &self.scx.resource_suffix, @@ -2110,7 +2110,7 @@ impl Context { title: "List of all items in this crate", css_class: "mod", root_path: "../", - static_root_path: self.shared.static_root_path.deref(), + static_root_path: self.shared.static_root_path.as_deref(), description: "List of all items in this crate", keywords: BASIC_KEYWORDS, resource_suffix: &self.shared.resource_suffix, @@ -2195,7 +2195,7 @@ impl Context { let page = layout::Page { css_class: tyname, root_path: &self.root_path(), - static_root_path: self.shared.static_root_path.deref(), + static_root_path: self.shared.static_root_path.as_deref(), title: &title, description: &desc, keywords: &keywords, From f2a97210b2388a71fd9e3f8101c496ba51a6a45a Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sat, 6 Jul 2019 02:37:34 +0900 Subject: [PATCH 07/22] Use DerefMut --- src/libcore/option.rs | 2 +- src/libcore/result.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index afc64c54bba87..abc8883d3985f 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -136,7 +136,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::iter::{FromIterator, FusedIterator, TrustedLen}; -use crate::{convert, fmt, hint, mem, ops::{self, Deref}}; +use crate::{convert, fmt, hint, mem, ops::{self, Deref, DerefMut}}; use crate::pin::Pin; // Note that this is not a lang item per se, but it has a hidden dependency on diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 167e14eae4310..cb6bc058730d1 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -232,7 +232,7 @@ use crate::fmt; use crate::iter::{FromIterator, FusedIterator, TrustedLen}; -use crate::ops::{self, Deref}; +use crate::ops::{self, Deref, DerefMut}; /// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]). /// From 59634bc1d43c56683ee752e23ee92e1b256b56e7 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sat, 6 Jul 2019 03:35:19 +0900 Subject: [PATCH 08/22] Replace deref with as_deref --- src/librustc/hir/print.rs | 2 +- src/librustc_typeck/check/expr.rs | 4 ++-- src/librustdoc/html/render.rs | 2 +- .../issue-50264-inner-deref-trait/option-as_deref.stderr | 2 +- .../issue-50264-inner-deref-trait/result-as_deref.stderr | 2 +- .../issue-50264-inner-deref-trait/result-as_deref_err.stderr | 2 +- .../issue-50264-inner-deref-trait/result-as_deref_mut.stderr | 2 +- .../result-as_deref_mut_err.stderr | 2 +- .../result-as_deref_mut_ok.stderr | 2 +- .../issue-50264-inner-deref-trait/result-as_deref_ok.stderr | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 3e571baaa4e51..da4a25e0860b1 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -941,7 +941,7 @@ impl<'a> State<'a> { self.maybe_print_comment(st.span.lo()); match st.node { hir::StmtKind::Local(ref loc) => { - self.print_local(loc.init.deref(), |this| this.print_local_decl(&loc)); + self.print_local(loc.init.as_deref(), |this| this.print_local_decl(&loc)); } hir::StmtKind::Item(item) => { self.ann.nested(self, Nested::Item(item)) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index b02a7c21027d4..7dfc4b82515d1 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -226,7 +226,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.mk_unit() } ExprKind::Break(destination, ref expr_opt) => { - self.check_expr_break(destination, expr_opt.deref(), expr) + self.check_expr_break(destination, expr_opt.as_deref(), expr) } ExprKind::Continue(destination) => { if destination.target_id.is_ok() { @@ -237,7 +237,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } ExprKind::Ret(ref expr_opt) => { - self.check_expr_return(expr_opt.deref(), expr) + self.check_expr_return(expr_opt.as_deref(), expr) } ExprKind::Assign(ref lhs, ref rhs) => { self.check_expr_assign(expr, expected, lhs, rhs) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 5db82b23614fc..6270ed3785905 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2137,7 +2137,7 @@ impl Context { self.shared.fs.write(&final_file, &v)?; // Generating settings page. - let settings = Settings::new(self.shared.static_root_path.deref().unwrap_or("./"), + let settings = Settings::new(self.shared.static_root_path.as_deref().unwrap_or("./"), &self.shared.resource_suffix); page.title = "Rustdoc settings"; page.description = "Settings of Rustdoc"; diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr index 54efcfd045ae9..345f91437b827 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref` found for type `std::option::Option<{in --> $DIR/option-as_deref.rs:4:29 | LL | let _result = &Some(42).as_deref(); - | ^^^^^^^^ help: did you mean: `as_ref` + | ^^^^^^^^ help: there is a method with a similar name: `as_ref` | = note: the method `as_deref` exists but the following trait bounds were not satisfied: `{integer} : std::ops::Deref` diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr index 6007f29e566e5..5e016748770dc 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref` found for type `std::result::Result<{in --> $DIR/result-as_deref.rs:4:27 | LL | let _result = &Ok(42).as_deref(); - | ^^^^^^^^ help: did you mean: `as_ref` + | ^^^^^^^^ help: there is a method with a similar name: `as_ref` | = note: the method `as_deref` exists but the following trait bounds were not satisfied: `{integer} : std::ops::Deref` diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr index 2e918b6835b5a..6dc13da548b12 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref_err` found for type `std::result::Result --> $DIR/result-as_deref_err.rs:4:28 | LL | let _result = &Err(41).as_deref_err(); - | ^^^^^^^^^^^^ help: did you mean: `as_deref_ok` + | ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_ok` | = note: the method `as_deref_err` exists but the following trait bounds were not satisfied: `{integer} : std::ops::Deref` diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr index 3d10cad201ec4..f21e97388b6f4 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref_mut` found for type `std::result::Result --> $DIR/result-as_deref_mut.rs:4:31 | LL | let _result = &mut Ok(42).as_deref_mut(); - | ^^^^^^^^^^^^ help: did you mean: `as_deref_err` + | ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_err` | = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied: `{integer} : std::ops::DerefMut` diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr index 99f941d1bedad..44c0c954eeeca 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref_mut_err` found for type `std::result::Re --> $DIR/result-as_deref_mut_err.rs:4:32 | LL | let _result = &mut Err(41).as_deref_mut_err(); - | ^^^^^^^^^^^^^^^^ help: did you mean: `as_deref_mut_ok` + | ^^^^^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut_ok` | = note: the method `as_deref_mut_err` exists but the following trait bounds were not satisfied: `{integer} : std::ops::DerefMut` diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.stderr index 6d2b019541ad0..b8369c9b82e1a 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_ok.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref_mut_ok` found for type `std::result::Res --> $DIR/result-as_deref_mut_ok.rs:4:31 | LL | let _result = &mut Ok(42).as_deref_mut_ok(); - | ^^^^^^^^^^^^^^^ help: did you mean: `as_deref_mut_err` + | ^^^^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut_err` | = note: the method `as_deref_mut_ok` exists but the following trait bounds were not satisfied: `{integer} : std::ops::DerefMut` diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.stderr index 5800bd37f9f7f..b26705a99e3bc 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_ok.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref_ok` found for type `std::result::Result< --> $DIR/result-as_deref_ok.rs:4:27 | LL | let _result = &Ok(42).as_deref_ok(); - | ^^^^^^^^^^^ help: did you mean: `as_deref_err` + | ^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_err` | = note: the method `as_deref_ok` exists but the following trait bounds were not satisfied: `{integer} : std::ops::Deref` From 3427a14bdf19437c455e54af704e0250ea8aa79b Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 19 Jul 2019 14:21:06 +0200 Subject: [PATCH 09/22] Remove support for -Zlower-128bit-ops It is broken and unused --- src/librustc/middle/lang_items.rs | 28 --- src/librustc/session/config.rs | 4 - src/librustc/ty/context.rs | 36 +--- src/librustc_mir/interpret/intrinsics.rs | 15 +- src/librustc_mir/transform/inline.rs | 7 - src/librustc_mir/transform/lower_128bit.rs | 230 --------------------- src/librustc_mir/transform/mod.rs | 3 - src/librustc_target/spec/mod.rs | 5 - 8 files changed, 3 insertions(+), 325 deletions(-) delete mode 100644 src/librustc_mir/transform/lower_128bit.rs diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index bdd48b3447498..cc09a0b20cfd5 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -367,34 +367,6 @@ language_item_table! { DebugTraitLangItem, "debug_trait", debug_trait, Target::Trait; - // A lang item for each of the 128-bit operators we can optionally lower. - I128AddFnLangItem, "i128_add", i128_add_fn, Target::Fn; - U128AddFnLangItem, "u128_add", u128_add_fn, Target::Fn; - I128SubFnLangItem, "i128_sub", i128_sub_fn, Target::Fn; - U128SubFnLangItem, "u128_sub", u128_sub_fn, Target::Fn; - I128MulFnLangItem, "i128_mul", i128_mul_fn, Target::Fn; - U128MulFnLangItem, "u128_mul", u128_mul_fn, Target::Fn; - I128DivFnLangItem, "i128_div", i128_div_fn, Target::Fn; - U128DivFnLangItem, "u128_div", u128_div_fn, Target::Fn; - I128RemFnLangItem, "i128_rem", i128_rem_fn, Target::Fn; - U128RemFnLangItem, "u128_rem", u128_rem_fn, Target::Fn; - I128ShlFnLangItem, "i128_shl", i128_shl_fn, Target::Fn; - U128ShlFnLangItem, "u128_shl", u128_shl_fn, Target::Fn; - I128ShrFnLangItem, "i128_shr", i128_shr_fn, Target::Fn; - U128ShrFnLangItem, "u128_shr", u128_shr_fn, Target::Fn; - // And overflow versions for the operators that are checkable. - // While MIR calls these Checked*, they return (T,bool), not Option. - I128AddoFnLangItem, "i128_addo", i128_addo_fn, Target::Fn; - U128AddoFnLangItem, "u128_addo", u128_addo_fn, Target::Fn; - I128SuboFnLangItem, "i128_subo", i128_subo_fn, Target::Fn; - U128SuboFnLangItem, "u128_subo", u128_subo_fn, Target::Fn; - I128MuloFnLangItem, "i128_mulo", i128_mulo_fn, Target::Fn; - U128MuloFnLangItem, "u128_mulo", u128_mulo_fn, Target::Fn; - I128ShloFnLangItem, "i128_shlo", i128_shlo_fn, Target::Fn; - U128ShloFnLangItem, "u128_shlo", u128_shlo_fn, Target::Fn; - I128ShroFnLangItem, "i128_shro", i128_shro_fn, Target::Fn; - U128ShroFnLangItem, "u128_shro", u128_shro_fn, Target::Fn; - // Align offset for stride != 1, must not panic. AlignOffsetLangItem, "align_offset", align_offset_fn, Target::Fn; diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index db8e2f64e3066..54d28b32accda 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1406,10 +1406,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, saturating_float_casts: bool = (false, parse_bool, [TRACKED], "make float->int casts UB-free: numbers outside the integer type's range are clipped to \ the max/min integer respectively, and NaN is mapped to 0"), - lower_128bit_ops: Option = (None, parse_opt_bool, [TRACKED], - "rewrite operators on i128 and u128 into lang item calls (typically provided \ - by compiler-builtins) so codegen doesn't need to support them, - overriding the default for the current target"), human_readable_cgu_names: bool = (false, parse_bool, [TRACKED], "generate human-readable, predictable names for codegen units"), dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED], diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 16fc46b66d9f4..9746f46dbaccc 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -21,7 +21,7 @@ use crate::middle::cstore::EncodedMetadata; use crate::middle::lang_items; use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault}; use crate::middle::stability; -use crate::mir::{self, Body, interpret, ProjectionKind}; +use crate::mir::{Body, interpret, ProjectionKind}; use crate::mir::interpret::{ConstValue, Allocation, Scalar}; use crate::ty::subst::{Kind, InternalSubsts, SubstsRef, Subst}; use crate::ty::ReprOptions; @@ -1297,40 +1297,6 @@ impl<'tcx> TyCtxt<'tcx> { self.get_lang_items(LOCAL_CRATE) } - /// Due to missing llvm support for lowering 128 bit math to software emulation - /// (on some targets), the lowering can be done in MIR. - /// - /// This function only exists until said support is implemented. - pub fn is_binop_lang_item(&self, def_id: DefId) -> Option<(mir::BinOp, bool)> { - let items = self.lang_items(); - let def_id = Some(def_id); - if items.i128_add_fn() == def_id { Some((mir::BinOp::Add, false)) } - else if items.u128_add_fn() == def_id { Some((mir::BinOp::Add, false)) } - else if items.i128_sub_fn() == def_id { Some((mir::BinOp::Sub, false)) } - else if items.u128_sub_fn() == def_id { Some((mir::BinOp::Sub, false)) } - else if items.i128_mul_fn() == def_id { Some((mir::BinOp::Mul, false)) } - else if items.u128_mul_fn() == def_id { Some((mir::BinOp::Mul, false)) } - else if items.i128_div_fn() == def_id { Some((mir::BinOp::Div, false)) } - else if items.u128_div_fn() == def_id { Some((mir::BinOp::Div, false)) } - else if items.i128_rem_fn() == def_id { Some((mir::BinOp::Rem, false)) } - else if items.u128_rem_fn() == def_id { Some((mir::BinOp::Rem, false)) } - else if items.i128_shl_fn() == def_id { Some((mir::BinOp::Shl, false)) } - else if items.u128_shl_fn() == def_id { Some((mir::BinOp::Shl, false)) } - else if items.i128_shr_fn() == def_id { Some((mir::BinOp::Shr, false)) } - else if items.u128_shr_fn() == def_id { Some((mir::BinOp::Shr, false)) } - else if items.i128_addo_fn() == def_id { Some((mir::BinOp::Add, true)) } - else if items.u128_addo_fn() == def_id { Some((mir::BinOp::Add, true)) } - else if items.i128_subo_fn() == def_id { Some((mir::BinOp::Sub, true)) } - else if items.u128_subo_fn() == def_id { Some((mir::BinOp::Sub, true)) } - else if items.i128_mulo_fn() == def_id { Some((mir::BinOp::Mul, true)) } - else if items.u128_mulo_fn() == def_id { Some((mir::BinOp::Mul, true)) } - else if items.i128_shlo_fn() == def_id { Some((mir::BinOp::Shl, true)) } - else if items.u128_shlo_fn() == def_id { Some((mir::BinOp::Shl, true)) } - else if items.i128_shro_fn() == def_id { Some((mir::BinOp::Shr, true)) } - else if items.u128_shro_fn() == def_id { Some((mir::BinOp::Shr, true)) } - else { None } - } - pub fn stability(self) -> &'tcx stability::Index<'tcx> { self.stability_index(LOCAL_CRATE) } diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index cf36c10a614e5..097bc3fabd159 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -230,21 +230,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &mut self, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx, M::PointerTag>], - dest: Option>, + _dest: Option>, ) -> InterpResult<'tcx, bool> { let def_id = instance.def_id(); - // Some fn calls are actually BinOp intrinsics - if let Some((op, oflo)) = self.tcx.is_binop_lang_item(def_id) { - let dest = dest.expect("128 lowerings can't diverge"); - let l = self.read_immediate(args[0])?; - let r = self.read_immediate(args[1])?; - if oflo { - self.binop_with_overflow(op, l, r, dest)?; - } else { - self.binop_ignore_overflow(op, l, r, dest)?; - } - return Ok(true); - } else if Some(def_id) == self.tcx.lang_items().panic_fn() { + if Some(def_id) == self.tcx.lang_items().panic_fn() { assert!(args.len() == 1); // &(&'static str, &'static str, u32, u32) let place = self.deref_operand(args[0])?; diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 04ee14f5f59be..61685f445c8db 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -232,13 +232,6 @@ impl Inliner<'tcx> { return false; } - // Do not inline {u,i}128 lang items, codegen const eval depends - // on detecting calls to these lang items and intercepting them - if tcx.is_binop_lang_item(callsite.callee).is_some() { - debug!(" not inlining 128bit integer lang item"); - return false; - } - let codegen_fn_attrs = tcx.codegen_fn_attrs(callsite.callee); let hinted = match codegen_fn_attrs.inline { diff --git a/src/librustc_mir/transform/lower_128bit.rs b/src/librustc_mir/transform/lower_128bit.rs deleted file mode 100644 index f09a77d486c7e..0000000000000 --- a/src/librustc_mir/transform/lower_128bit.rs +++ /dev/null @@ -1,230 +0,0 @@ -//! Replaces 128-bit operators with lang item calls - -use rustc::hir::def_id::DefId; -use rustc::middle::lang_items::LangItem; -use rustc::mir::*; -use rustc::ty::{self, List, Ty, TyCtxt}; -use rustc_data_structures::indexed_vec::{Idx}; -use crate::transform::{MirPass, MirSource}; - -pub struct Lower128Bit; - -impl MirPass for Lower128Bit { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { - let debugging_override = tcx.sess.opts.debugging_opts.lower_128bit_ops; - let target_default = tcx.sess.host.options.i128_lowering; - if !debugging_override.unwrap_or(target_default) { - return - } - - self.lower_128bit_ops(tcx, body); -} -} - -impl Lower128Bit { - fn lower_128bit_ops<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let mut new_blocks = Vec::new(); - let cur_len = body.basic_blocks().len(); - - let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); - for block in basic_blocks.iter_mut() { - for i in (0..block.statements.len()).rev() { - let (lang_item, rhs_kind) = - if let Some((lang_item, rhs_kind)) = - lower_to(&block.statements[i], local_decls, tcx) - { - (lang_item, rhs_kind) - } else { - continue; - }; - - let rhs_override_ty = rhs_kind.ty(tcx); - let cast_local = - match rhs_override_ty { - None => None, - Some(ty) => { - let local_decl = LocalDecl::new_internal( - ty, block.statements[i].source_info.span); - Some(local_decls.push(local_decl)) - }, - }; - - let storage_dead = cast_local.map(|local| { - Statement { - source_info: block.statements[i].source_info, - kind: StatementKind::StorageDead(local), - } - }); - let after_call = BasicBlockData { - statements: storage_dead.into_iter() - .chain(block.statements.drain((i+1)..)).collect(), - is_cleanup: block.is_cleanup, - terminator: block.terminator.take(), - }; - - let bin_statement = block.statements.pop().unwrap(); - let source_info = bin_statement.source_info; - let (place, lhs, mut rhs) = match bin_statement.kind { - StatementKind::Assign(place, box rvalue) => { - match rvalue { - Rvalue::BinaryOp(_, lhs, rhs) - | Rvalue::CheckedBinaryOp(_, lhs, rhs) => (place, lhs, rhs), - _ => bug!(), - } - } - _ => bug!() - }; - - if let Some(local) = cast_local { - block.statements.push(Statement { - source_info: source_info, - kind: StatementKind::StorageLive(local), - }); - block.statements.push(Statement { - source_info: source_info, - kind: StatementKind::Assign( - Place::from(local), - box Rvalue::Cast( - CastKind::Misc, - rhs, - rhs_override_ty.unwrap())), - }); - rhs = Operand::Move(Place::from(local)); - } - - let call_did = check_lang_item_type( - lang_item, &place, &lhs, &rhs, local_decls, tcx); - - let bb = BasicBlock::new(cur_len + new_blocks.len()); - new_blocks.push(after_call); - - block.terminator = - Some(Terminator { - source_info, - kind: TerminatorKind::Call { - func: Operand::function_handle(tcx, call_did, - List::empty(), source_info.span), - args: vec![lhs, rhs], - destination: Some((place, bb)), - cleanup: None, - from_hir_call: false, - }, - }); - } - } - - basic_blocks.extend(new_blocks); - } -} - -fn check_lang_item_type<'tcx, D>( - lang_item: LangItem, - place: &Place<'tcx>, - lhs: &Operand<'tcx>, - rhs: &Operand<'tcx>, - local_decls: &D, - tcx: TyCtxt<'tcx>, -) -> DefId -where - D: HasLocalDecls<'tcx>, -{ - let did = tcx.require_lang_item(lang_item); - let poly_sig = tcx.fn_sig(did); - let sig = poly_sig.no_bound_vars().unwrap(); - let lhs_ty = lhs.ty(local_decls, tcx); - let rhs_ty = rhs.ty(local_decls, tcx); - let place_ty = place.ty(local_decls, tcx).ty; - let expected = [lhs_ty, rhs_ty, place_ty]; - assert_eq!(sig.inputs_and_output[..], expected, - "lang item `{}`", tcx.def_path_str(did)); - did -} - -fn lower_to<'tcx, D>( - statement: &Statement<'tcx>, - local_decls: &D, - tcx: TyCtxt<'tcx>, -) -> Option<(LangItem, RhsKind)> -where - D: HasLocalDecls<'tcx>, -{ - match statement.kind { - StatementKind::Assign(_, box Rvalue::BinaryOp(bin_op, ref lhs, _)) => { - let ty = lhs.ty(local_decls, tcx); - if let Some(is_signed) = sign_of_128bit(ty) { - return item_for_op(bin_op, is_signed); - } - }, - StatementKind::Assign(_, box Rvalue::CheckedBinaryOp(bin_op, ref lhs, _)) => { - let ty = lhs.ty(local_decls, tcx); - if let Some(is_signed) = sign_of_128bit(ty) { - return item_for_checked_op(bin_op, is_signed); - } - }, - _ => {}, - } - None -} - -#[derive(Copy, Clone)] -enum RhsKind { - Unchanged, - ForceU128, - ForceU32, -} - -impl RhsKind { - fn ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option> { - match *self { - RhsKind::Unchanged => None, - RhsKind::ForceU128 => Some(tcx.types.u128), - RhsKind::ForceU32 => Some(tcx.types.u32), - } - } -} - -fn sign_of_128bit(ty: Ty<'_>) -> Option { - match ty.sty { - ty::Int(syntax::ast::IntTy::I128) => Some(true), - ty::Uint(syntax::ast::UintTy::U128) => Some(false), - _ => None, - } -} - -fn item_for_op(bin_op: BinOp, is_signed: bool) -> Option<(LangItem, RhsKind)> { - let i = match (bin_op, is_signed) { - (BinOp::Add, true) => (LangItem::I128AddFnLangItem, RhsKind::Unchanged), - (BinOp::Add, false) => (LangItem::U128AddFnLangItem, RhsKind::Unchanged), - (BinOp::Sub, true) => (LangItem::I128SubFnLangItem, RhsKind::Unchanged), - (BinOp::Sub, false) => (LangItem::U128SubFnLangItem, RhsKind::Unchanged), - (BinOp::Mul, true) => (LangItem::I128MulFnLangItem, RhsKind::Unchanged), - (BinOp::Mul, false) => (LangItem::U128MulFnLangItem, RhsKind::Unchanged), - (BinOp::Div, true) => (LangItem::I128DivFnLangItem, RhsKind::Unchanged), - (BinOp::Div, false) => (LangItem::U128DivFnLangItem, RhsKind::Unchanged), - (BinOp::Rem, true) => (LangItem::I128RemFnLangItem, RhsKind::Unchanged), - (BinOp::Rem, false) => (LangItem::U128RemFnLangItem, RhsKind::Unchanged), - (BinOp::Shl, true) => (LangItem::I128ShlFnLangItem, RhsKind::ForceU32), - (BinOp::Shl, false) => (LangItem::U128ShlFnLangItem, RhsKind::ForceU32), - (BinOp::Shr, true) => (LangItem::I128ShrFnLangItem, RhsKind::ForceU32), - (BinOp::Shr, false) => (LangItem::U128ShrFnLangItem, RhsKind::ForceU32), - _ => return None, - }; - Some(i) -} - -fn item_for_checked_op(bin_op: BinOp, is_signed: bool) -> Option<(LangItem, RhsKind)> { - let i = match (bin_op, is_signed) { - (BinOp::Add, true) => (LangItem::I128AddoFnLangItem, RhsKind::Unchanged), - (BinOp::Add, false) => (LangItem::U128AddoFnLangItem, RhsKind::Unchanged), - (BinOp::Sub, true) => (LangItem::I128SuboFnLangItem, RhsKind::Unchanged), - (BinOp::Sub, false) => (LangItem::U128SuboFnLangItem, RhsKind::Unchanged), - (BinOp::Mul, true) => (LangItem::I128MuloFnLangItem, RhsKind::Unchanged), - (BinOp::Mul, false) => (LangItem::U128MuloFnLangItem, RhsKind::Unchanged), - (BinOp::Shl, true) => (LangItem::I128ShloFnLangItem, RhsKind::ForceU128), - (BinOp::Shl, false) => (LangItem::U128ShloFnLangItem, RhsKind::ForceU128), - (BinOp::Shr, true) => (LangItem::I128ShroFnLangItem, RhsKind::ForceU128), - (BinOp::Shr, false) => (LangItem::U128ShroFnLangItem, RhsKind::ForceU128), - _ => bug!("That should be all the checked ones?"), - }; - Some(i) -} diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 9e23d06145330..c7e6eed1d9a2e 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -34,7 +34,6 @@ pub mod copy_prop; pub mod const_prop; pub mod generator; pub mod inline; -pub mod lower_128bit; pub mod uniform_array_move_out; pub(crate) fn provide(providers: &mut Providers<'_>) { @@ -272,8 +271,6 @@ fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> { // From here on out, regions are gone. &erase_regions::EraseRegions, - &lower_128bit::Lower128Bit, - // Optimizations begin. &uniform_array_move_out::RestoreSubsliceArrayMoveOut, diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 1fdc9b015ba39..e78fda61a4396 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -731,10 +731,6 @@ pub struct TargetOptions { /// for this target unconditionally. pub no_builtins: bool, - /// Whether to lower 128-bit operations to compiler_builtins calls. Use if - /// your backend only supports 64-bit and smaller math. - pub i128_lowering: bool, - /// The codegen backend to use for this target, typically "llvm" pub codegen_backend: String, @@ -850,7 +846,6 @@ impl Default for TargetOptions { requires_lto: false, singlethread: false, no_builtins: false, - i128_lowering: false, codegen_backend: "llvm".to_string(), default_hidden_visibility: false, embed_bitcode: false, From e8a1e73ff5fa0b2a085aa23d013c536c4e7c9675 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 20 Jul 2019 11:27:13 +0200 Subject: [PATCH 10/22] Update compiler_builtins to 0.1.18 --- Cargo.lock | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a8e9850e6436e..fe1b090c5467e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,7 +17,7 @@ dependencies = [ name = "alloc" version = "0.0.0" dependencies = [ - "compiler_builtins 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -110,7 +110,7 @@ dependencies = [ "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", @@ -122,7 +122,7 @@ version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -335,7 +335,7 @@ name = "cfg-if" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -464,7 +464,7 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", @@ -795,7 +795,7 @@ name = "dlmalloc" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -960,7 +960,7 @@ name = "fortanix-sgx-abi" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -1137,7 +1137,7 @@ name = "hashbrown" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-alloc 1.0.0", "rustc-std-workspace-core 1.0.0", ] @@ -1956,7 +1956,7 @@ dependencies = [ name = "panic_abort" version = "0.0.0" dependencies = [ - "compiler_builtins 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1967,7 +1967,7 @@ version = "0.0.0" dependencies = [ "alloc 0.0.0", "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "unwind 0.0.0", @@ -2138,7 +2138,7 @@ name = "profiler_builtins" version = "0.0.0" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2675,7 +2675,7 @@ name = "rustc-demangle" version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -2781,7 +2781,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -3000,7 +3000,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -3063,7 +3063,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -3181,7 +3181,7 @@ dependencies = [ "alloc 0.0.0", "build_helper 0.1.0", "cmake 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -3488,7 +3488,7 @@ dependencies = [ "backtrace 0.3.29 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4114,7 +4114,7 @@ version = "0.0.0" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -4328,7 +4328,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc" "checksum commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007" "checksum commoncrypto-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2" -"checksum compiler_builtins 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "ad9b4731b9e701aefe9e6bd1e9173f30526661508f9aaadaa5caec25ddf95585" +"checksum compiler_builtins 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "ef1c086a06d6f52f9c0d50cacdc021bfb6034ddeec9fb7e62f099f13f65472f4" "checksum compiletest_rs 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "f40ecc9332b68270998995c00f8051ee856121764a0d3230e64c9efd059d27b6" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4e2640d6d0bf22e82bed1b73c6aef8d5dd31e5abe6666c57e6d45e2649f4f887" From 93de733f021598ff6d0fa25c7d6f9dbb7dd58da7 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 20 Jul 2019 14:38:50 +0200 Subject: [PATCH 11/22] Remove tests for -Zlower-128bit-ops --- src/test/mir-opt/lower_128bit_debug_test.rs | 226 -------------------- src/test/mir-opt/lower_128bit_test.rs | 149 ------------- 2 files changed, 375 deletions(-) delete mode 100644 src/test/mir-opt/lower_128bit_debug_test.rs delete mode 100644 src/test/mir-opt/lower_128bit_test.rs diff --git a/src/test/mir-opt/lower_128bit_debug_test.rs b/src/test/mir-opt/lower_128bit_debug_test.rs deleted file mode 100644 index 1d23bac4ee206..0000000000000 --- a/src/test/mir-opt/lower_128bit_debug_test.rs +++ /dev/null @@ -1,226 +0,0 @@ -// asmjs can't even pass i128 as arguments or return values, so ignore it. -// this will hopefully be fixed by the LLVM 5 upgrade (#43370) -// ignore-asmjs -// ignore-emscripten - -// compile-flags: -Z lower_128bit_ops=yes -C debug_assertions=yes - -static TEST_SIGNED: i128 = const_signed(-222); -static TEST_UNSIGNED: u128 = const_unsigned(200); - -const fn const_signed(mut x: i128) -> i128 { - ((((((x + 1) - 2) * 3) / 4) % 5) << 6) >> 7 -} - -const fn const_unsigned(mut x: u128) -> u128 { - ((((((x + 1) - 2) * 3) / 4) % 5) << 6) >> 7 -} - -fn test_signed(mut x: i128) -> i128 { - x += 1; - x -= 2; - x *= 3; - x /= 4; - x %= 5; - x <<= 6; - x >>= 7; - x -} - -fn test_unsigned(mut x: u128) -> u128 { - x += 1; - x -= 2; - x *= 3; - x /= 4; - x %= 5; - x <<= 6; - x >>= 7; - x -} - -fn check(x: i128, y: u128) { - assert_eq!(test_signed(x), -1); - assert_eq!(const_signed(x), -1); - assert_eq!(TEST_SIGNED, -1); - assert_eq!(test_unsigned(y), 2); - assert_eq!(const_unsigned(y), 2); - assert_eq!(TEST_UNSIGNED, 2); -} - -fn main() { - check(-222, 200); -} - -// END RUST SOURCE - -// START rustc.const_signed.Lower128Bit.after.mir -// _8 = _1; -// _9 = const compiler_builtins::int::addsub::rust_i128_addo(move _8, const 1i128) -> bb10; -// ... -// _7 = move (_9.0: i128); -// ... -// _10 = const compiler_builtins::int::addsub::rust_i128_subo(move _7, const 2i128) -> bb11; -// ... -// _6 = move (_10.0: i128); -// ... -// _11 = const compiler_builtins::int::mul::rust_i128_mulo(move _6, const 3i128) -> bb12; -// ... -// _5 = move (_11.0: i128); -// ... -// _12 = Eq(const 4i128, const 0i128); -// assert(!move _12, "attempt to divide by zero") -> bb4; -// ... -// _13 = Eq(const 4i128, const -1i128); -// _14 = Eq(_5, const -170141183460469231731687303715884105728i128); -// _15 = BitAnd(move _13, move _14); -// assert(!move _15, "attempt to divide with overflow") -> bb5; -// ... -// _4 = const compiler_builtins::int::sdiv::rust_i128_div(move _5, const 4i128) -> bb13; -// ... -// _17 = Eq(const 5i128, const -1i128); -// _18 = Eq(_4, const -170141183460469231731687303715884105728i128); -// _19 = BitAnd(move _17, move _18); -// assert(!move _19, "attempt to calculate the remainder with overflow") -> bb7; -// ... -// _3 = const compiler_builtins::int::sdiv::rust_i128_rem(move _4, const 5i128) -> bb15; -// ... -// _2 = move (_20.0: i128); -// ... -// _23 = const 7i32 as u128 (Misc); -// _21 = const compiler_builtins::int::shift::rust_i128_shro(move _2, move _23) -> bb16; -// ... -// _0 = move (_21.0: i128); -// ... -// assert(!move (_9.1: bool), "attempt to add with overflow") -> bb1; -// ... -// assert(!move (_10.1: bool), "attempt to subtract with overflow") -> bb2; -// ... -// assert(!move (_11.1: bool), "attempt to multiply with overflow") -> bb3; -// ... -// _16 = Eq(const 5i128, const 0i128); -// assert(!move _16, "attempt to calculate the remainder with a divisor of zero") -> bb6; -// ... -// assert(!move (_20.1: bool), "attempt to shift left with overflow") -> bb8; -// ... -// _22 = const 6i32 as u128 (Misc); -// _20 = const compiler_builtins::int::shift::rust_i128_shlo(move _3, move _22) -> bb14; -// ... -// assert(!move (_21.1: bool), "attempt to shift right with overflow") -> bb9; -// END rustc.const_signed.Lower128Bit.after.mir - -// START rustc.const_unsigned.Lower128Bit.after.mir -// _8 = _1; -// _9 = const compiler_builtins::int::addsub::rust_u128_addo(move _8, const 1u128) -> bb8; -// ... -// _7 = move (_9.0: u128); -// ... -// _10 = const compiler_builtins::int::addsub::rust_u128_subo(move _7, const 2u128) -> bb9; -// ... -// _6 = move (_10.0: u128); -// ... -// _11 = const compiler_builtins::int::mul::rust_u128_mulo(move _6, const 3u128) -> bb10; -// ... -// _5 = move (_11.0: u128); -// ... -// _12 = Eq(const 4u128, const 0u128); -// assert(!move _12, "attempt to divide by zero") -> bb4; -// ... -// _4 = const compiler_builtins::int::udiv::rust_u128_div(move _5, const 4u128) -> bb11; -// ... -// _3 = const compiler_builtins::int::udiv::rust_u128_rem(move _4, const 5u128) -> bb13; -// ... -// _2 = move (_14.0: u128); -// ... -// _17 = const 7i32 as u128 (Misc); -// _15 = const compiler_builtins::int::shift::rust_u128_shro(move _2, move _17) -> bb14; -// ... -// _0 = move (_15.0: u128); -// ... -// assert(!move (_9.1: bool), "attempt to add with overflow") -> bb1; -// ... -// assert(!move (_10.1: bool), "attempt to subtract with overflow") -> bb2; -// ... -// assert(!move (_11.1: bool), "attempt to multiply with overflow") -> bb3; -// ... -// _13 = Eq(const 5u128, const 0u128); -// assert(!move _13, "attempt to calculate the remainder with a divisor of zero") -> bb5; -// ... -// assert(!move (_14.1: bool), "attempt to shift left with overflow") -> bb6; -// ... -// _16 = const 6i32 as u128 (Misc); -// _14 = const compiler_builtins::int::shift::rust_u128_shlo(move _3, move _16) -> bb12; -// ... -// assert(!move (_15.1: bool), "attempt to shift right with overflow") -> bb7; -// END rustc.const_unsigned.Lower128Bit.after.mir - -// START rustc.test_signed.Lower128Bit.after.mir -// _2 = const compiler_builtins::int::addsub::rust_i128_addo(_1, const 1i128) -> bb10; -// ... -// _1 = move (_2.0: i128); -// _3 = const compiler_builtins::int::addsub::rust_i128_subo(_1, const 2i128) -> bb11; -// ... -// _1 = move (_3.0: i128); -// _4 = const compiler_builtins::int::mul::rust_i128_mulo(_1, const 3i128) -> bb12; -// ... -// _1 = move (_4.0: i128); -// ... -// _1 = const compiler_builtins::int::sdiv::rust_i128_div(_1, const 4i128) -> bb13; -// ... -// _1 = const compiler_builtins::int::sdiv::rust_i128_rem(_1, const 5i128) -> bb15; -// ... -// _1 = move (_13.0: i128); -// ... -// _16 = const 7i32 as u128 (Misc); -// _14 = const compiler_builtins::int::shift::rust_i128_shro(_1, move _16) -> bb16; -// ... -// _1 = move (_14.0: i128); -// ... -// assert(!move (_2.1: bool), "attempt to add with overflow") -> bb1; -// ... -// assert(!move (_3.1: bool), "attempt to subtract with overflow") -> bb2; -// ... -// assert(!move (_4.1: bool), "attempt to multiply with overflow") -> bb3; -// ... -// assert(!move (_13.1: bool), "attempt to shift left with overflow") -> bb8; -// ... -// _15 = const 6i32 as u128 (Misc); -// _13 = const compiler_builtins::int::shift::rust_i128_shlo(_1, move _15) -> bb14; -// ... -// assert(!move (_14.1: bool), "attempt to shift right with overflow") -> bb9; -// END rustc.test_signed.Lower128Bit.after.mir - -// START rustc.test_unsigned.Lower128Bit.after.mir -// _2 = const compiler_builtins::int::addsub::rust_u128_addo(_1, const 1u128) -> bb8; -// ... -// _1 = move (_2.0: u128); -// _3 = const compiler_builtins::int::addsub::rust_u128_subo(_1, const 2u128) -> bb9; -// ... -// _1 = move (_3.0: u128); -// _4 = const compiler_builtins::int::mul::rust_u128_mulo(_1, const 3u128) -> bb10; -// ... -// _1 = move (_4.0: u128); -// ... -// _1 = const compiler_builtins::int::udiv::rust_u128_div(_1, const 4u128) -> bb11; -// ... -// _1 = const compiler_builtins::int::udiv::rust_u128_rem(_1, const 5u128) -> bb13; -// ... -// _1 = move (_7.0: u128); -// ... -// _10 = const 7i32 as u128 (Misc); -// _8 = const compiler_builtins::int::shift::rust_u128_shro(_1, move _10) -> bb14; -// ... -// _1 = move (_8.0: u128); -// ... -// assert(!move (_2.1: bool), "attempt to add with overflow") -> bb1; -// ... -// assert(!move (_3.1: bool), "attempt to subtract with overflow") -> bb2; -// ... -// assert(!move (_4.1: bool), "attempt to multiply with overflow") -> bb3; -// ... -// assert(!move (_7.1: bool), "attempt to shift left with overflow") -> bb6; -// ... -// _9 = const 6i32 as u128 (Misc); -// _7 = const compiler_builtins::int::shift::rust_u128_shlo(_1, move _9) -> bb12; -// ... -// assert(!move (_8.1: bool), "attempt to shift right with overflow") -> bb7; -// END rustc.test_unsigned.Lower128Bit.after.mir diff --git a/src/test/mir-opt/lower_128bit_test.rs b/src/test/mir-opt/lower_128bit_test.rs deleted file mode 100644 index 7528330b030ce..0000000000000 --- a/src/test/mir-opt/lower_128bit_test.rs +++ /dev/null @@ -1,149 +0,0 @@ -// ignore-emscripten - -// compile-flags: -Z lower_128bit_ops=yes -C debug_assertions=no -O - -static TEST_SIGNED: i128 = const_signed(-222); -static TEST_UNSIGNED: u128 = const_unsigned(200); - -const fn const_signed(mut x: i128) -> i128 { - ((((((x + 1) - 2) * 3) / 4) % 5) << 6) >> 7 -} - -const fn const_unsigned(mut x: u128) -> u128 { - ((((((x + 1) - 2) * 3) / 4) % 5) << 6) >> 7 -} - -fn test_signed(mut x: i128) -> i128 { - x += 1; - x -= 2; - x *= 3; - x /= 4; - x %= 5; - x <<= 6; - x >>= 7; - x -} - -fn test_unsigned(mut x: u128) -> u128 { - x += 1; - x -= 2; - x *= 3; - x /= 4; - x %= 5; - x <<= 6; - x >>= 7; - x -} - -fn check(x: i128, y: u128) { - assert_eq!(test_signed(x), -1); - assert_eq!(const_signed(x), -1); - assert_eq!(TEST_SIGNED, -1); - assert_eq!(test_unsigned(y), 2); - assert_eq!(const_unsigned(y), 2); - assert_eq!(TEST_UNSIGNED, 2); -} - -fn main() { - check(-222, 200); -} - -// END RUST SOURCE - -// START rustc.const_signed.Lower128Bit.after.mir -// _7 = const compiler_builtins::int::addsub::rust_i128_add(move _8, const 1i128) -> bb7; -// ... -// _10 = Eq(const 4i128, const -1i128); -// _11 = Eq(_5, const -170141183460469231731687303715884105728i128); -// _12 = BitAnd(move _10, move _11); -// assert(!move _12, "attempt to divide with overflow") -> bb2; -// ... -// _4 = const compiler_builtins::int::sdiv::rust_i128_div(move _5, const 4i128) -> bb8; -// ... -// _14 = Eq(const 5i128, const -1i128); -// _15 = Eq(_4, const -170141183460469231731687303715884105728i128); -// _16 = BitAnd(move _14, move _15); -// assert(!move _16, "attempt to calculate the remainder with overflow") -> bb4; -// ... -// _3 = const compiler_builtins::int::sdiv::rust_i128_rem(move _4, const 5i128) -> bb11; -// ... -// _9 = Eq(const 4i128, const 0i128); -// assert(!move _9, "attempt to divide by zero") -> bb1; -// ... -// _5 = const compiler_builtins::int::mul::rust_i128_mul(move _6, const 3i128) -> bb5; -// ... -// _6 = const compiler_builtins::int::addsub::rust_i128_sub(move _7, const 2i128) -> bb6; -// ... -// _13 = Eq(const 5i128, const 0i128); -// assert(!move _13, "attempt to calculate the remainder with a divisor of zero") -> bb3; -// ... -// _17 = const 7i32 as u32 (Misc); -// _0 = const compiler_builtins::int::shift::rust_i128_shr(move _2, move _17) -> bb9; -// ... -// _18 = const 6i32 as u32 (Misc); -// _2 = const compiler_builtins::int::shift::rust_i128_shl(move _3, move _18) -> bb10; -// END rustc.const_signed.Lower128Bit.after.mir - -// START rustc.const_unsigned.Lower128Bit.after.mir -// _8 = _1; -// _7 = const compiler_builtins::int::addsub::rust_u128_add(move _8, const 1u128) -> bb5; -// ... -// _4 = const compiler_builtins::int::udiv::rust_u128_div(move _5, const 4u128) -> bb6; -// ... -// _3 = const compiler_builtins::int::udiv::rust_u128_rem(move _4, const 5u128) -> bb9; -// ... -// _9 = Eq(const 4u128, const 0u128); -// assert(!move _9, "attempt to divide by zero") -> bb1; -// ... -// _5 = const compiler_builtins::int::mul::rust_u128_mul(move _6, const 3u128) -> bb3; -// ... -// _6 = const compiler_builtins::int::addsub::rust_u128_sub(move _7, const 2u128) -> bb4; -// ... -// _10 = Eq(const 5u128, const 0u128); -// assert(!move _10, "attempt to calculate the remainder with a divisor of zero") -> bb2; -// ... -// return; -// ... -// _11 = const 7i32 as u32 (Misc); -// _0 = const compiler_builtins::int::shift::rust_u128_shr(move _2, move _11) -> bb7; -// ... -// _12 = const 6i32 as u32 (Misc); -// _2 = const compiler_builtins::int::shift::rust_u128_shl(move _3, move _12) -> bb8; - -// END rustc.const_unsigned.Lower128Bit.after.mir - -// START rustc.test_signed.Lower128Bit.after.mir -// _1 = const compiler_builtins::int::addsub::rust_i128_add(_1, const 1i128) -> bb7; -// ... -// _1 = const compiler_builtins::int::sdiv::rust_i128_div(_1, const 4i128) -> bb8; -// ... -// _1 = const compiler_builtins::int::sdiv::rust_i128_rem(_1, const 5i128) -> bb11; -// ... -// _1 = const compiler_builtins::int::mul::rust_i128_mul(_1, const 3i128) -> bb5; -// ... -// _1 = const compiler_builtins::int::addsub::rust_i128_sub(_1, const 2i128) -> bb6; -// ... -// _10 = const 7i32 as u32 (Misc); -// _1 = const compiler_builtins::int::shift::rust_i128_shr(_1, move _10) -> bb9; -// ... -// _11 = const 6i32 as u32 (Misc); -// _1 = const compiler_builtins::int::shift::rust_i128_shl(_1, move _11) -> bb10; -// END rustc.test_signed.Lower128Bit.after.mir - -// START rustc.test_unsigned.Lower128Bit.after.mir -// _1 = const compiler_builtins::int::addsub::rust_u128_add(_1, const 1u128) -> bb5; -// ... -// _1 = const compiler_builtins::int::udiv::rust_u128_div(_1, const 4u128) -> bb6; -// ... -// _1 = const compiler_builtins::int::udiv::rust_u128_rem(_1, const 5u128) -> bb9; -// ... -// _1 = const compiler_builtins::int::mul::rust_u128_mul(_1, const 3u128) -> bb3; -// ... -// _1 = const compiler_builtins::int::addsub::rust_u128_sub(_1, const 2u128) -> bb4; -// ... -// _4 = const 7i32 as u32 (Misc); -// _1 = const compiler_builtins::int::shift::rust_u128_shr(_1, move _4) -> bb7; -// ... -// _5 = const 6i32 as u32 (Misc); -// _1 = const compiler_builtins::int::shift::rust_u128_shl(_1, move _5) -> bb8; -// END rustc.test_unsigned.Lower128Bit.after.mir From 6fae7db65d5f772cfbf116fbb9e5944447725289 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 20 Jul 2019 13:05:37 +0200 Subject: [PATCH 12/22] Remove vector fadd/fmul reduction workarounds The bugs that this was working around have been fixed in LLVM 9. --- src/librustc_codegen_llvm/builder.rs | 12 ++--- src/librustc_codegen_llvm/common.rs | 19 -------- src/librustc_codegen_llvm/intrinsic.rs | 28 ++--------- src/librustc_codegen_llvm/llvm/ffi.rs | 2 - .../simd/simd-intrinsic-generic-reduction.rs | 10 ++-- .../simd-intrinsic-generic-reduction.rs | 22 ++------- .../simd-intrinsic-generic-reduction.stderr | 46 +++++++------------ 7 files changed, 37 insertions(+), 102 deletions(-) diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 5ac1cf8c36f93..894e5c2fd3d93 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -1153,11 +1153,14 @@ impl Builder<'a, 'll, 'tcx> { } } + pub fn vector_reduce_fadd(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { + unsafe { llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src) } + } + pub fn vector_reduce_fmul(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { + unsafe { llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src) } + } pub fn vector_reduce_fadd_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { unsafe { - // FIXME: add a non-fast math version once - // https://bugs.llvm.org/show_bug.cgi?id=36732 - // is fixed. let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src); llvm::LLVMRustSetHasUnsafeAlgebra(instr); instr @@ -1165,9 +1168,6 @@ impl Builder<'a, 'll, 'tcx> { } pub fn vector_reduce_fmul_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { unsafe { - // FIXME: add a non-fast math version once - // https://bugs.llvm.org/show_bug.cgi?id=36732 - // is fixed. let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src); llvm::LLVMRustSetHasUnsafeAlgebra(instr); instr diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index e9f25e6344b06..f00624f3811f1 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -166,25 +166,6 @@ impl CodegenCx<'ll, 'tcx> { r } } - - pub fn const_get_real(&self, v: &'ll Value) -> Option<(f64, bool)> { - unsafe { - if self.is_const_real(v) { - let mut loses_info: llvm::Bool = 0; - let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info); - let loses_info = if loses_info == 1 { true } else { false }; - Some((r, loses_info)) - } else { - None - } - } - } - - fn is_const_real(&self, v: &'ll Value) -> bool { - unsafe { - llvm::LLVMIsAConstantFP(v).is_some() - } - } } impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index dd6cfd7e29e4e..44b3eff2ac5c9 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -1640,29 +1640,11 @@ fn generic_simd_intrinsic( } }, ty::Float(f) => { - // ordered arithmetic reductions take an accumulator let acc = if $ordered { - let acc = args[1].immediate(); - // FIXME: https://bugs.llvm.org/show_bug.cgi?id=36734 - // * if the accumulator of the fadd isn't 0, incorrect - // code is generated - // * if the accumulator of the fmul isn't 1, incorrect - // code is generated - match bx.const_get_real(acc) { - None => return_error!("accumulator of {} is not a constant", $name), - Some((v, loses_info)) => { - if $name.contains("mul") && v != 1.0_f64 { - return_error!("accumulator of {} is not 1.0", $name); - } else if $name.contains("add") && v != 0.0_f64 { - return_error!("accumulator of {} is not 0.0", $name); - } else if loses_info { - return_error!("accumulator of {} loses information", $name); - } - } - } - acc + // ordered arithmetic reductions take an accumulator + args[1].immediate() } else { - // unordered arithmetic reductions do not: + // unordered arithmetic reductions use the identity accumulator let identity_acc = if $name.contains("mul") { 1.0 } else { 0.0 }; match f.bit_width() { 32 => bx.const_real(bx.type_f32(), identity_acc), @@ -1688,8 +1670,8 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, } } - arith_red!("simd_reduce_add_ordered": vector_reduce_add, vector_reduce_fadd_fast, true); - arith_red!("simd_reduce_mul_ordered": vector_reduce_mul, vector_reduce_fmul_fast, true); + arith_red!("simd_reduce_add_ordered": vector_reduce_add, vector_reduce_fadd, true); + arith_red!("simd_reduce_mul_ordered": vector_reduce_mul, vector_reduce_fmul, true); arith_red!("simd_reduce_add_unordered": vector_reduce_add, vector_reduce_fadd_fast, false); arith_red!("simd_reduce_mul_unordered": vector_reduce_mul, vector_reduce_fmul_fast, false); diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 5d82698d8efb6..8c6ea00eb8c87 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -719,7 +719,6 @@ extern "C" { pub fn LLVMConstIntGetZExtValue(ConstantVal: &Value) -> c_ulonglong; pub fn LLVMRustConstInt128Get(ConstantVal: &Value, SExt: bool, high: &mut u64, low: &mut u64) -> bool; - pub fn LLVMConstRealGetDouble (ConstantVal: &Value, losesInfo: &mut Bool) -> f64; // Operations on composite constants @@ -1663,7 +1662,6 @@ extern "C" { pub fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString); pub fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&Value>; - pub fn LLVMIsAConstantFP(value_ref: &Value) -> Option<&Value>; pub fn LLVMRustPassKind(Pass: &Pass) -> PassKind; pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> Option<&'static mut Pass>; diff --git a/src/test/run-pass/simd/simd-intrinsic-generic-reduction.rs b/src/test/run-pass/simd/simd-intrinsic-generic-reduction.rs index e3faa7c625ccc..4195444a73f67 100644 --- a/src/test/run-pass/simd/simd-intrinsic-generic-reduction.rs +++ b/src/test/run-pass/simd/simd-intrinsic-generic-reduction.rs @@ -2,7 +2,7 @@ #![allow(non_camel_case_types)] // ignore-emscripten -// ignore-aarch64 FIXME: https://github.com/rust-lang/rust/issues/54510 +// min-system-llvm-version: 9.0 // Test that the simd_reduce_{op} intrinsics produce the correct results. @@ -124,14 +124,14 @@ fn main() { assert_eq!(r, 6_f32); let r: f32 = simd_reduce_mul_unordered(x); assert_eq!(r, -24_f32); - // FIXME: only works correctly for accumulator, 0: - // https://bugs.llvm.org/show_bug.cgi?id=36734 let r: f32 = simd_reduce_add_ordered(x, 0.); assert_eq!(r, 6_f32); - // FIXME: only works correctly for accumulator, 1: - // https://bugs.llvm.org/show_bug.cgi?id=36734 let r: f32 = simd_reduce_mul_ordered(x, 1.); assert_eq!(r, -24_f32); + let r: f32 = simd_reduce_add_ordered(x, 1.); + assert_eq!(r, 7_f32); + let r: f32 = simd_reduce_mul_ordered(x, 2.); + assert_eq!(r, -48_f32); let r: f32 = simd_reduce_min(x); assert_eq!(r, -2_f32); diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.rs index 8e67c27ef2255..9a6dbe9d9ab1d 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.rs +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.rs @@ -30,13 +30,10 @@ fn main() { let z = f32x4(0.0, 0.0, 0.0, 0.0); unsafe { - simd_reduce_add_ordered(z, 0_f32); - simd_reduce_mul_ordered(z, 1_f32); - - simd_reduce_add_ordered(z, 2_f32); - //~^ ERROR accumulator of simd_reduce_add_ordered is not 0.0 - simd_reduce_mul_ordered(z, 3_f32); - //~^ ERROR accumulator of simd_reduce_mul_ordered is not 1.0 + simd_reduce_add_ordered(z, 0); + //~^ ERROR expected return type `f32` (element of input `f32x4`), found `i32` + simd_reduce_mul_ordered(z, 1); + //~^ ERROR expected return type `f32` (element of input `f32x4`), found `i32` let _: f32 = simd_reduce_and(x); //~^ ERROR expected return type `u32` (element of input `u32x4`), found `f32` @@ -56,16 +53,5 @@ fn main() { //~^ ERROR unsupported simd_reduce_all from `f32x4` with element `f32` to `bool` let _: bool = simd_reduce_any(z); //~^ ERROR unsupported simd_reduce_any from `f32x4` with element `f32` to `bool` - - foo(0_f32); } } - -#[inline(never)] -unsafe fn foo(x: f32) { - let z = f32x4(0.0, 0.0, 0.0, 0.0); - simd_reduce_add_ordered(z, x); - //~^ ERROR accumulator of simd_reduce_add_ordered is not a constant - simd_reduce_mul_ordered(z, x); - //~^ ERROR accumulator of simd_reduce_mul_ordered is not a constant -} diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.stderr index 144571cb26353..3863eeac3f394 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.stderr +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-reduction.stderr @@ -1,74 +1,62 @@ -error[E0511]: invalid monomorphization of `simd_reduce_add_ordered` intrinsic: accumulator of simd_reduce_add_ordered is not 0.0 - --> $DIR/simd-intrinsic-generic-reduction.rs:36:9 +error[E0511]: invalid monomorphization of `simd_reduce_add_ordered` intrinsic: expected return type `f32` (element of input `f32x4`), found `i32` + --> $DIR/simd-intrinsic-generic-reduction.rs:33:9 | -LL | simd_reduce_add_ordered(z, 2_f32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_reduce_add_ordered(z, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_reduce_mul_ordered` intrinsic: accumulator of simd_reduce_mul_ordered is not 1.0 - --> $DIR/simd-intrinsic-generic-reduction.rs:38:9 +error[E0511]: invalid monomorphization of `simd_reduce_mul_ordered` intrinsic: expected return type `f32` (element of input `f32x4`), found `i32` + --> $DIR/simd-intrinsic-generic-reduction.rs:35:9 | -LL | simd_reduce_mul_ordered(z, 3_f32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | simd_reduce_mul_ordered(z, 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_and` intrinsic: expected return type `u32` (element of input `u32x4`), found `f32` - --> $DIR/simd-intrinsic-generic-reduction.rs:41:22 + --> $DIR/simd-intrinsic-generic-reduction.rs:38:22 | LL | let _: f32 = simd_reduce_and(x); | ^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_or` intrinsic: expected return type `u32` (element of input `u32x4`), found `f32` - --> $DIR/simd-intrinsic-generic-reduction.rs:43:22 + --> $DIR/simd-intrinsic-generic-reduction.rs:40:22 | LL | let _: f32 = simd_reduce_or(x); | ^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_xor` intrinsic: expected return type `u32` (element of input `u32x4`), found `f32` - --> $DIR/simd-intrinsic-generic-reduction.rs:45:22 + --> $DIR/simd-intrinsic-generic-reduction.rs:42:22 | LL | let _: f32 = simd_reduce_xor(x); | ^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_and` intrinsic: unsupported simd_reduce_and from `f32x4` with element `f32` to `f32` - --> $DIR/simd-intrinsic-generic-reduction.rs:48:22 + --> $DIR/simd-intrinsic-generic-reduction.rs:45:22 | LL | let _: f32 = simd_reduce_and(z); | ^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_or` intrinsic: unsupported simd_reduce_or from `f32x4` with element `f32` to `f32` - --> $DIR/simd-intrinsic-generic-reduction.rs:50:22 + --> $DIR/simd-intrinsic-generic-reduction.rs:47:22 | LL | let _: f32 = simd_reduce_or(z); | ^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_xor` intrinsic: unsupported simd_reduce_xor from `f32x4` with element `f32` to `f32` - --> $DIR/simd-intrinsic-generic-reduction.rs:52:22 + --> $DIR/simd-intrinsic-generic-reduction.rs:49:22 | LL | let _: f32 = simd_reduce_xor(z); | ^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_all` intrinsic: unsupported simd_reduce_all from `f32x4` with element `f32` to `bool` - --> $DIR/simd-intrinsic-generic-reduction.rs:55:23 + --> $DIR/simd-intrinsic-generic-reduction.rs:52:23 | LL | let _: bool = simd_reduce_all(z); | ^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_reduce_any` intrinsic: unsupported simd_reduce_any from `f32x4` with element `f32` to `bool` - --> $DIR/simd-intrinsic-generic-reduction.rs:57:23 + --> $DIR/simd-intrinsic-generic-reduction.rs:54:23 | LL | let _: bool = simd_reduce_any(z); | ^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `simd_reduce_add_ordered` intrinsic: accumulator of simd_reduce_add_ordered is not a constant - --> $DIR/simd-intrinsic-generic-reduction.rs:67:5 - | -LL | simd_reduce_add_ordered(z, x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0511]: invalid monomorphization of `simd_reduce_mul_ordered` intrinsic: accumulator of simd_reduce_mul_ordered is not a constant - --> $DIR/simd-intrinsic-generic-reduction.rs:69:5 - | -LL | simd_reduce_mul_ordered(z, x); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 12 previous errors +error: aborting due to 10 previous errors From 279c399599357cdb40d2bbe24a769d2d1dd4a9d9 Mon Sep 17 00:00:00 2001 From: Baoshan Pang Date: Sun, 21 Jul 2019 18:22:29 -0700 Subject: [PATCH 13/22] code cleanup --- src/libstd/sys/vxworks/alloc.rs | 30 -- src/libstd/sys/vxworks/android.rs | 160 ------ src/libstd/sys/vxworks/condvar.rs | 73 --- src/libstd/sys/vxworks/ext/net.rs | 27 +- src/libstd/sys/vxworks/l4re.rs | 469 ------------------ src/libstd/sys/vxworks/memchr.rs | 19 - src/libstd/sys/vxworks/mod.rs | 14 - src/libstd/sys/vxworks/net.rs | 13 - .../sys/vxworks/process/process_common.rs | 34 -- src/libstd/sys/vxworks/stack_overflow.rs | 168 ------- src/libstd/sys/vxworks/thread.rs | 36 -- 11 files changed, 1 insertion(+), 1042 deletions(-) delete mode 100644 src/libstd/sys/vxworks/android.rs delete mode 100644 src/libstd/sys/vxworks/l4re.rs diff --git a/src/libstd/sys/vxworks/alloc.rs b/src/libstd/sys/vxworks/alloc.rs index c60d1b8dab898..e0c560b9214ea 100644 --- a/src/libstd/sys/vxworks/alloc.rs +++ b/src/libstd/sys/vxworks/alloc.rs @@ -41,36 +41,6 @@ unsafe impl GlobalAlloc for System { } } -#[cfg(any(target_os = "android", - target_os = "hermit", - target_os = "redox", - target_os = "solaris"))] -#[inline] -unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { - // On android we currently target API level 9 which unfortunately - // doesn't have the `posix_memalign` API used below. Instead we use - // `memalign`, but this unfortunately has the property on some systems - // where the memory returned cannot be deallocated by `free`! - // - // Upon closer inspection, however, this appears to work just fine with - // Android, so for this platform we should be fine to call `memalign` - // (which is present in API level 9). Some helpful references could - // possibly be chromium using memalign [1], attempts at documenting that - // memalign + free is ok [2] [3], or the current source of chromium - // which still uses memalign on android [4]. - // - // [1]: https://codereview.chromium.org/10796020/ - // [2]: https://code.google.com/p/android/issues/detail?id=35391 - // [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579 - // [4]: https://chromium.googlesource.com/chromium/src/base/+/master/ - // /memory/aligned_memory.cc - libc::memalign(layout.align(), layout.size()) as *mut u8 -} - -#[cfg(not(any(target_os = "android", - target_os = "hermit", - target_os = "redox", - target_os = "solaris")))] #[inline] unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { let mut out = ptr::null_mut(); diff --git a/src/libstd/sys/vxworks/android.rs b/src/libstd/sys/vxworks/android.rs deleted file mode 100644 index 6774160bb2561..0000000000000 --- a/src/libstd/sys/vxworks/android.rs +++ /dev/null @@ -1,160 +0,0 @@ -//! Android ABI-compatibility module -//! -//! The ABI of Android has changed quite a bit over time, and libstd attempts to -//! be both forwards and backwards compatible as much as possible. We want to -//! always work with the most recent version of Android, but we also want to -//! work with older versions of Android for whenever projects need to. -//! -//! Our current minimum supported Android version is `android-9`, e.g., Android -//! with API level 9. We then in theory want to work on that and all future -//! versions of Android! -//! -//! Some of the detection here is done at runtime via `dlopen` and -//! introspection. Other times no detection is performed at all and we just -//! provide a fallback implementation as some versions of Android we support -//! don't have the function. -//! -//! You'll find more details below about why each compatibility shim is needed. - -#![cfg(target_os = "android")] - -use libc::{c_int, c_void, sighandler_t, size_t, ssize_t}; -use libc::{ftruncate, pread, pwrite}; - -use crate::io; -use super::{cvt, cvt_r}; - -// The `log2` and `log2f` functions apparently appeared in android-18, or at -// least you can see they're not present in the android-17 header [1] and they -// are present in android-18 [2]. -// -// [1]: https://chromium.googlesource.com/android_tools/+/20ee6d20/ndk/platforms -// /android-17/arch-arm/usr/include/math.h -// [2]: https://chromium.googlesource.com/android_tools/+/20ee6d20/ndk/platforms -// /android-18/arch-arm/usr/include/math.h -// -// Note that these shims are likely less precise than directly calling `log2`, -// but hopefully that should be enough for now... -// -// Note that mathematically, for any arbitrary `y`: -// -// log_2(x) = log_y(x) / log_y(2) -// = log_y(x) / (1 / log_2(y)) -// = log_y(x) * log_2(y) -// -// Hence because `ln` (log_e) is available on all Android we just choose `y = e` -// and get: -// -// log_2(x) = ln(x) * log_2(e) - -#[cfg(not(test))] -pub fn log2f32(f: f32) -> f32 { - f.ln() * crate::f32::consts::LOG2_E -} - -#[cfg(not(test))] -pub fn log2f64(f: f64) -> f64 { - f.ln() * crate::f64::consts::LOG2_E -} - -// Back in the day [1] the `signal` function was just an inline wrapper -// around `bsd_signal`, but starting in API level android-20 the `signal` -// symbols was introduced [2]. Finally, in android-21 the API `bsd_signal` was -// removed [3]. -// -// Basically this means that if we want to be binary compatible with multiple -// Android releases (oldest being 9 and newest being 21) then we need to check -// for both symbols and not actually link against either. -// -// [1]: https://chromium.googlesource.com/android_tools/+/20ee6d20/ndk/platforms -// /android-18/arch-arm/usr/include/signal.h -// [2]: https://chromium.googlesource.com/android_tools/+/fbd420/ndk_experimental -// /platforms/android-20/arch-arm -// /usr/include/signal.h -// [3]: https://chromium.googlesource.com/android_tools/+/20ee6d/ndk/platforms -// /android-21/arch-arm/usr/include/signal.h -pub unsafe fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t { - weak!(fn signal(c_int, sighandler_t) -> sighandler_t); - weak!(fn bsd_signal(c_int, sighandler_t) -> sighandler_t); - - let f = signal.get().or_else(|| bsd_signal.get()); - let f = f.expect("neither `signal` nor `bsd_signal` symbols found"); - f(signum, handler) -} - -// The `ftruncate64` symbol apparently appeared in android-12, so we do some -// dynamic detection to see if we can figure out whether `ftruncate64` exists. -// -// If it doesn't we just fall back to `ftruncate`, generating an error for -// too-large values. -#[cfg(target_pointer_width = "32")] -pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> { - weak!(fn ftruncate64(c_int, i64) -> c_int); - - unsafe { - match ftruncate64.get() { - Some(f) => cvt_r(|| f(fd, size as i64)).map(|_| ()), - None => { - if size > i32::max_value() as u64 { - Err(io::Error::new(io::ErrorKind::InvalidInput, - "cannot truncate >2GB")) - } else { - cvt_r(|| ftruncate(fd, size as i32)).map(|_| ()) - } - } - } - } -} - -#[cfg(target_pointer_width = "64")] -pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> { - unsafe { - cvt_r(|| ftruncate(fd, size as i64)).map(|_| ()) - } -} - -#[cfg(target_pointer_width = "32")] -pub unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: size_t, offset: i64) - -> io::Result -{ - use crate::convert::TryInto; - weak!(fn pread64(c_int, *mut c_void, size_t, i64) -> ssize_t); - pread64.get().map(|f| cvt(f(fd, buf, count, offset))).unwrap_or_else(|| { - if let Ok(o) = offset.try_into() { - cvt(pread(fd, buf, count, o)) - } else { - Err(io::Error::new(io::ErrorKind::InvalidInput, - "cannot pread >2GB")) - } - }) -} - -#[cfg(target_pointer_width = "32")] -pub unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: size_t, offset: i64) - -> io::Result -{ - use crate::convert::TryInto; - weak!(fn pwrite64(c_int, *const c_void, size_t, i64) -> ssize_t); - pwrite64.get().map(|f| cvt(f(fd, buf, count, offset))).unwrap_or_else(|| { - if let Ok(o) = offset.try_into() { - cvt(pwrite(fd, buf, count, o)) - } else { - Err(io::Error::new(io::ErrorKind::InvalidInput, - "cannot pwrite >2GB")) - } - }) -} - -#[cfg(target_pointer_width = "64")] -pub unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: size_t, offset: i64) - -> io::Result -{ - cvt(pread(fd, buf, count, offset)) -} - -#[cfg(target_pointer_width = "64")] -pub unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: size_t, offset: i64) - -> io::Result -{ - cvt(pwrite(fd, buf, count, offset)) -} diff --git a/src/libstd/sys/vxworks/condvar.rs b/src/libstd/sys/vxworks/condvar.rs index 4d221264f232f..783c3eb7c766f 100644 --- a/src/libstd/sys/vxworks/condvar.rs +++ b/src/libstd/sys/vxworks/condvar.rs @@ -62,10 +62,6 @@ impl Condvar { // where we configure condition variable to use monotonic clock (instead of // default system clock). This approach avoids all problems that result // from changes made to the system time. - #[cfg(not(any(target_os = "macos", - target_os = "ios", - target_os = "android", - target_os = "hermit")))] pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { use crate::mem; @@ -92,78 +88,9 @@ impl Condvar { } - // This implementation is modeled after libcxx's condition_variable - // https://github.com/llvm-mirror/libcxx/blob/release_35/src/condition_variable.cpp#L46 - // https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367 - #[cfg(any(target_os = "macos", target_os = "ios", target_os = "android", target_os = "hermit"))] - pub unsafe fn wait_timeout(&self, mutex: &Mutex, mut dur: Duration) -> bool { - use crate::ptr; - use crate::time::Instant; - - // 1000 years - let max_dur = Duration::from_secs(1000 * 365 * 86400); - - if dur > max_dur { - // OSX implementation of `pthread_cond_timedwait` is buggy - // with super long durations. When duration is greater than - // 0x100_0000_0000_0000 seconds, `pthread_cond_timedwait` - // in macOS Sierra return error 316. - // - // This program demonstrates the issue: - // https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c - // - // To work around this issue, and possible bugs of other OSes, timeout - // is clamped to 1000 years, which is allowable per the API of `wait_timeout` - // because of spurious wakeups. - - dur = max_dur; - } - - // First, figure out what time it currently is, in both system and - // stable time. pthread_cond_timedwait uses system time, but we want to - // report timeout based on stable time. - let mut sys_now = libc::timeval { tv_sec: 0, tv_usec: 0 }; - let stable_now = Instant::now(); - let r = libc::gettimeofday(&mut sys_now, ptr::null_mut()); - debug_assert_eq!(r, 0); - - let nsec = dur.subsec_nanos() as libc::c_long + - (sys_now.tv_usec * 1000) as libc::c_long; - let extra = (nsec / 1_000_000_000) as libc::time_t; - let nsec = nsec % 1_000_000_000; - let seconds = saturating_cast_to_time_t(dur.as_secs()); - - let timeout = sys_now.tv_sec.checked_add(extra).and_then(|s| { - s.checked_add(seconds) - }).map(|s| { - libc::timespec { tv_sec: s, tv_nsec: nsec } - }).unwrap_or(TIMESPEC_MAX); - - // And wait! - let r = libc::pthread_cond_timedwait(self.inner.get(), mutex::raw(mutex), - &timeout); - debug_assert!(r == libc::ETIMEDOUT || r == 0); - - // ETIMEDOUT is not a totally reliable method of determining timeout due - // to clock shifts, so do the check ourselves - stable_now.elapsed() < dur - } - #[inline] - #[cfg(not(target_os = "dragonfly"))] pub unsafe fn destroy(&self) { let r = libc::pthread_cond_destroy(self.inner.get()); debug_assert_eq!(r, 0); } - - #[inline] - #[cfg(target_os = "dragonfly")] - pub unsafe fn destroy(&self) { - let r = libc::pthread_cond_destroy(self.inner.get()); - // On DragonFly pthread_cond_destroy() returns EINVAL if called on - // a condvar that was just initialized with - // libc::PTHREAD_COND_INITIALIZER. Once it is used or - // pthread_cond_init() is called, this behaviour no longer occurs. - debug_assert!(r == 0 || r == libc::EINVAL); - } } diff --git a/src/libstd/sys/vxworks/ext/net.rs b/src/libstd/sys/vxworks/ext/net.rs index 41090caee8459..3f0a7e9e84319 100644 --- a/src/libstd/sys/vxworks/ext/net.rs +++ b/src/libstd/sys/vxworks/ext/net.rs @@ -5,16 +5,6 @@ #[cfg(unix)] use libc; -// FIXME(#43348): Make libc adapt #[doc(cfg(...))] so we don't need these fake definitions here? -#[cfg(not(unix))] -mod libc { - pub use libc::c_int; - pub type socklen_t = u32; - pub struct sockaddr; - #[derive(Clone)] - pub struct sockaddr_un; -} - use crate::ascii; use crate::ffi::OsStr; use crate::fmt; @@ -29,15 +19,6 @@ use crate::sys::{self, cvt}; use crate::sys::net::Socket; use crate::sys_common::{self, AsInner, FromInner, IntoInner}; -#[cfg(any(target_os = "linux", target_os = "android", - target_os = "dragonfly", target_os = "freebsd", - target_os = "openbsd", target_os = "netbsd", - target_os = "haiku"))] -use libc::MSG_NOSIGNAL; -#[cfg(not(any(target_os = "linux", target_os = "android", - target_os = "dragonfly", target_os = "freebsd", - target_os = "openbsd", target_os = "netbsd", - target_os = "haiku")))] const MSG_NOSIGNAL: libc::c_int = 0x0; fn sun_path_offset(addr: &libc::sockaddr_un) -> usize { @@ -202,13 +183,7 @@ impl SocketAddr { let len = self.len as usize - sun_path_offset(&self.addr); let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) }; - // macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses - if len == 0 - || (cfg!(not(any(target_os = "linux", target_os = "android"))) - && self.addr.sun_path[0] == 0) - { - AddressKind::Unnamed - } else if self.addr.sun_path[0] == 0 { + if self.addr.sun_path[0] == 0 { AddressKind::Abstract(&path[1..len]) } else { AddressKind::Pathname(OsStr::from_bytes(&path[..len - 1]).as_ref()) diff --git a/src/libstd/sys/vxworks/l4re.rs b/src/libstd/sys/vxworks/l4re.rs deleted file mode 100644 index b3dd1cf6aaac7..0000000000000 --- a/src/libstd/sys/vxworks/l4re.rs +++ /dev/null @@ -1,469 +0,0 @@ -macro_rules! unimpl { - () => (return Err(io::Error::new(io::ErrorKind::Other, "No networking available on L4Re."));) -} - -pub mod net { - #![allow(warnings)] - use crate::fmt; - use crate::io::{self, IoVec, IoVecMut}; - use crate::net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr}; - use crate::sys_common::{AsInner, FromInner, IntoInner}; - use crate::sys::fd::FileDesc; - use crate::time::Duration; - use crate::convert::TryFrom; - - #[allow(unused_extern_crates)] - pub extern crate libc as netc; - - pub struct Socket(FileDesc); - impl Socket { - pub fn new(_: &SocketAddr, _: libc::c_int) -> io::Result { - unimpl!(); - } - - pub fn new_raw(_: libc::c_int, _: libc::c_int) -> io::Result { - unimpl!(); - } - - pub fn new_pair(_: libc::c_int, _: libc::c_int) -> io::Result<(Socket, Socket)> { - unimpl!(); - } - - pub fn connect_timeout(&self, _: &SocketAddr, _: Duration) -> io::Result<()> { - unimpl!(); - } - - pub fn accept(&self, _: *mut libc::sockaddr, _: *mut libc::socklen_t) - -> io::Result { - unimpl!(); - } - - pub fn duplicate(&self) -> io::Result { - unimpl!(); - } - - pub fn read(&self, _: &mut [u8]) -> io::Result { - unimpl!(); - } - - pub fn read_vectored(&self, _: &mut [IoVecMut<'_>]) -> io::Result { - unimpl!(); - } - - pub fn peek(&self, _: &mut [u8]) -> io::Result { - unimpl!(); - } - - pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - unimpl!(); - } - - pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - unimpl!(); - } - - pub fn write(&self, _: &[u8]) -> io::Result { - unimpl!(); - } - - pub fn write_vectored(&self, _: &[IoVec<'_>]) -> io::Result { - unimpl!(); - } - - pub fn set_timeout(&self, _: Option, _: libc::c_int) -> io::Result<()> { - unimpl!(); - } - - pub fn timeout(&self, _: libc::c_int) -> io::Result> { - unimpl!(); - } - - pub fn shutdown(&self, _: Shutdown) -> io::Result<()> { - unimpl!(); - } - - pub fn set_nodelay(&self, _: bool) -> io::Result<()> { - unimpl!(); - } - - pub fn nodelay(&self) -> io::Result { - unimpl!(); - } - - pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - unimpl!(); - } - - pub fn take_error(&self) -> io::Result> { - unimpl!(); - } - } - - impl AsInner for Socket { - fn as_inner(&self) -> &libc::c_int { self.0.as_inner() } - } - - impl FromInner for Socket { - fn from_inner(fd: libc::c_int) -> Socket { Socket(FileDesc::new(fd)) } - } - - impl IntoInner for Socket { - fn into_inner(self) -> libc::c_int { self.0.into_raw() } - } - - pub struct TcpStream { - inner: Socket, - } - - impl TcpStream { - pub fn connect(_: io::Result<&SocketAddr>) -> io::Result { - unimpl!(); - } - - pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result { - unimpl!(); - } - - pub fn socket(&self) -> &Socket { &self.inner } - - pub fn into_socket(self) -> Socket { self.inner } - - pub fn set_read_timeout(&self, _: Option) -> io::Result<()> { - unimpl!(); - } - - pub fn set_write_timeout(&self, _: Option) -> io::Result<()> { - unimpl!(); - } - - pub fn read_timeout(&self) -> io::Result> { - unimpl!(); - } - - pub fn write_timeout(&self) -> io::Result> { - unimpl!(); - } - - pub fn peek(&self, _: &mut [u8]) -> io::Result { - unimpl!(); - } - - pub fn read(&self, _: &mut [u8]) -> io::Result { - unimpl!(); - } - - pub fn read_vectored(&self, _: &mut [IoVecMut<'_>]) -> io::Result { - unimpl!(); - } - - pub fn write(&self, _: &[u8]) -> io::Result { - unimpl!(); - } - - pub fn write_vectored(&self, _: &[IoVec<'_>]) -> io::Result { - unimpl!(); - } - - pub fn peer_addr(&self) -> io::Result { - unimpl!(); - } - - pub fn socket_addr(&self) -> io::Result { - unimpl!(); - } - - pub fn shutdown(&self, _: Shutdown) -> io::Result<()> { - unimpl!(); - } - - pub fn duplicate(&self) -> io::Result { - unimpl!(); - } - - pub fn set_nodelay(&self, _: bool) -> io::Result<()> { - unimpl!(); - } - - pub fn nodelay(&self) -> io::Result { - unimpl!(); - } - - pub fn set_ttl(&self, _: u32) -> io::Result<()> { - unimpl!(); - } - - pub fn ttl(&self) -> io::Result { - unimpl!(); - } - - pub fn take_error(&self) -> io::Result> { - unimpl!(); - } - - pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - unimpl!(); - } - } - - impl FromInner for TcpStream { - fn from_inner(socket: Socket) -> TcpStream { - TcpStream { inner: socket } - } - } - - impl fmt::Debug for TcpStream { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "No networking support available on L4Re") - } - } - - pub struct TcpListener { - inner: Socket, - } - - impl TcpListener { - pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { - unimpl!(); - } - - pub fn socket(&self) -> &Socket { &self.inner } - - pub fn into_socket(self) -> Socket { self.inner } - - pub fn socket_addr(&self) -> io::Result { - unimpl!(); - } - - pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { - unimpl!(); - } - - pub fn duplicate(&self) -> io::Result { - unimpl!(); - } - - pub fn set_ttl(&self, _: u32) -> io::Result<()> { - unimpl!(); - } - - pub fn ttl(&self) -> io::Result { - unimpl!(); - } - - pub fn set_only_v6(&self, _: bool) -> io::Result<()> { - unimpl!(); - } - - pub fn only_v6(&self) -> io::Result { - unimpl!(); - } - - pub fn take_error(&self) -> io::Result> { - unimpl!(); - } - - pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - unimpl!(); - } - } - - impl FromInner for TcpListener { - fn from_inner(socket: Socket) -> TcpListener { - TcpListener { inner: socket } - } - } - - impl fmt::Debug for TcpListener { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "No networking support available on L4Re.") - } - } - - pub struct UdpSocket { - inner: Socket, - } - - impl UdpSocket { - pub fn bind(_: io::Result<&SocketAddr>) -> io::Result { - unimpl!(); - } - - pub fn socket(&self) -> &Socket { &self.inner } - - pub fn into_socket(self) -> Socket { self.inner } - - pub fn peer_addr(&self) -> io::Result { - unimpl!(); - } - - pub fn socket_addr(&self) -> io::Result { - unimpl!(); - } - - pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - unimpl!(); - } - - pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - unimpl!(); - } - - pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result { - unimpl!(); - } - - pub fn duplicate(&self) -> io::Result { - unimpl!(); - } - - pub fn set_read_timeout(&self, _: Option) -> io::Result<()> { - unimpl!(); - } - - pub fn set_write_timeout(&self, _: Option) -> io::Result<()> { - unimpl!(); - } - - pub fn read_timeout(&self) -> io::Result> { - unimpl!(); - } - - pub fn write_timeout(&self) -> io::Result> { - unimpl!(); - } - - pub fn set_broadcast(&self, _: bool) -> io::Result<()> { - unimpl!(); - } - - pub fn broadcast(&self) -> io::Result { - unimpl!(); - } - - pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> { - unimpl!(); - } - - pub fn multicast_loop_v4(&self) -> io::Result { - unimpl!(); - } - - pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> { - unimpl!(); - } - - pub fn multicast_ttl_v4(&self) -> io::Result { - unimpl!(); - } - - pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> { - unimpl!(); - } - - pub fn multicast_loop_v6(&self) -> io::Result { - unimpl!(); - } - - pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) - -> io::Result<()> { - unimpl!(); - } - - pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) - -> io::Result<()> { - unimpl!(); - } - - pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) - -> io::Result<()> { - unimpl!(); - } - - pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) - -> io::Result<()> { - unimpl!(); - } - - pub fn set_ttl(&self, _: u32) -> io::Result<()> { - unimpl!(); - } - - pub fn ttl(&self) -> io::Result { - unimpl!(); - } - - pub fn take_error(&self) -> io::Result> { - unimpl!(); - } - - pub fn set_nonblocking(&self, _: bool) -> io::Result<()> { - unimpl!(); - } - - pub fn recv(&self, _: &mut [u8]) -> io::Result { - unimpl!(); - } - - pub fn peek(&self, _: &mut [u8]) -> io::Result { - unimpl!(); - } - - pub fn send(&self, _: &[u8]) -> io::Result { - unimpl!(); - } - - pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> { - unimpl!(); - } - } - - impl FromInner for UdpSocket { - fn from_inner(socket: Socket) -> UdpSocket { - UdpSocket { inner: socket } - } - } - - impl fmt::Debug for UdpSocket { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "No networking support on L4Re available.") - } - } - - pub struct LookupHost { - original: *mut libc::addrinfo, - cur: *mut libc::addrinfo, - } - - impl Iterator for LookupHost { - type Item = SocketAddr; - fn next(&mut self) -> Option { - None - } - } - - impl LookupHost { - pub fn port(&self) -> u16 { - unimpl!(); - } - } - - unsafe impl Sync for LookupHost {} - unsafe impl Send for LookupHost {} - - - impl TryFrom<&str> for LookupHost { - type Error = io::Error; - - fn try_from(_v: &str) -> io::Result { - unimpl!(); - } - } - - impl<'a> TryFrom<(&'a str, u16)> for LookupHost { - type Error = io::Error; - - fn try_from(_v: (&'a str, u16)) -> io::Result { - unimpl!(); - } - } -} diff --git a/src/libstd/sys/vxworks/memchr.rs b/src/libstd/sys/vxworks/memchr.rs index 1984678bdde4e..b5b4e6d9c134e 100644 --- a/src/libstd/sys/vxworks/memchr.rs +++ b/src/libstd/sys/vxworks/memchr.rs @@ -16,25 +16,6 @@ pub fn memchr(needle: u8, haystack: &[u8]) -> Option { } pub fn memrchr(needle: u8, haystack: &[u8]) -> Option { - - #[cfg(target_os = "linux")] - fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option { - // GNU's memrchr() will - unlike memchr() - error if haystack is empty. - if haystack.is_empty() {return None} - let p = unsafe { - libc::memrchr( - haystack.as_ptr() as *const libc::c_void, - needle as libc::c_int, - haystack.len()) - }; - if p.is_null() { - None - } else { - Some(p as usize - (haystack.as_ptr() as usize)) - } - } - - #[cfg(not(target_os = "linux"))] fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option { core::slice::memchr::memrchr(needle, haystack) } diff --git a/src/libstd/sys/vxworks/mod.rs b/src/libstd/sys/vxworks/mod.rs index b01bea03c1b52..1eff4fbcd83b7 100644 --- a/src/libstd/sys/vxworks/mod.rs +++ b/src/libstd/sys/vxworks/mod.rs @@ -7,14 +7,8 @@ pub use crate::os::vxworks as platform; pub use self::rand::hashmap_random_keys; pub use libc::strlen; -#[macro_use] -pub mod weak; - pub mod alloc; pub mod args; -pub mod android; -//#[cfg(feature = "backtrace")] -//pub mod backtrace; pub mod cmath; pub mod condvar; pub mod env; @@ -25,12 +19,7 @@ pub mod fs; pub mod memchr; pub mod io; pub mod mutex; -#[cfg(not(target_os = "l4re"))] pub mod net; -#[cfg(target_os = "l4re")] -mod l4re; -#[cfg(target_os = "l4re")] -pub use self::l4re::net; pub mod os; pub mod path; pub mod pipe; @@ -61,9 +50,6 @@ pub fn init() { unsafe fn reset_sigpipe() { } } -#[cfg(target_os = "android")] -pub use crate::sys::android::signal; -#[cfg(not(target_os = "android"))] pub use libc::signal; pub fn decode_error_kind(errno: i32) -> ErrorKind { diff --git a/src/libstd/sys/vxworks/net.rs b/src/libstd/sys/vxworks/net.rs index 686cea49a6ea8..aa6b93c860069 100644 --- a/src/libstd/sys/vxworks/net.rs +++ b/src/libstd/sys/vxworks/net.rs @@ -58,19 +58,6 @@ impl Socket { pub fn new_raw(fam: c_int, ty: c_int) -> io::Result { unsafe { - // On linux we first attempt to pass the SOCK_CLOEXEC flag to - // atomically create the socket and set it as CLOEXEC. Support for - // this option, however, was added in 2.6.27, and we still support - // 2.6.18 as a kernel, so if the returned error is EINVAL we - // fallthrough to the fallback. - if cfg!(target_os = "linux") { - match cvt(libc::socket(fam, ty | SOCK_CLOEXEC, 0)) { - Ok(fd) => return Ok(Socket(FileDesc::new(fd))), - Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {} - Err(e) => return Err(e), - } - } - let fd = cvt(libc::socket(fam, ty, 0))?; let fd = FileDesc::new(fd); fd.set_cloexec()?; diff --git a/src/libstd/sys/vxworks/process/process_common.rs b/src/libstd/sys/vxworks/process/process_common.rs index db4e80c216c12..9fce5f5811f35 100644 --- a/src/libstd/sys/vxworks/process/process_common.rs +++ b/src/libstd/sys/vxworks/process/process_common.rs @@ -422,46 +422,12 @@ mod tests { } } - // Android with api less than 21 define sig* functions inline, so it is not - // available for dynamic link. Implementing sigemptyset and sigaddset allow us - // to support older Android version (independent of libc version). - // The following implementations are based on https://git.io/vSkNf - - #[cfg(not(target_os = "android"))] extern { - #[cfg_attr(target_os = "netbsd", link_name = "__sigemptyset14")] fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int; - - #[cfg_attr(target_os = "netbsd", link_name = "__sigaddset14")] fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int; } - #[cfg(target_os = "android")] - unsafe fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int { - libc::memset(set as *mut _, 0, mem::size_of::()); - return 0; - } - - #[cfg(target_os = "android")] - unsafe fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int { - use crate::slice; - - let raw = slice::from_raw_parts_mut(set as *mut u8, mem::size_of::()); - let bit = (signum - 1) as usize; - raw[bit / 8] |= 1 << (bit % 8); - return 0; - } - - // See #14232 for more information, but it appears that signal delivery to a - // newly spawned process may just be raced in the macOS, so to prevent this - // test from being flaky we ignore it on macOS. #[test] - #[cfg_attr(target_os = "macos", ignore)] - // When run under our current QEMU emulation test suite this test fails, - // although the reason isn't very clear as to why. For now this test is - // ignored there. - #[cfg_attr(target_arch = "arm", ignore)] - #[cfg_attr(target_arch = "aarch64", ignore)] fn test_process_mask() { unsafe { // Test to make sure that a signal mask does not get inherited. diff --git a/src/libstd/sys/vxworks/stack_overflow.rs b/src/libstd/sys/vxworks/stack_overflow.rs index 561279e82785c..08e7b310ca1b8 100644 --- a/src/libstd/sys/vxworks/stack_overflow.rs +++ b/src/libstd/sys/vxworks/stack_overflow.rs @@ -23,174 +23,6 @@ impl Drop for Handler { } } -#[cfg(any(target_os = "linux", - target_os = "macos", - target_os = "bitrig", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "solaris", - all(target_os = "netbsd", not(target_vendor = "rumprun")), - target_os = "openbsd"))] -mod imp { - use super::Handler; - use crate::mem; - use crate::ptr; - - use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE}; - use libc::{sigaction, SIGBUS, SIG_DFL, - SA_SIGINFO, SA_ONSTACK, sighandler_t}; - use libc::{mmap, munmap}; - use libc::{SIGSEGV, PROT_READ, PROT_WRITE, MAP_PRIVATE, MAP_ANON}; - use libc::MAP_FAILED; - - use crate::sys_common::thread_info; - - - #[cfg(any(target_os = "linux", target_os = "android"))] - unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize { - #[repr(C)] - struct siginfo_t { - a: [libc::c_int; 3], // si_signo, si_errno, si_code - si_addr: *mut libc::c_void, - } - - (*(info as *const siginfo_t)).si_addr as usize - } - - #[cfg(not(any(target_os = "linux", target_os = "android")))] - unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize { - (*info).si_addr as usize - } - - // Signal handler for the SIGSEGV and SIGBUS handlers. We've got guard pages - // (unmapped pages) at the end of every thread's stack, so if a thread ends - // up running into the guard page it'll trigger this handler. We want to - // detect these cases and print out a helpful error saying that the stack - // has overflowed. All other signals, however, should go back to what they - // were originally supposed to do. - // - // This handler currently exists purely to print an informative message - // whenever a thread overflows its stack. We then abort to exit and - // indicate a crash, but to avoid a misleading SIGSEGV that might lead - // users to believe that unsafe code has accessed an invalid pointer; the - // SIGSEGV encountered when overflowing the stack is expected and - // well-defined. - // - // If this is not a stack overflow, the handler un-registers itself and - // then returns (to allow the original signal to be delivered again). - // Returning from this kind of signal handler is technically not defined - // to work when reading the POSIX spec strictly, but in practice it turns - // out many large systems and all implementations allow returning from a - // signal handler to work. For a more detailed explanation see the - // comments on #26458. - unsafe extern fn signal_handler(signum: libc::c_int, - info: *mut libc::siginfo_t, - _data: *mut libc::c_void) { - use crate::sys_common::util::report_overflow; - - let guard = thread_info::stack_guard().unwrap_or(0..0); - let addr = siginfo_si_addr(info); - - // If the faulting address is within the guard page, then we print a - // message saying so and abort. - if guard.start <= addr && addr < guard.end { - report_overflow(); - rtabort!("stack overflow"); - } else { - // Unregister ourselves by reverting back to the default behavior. - let mut action: sigaction = mem::zeroed(); - action.sa_sigaction = SIG_DFL; - sigaction(signum, &action, ptr::null_mut()); - - // See comment above for why this function returns. - } - } - - static mut MAIN_ALTSTACK: *mut libc::c_void = ptr::null_mut(); - - pub unsafe fn init() { - let mut action: sigaction = mem::zeroed(); - action.sa_flags = SA_SIGINFO | SA_ONSTACK; - action.sa_sigaction = signal_handler as sighandler_t; - sigaction(SIGSEGV, &action, ptr::null_mut()); - sigaction(SIGBUS, &action, ptr::null_mut()); - - let handler = make_handler(); - MAIN_ALTSTACK = handler._data; - mem::forget(handler); - } - - pub unsafe fn cleanup() { - Handler { _data: MAIN_ALTSTACK }; - } - - unsafe fn get_stackp() -> *mut libc::c_void { - let stackp = mmap(ptr::null_mut(), - SIGSTKSZ, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON, - -1, - 0); - if stackp == MAP_FAILED { - panic!("failed to allocate an alternative stack"); - } - stackp - } - - #[cfg(any(target_os = "linux", - target_os = "macos", - target_os = "bitrig", - target_os = "freebsd", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris"))] - unsafe fn get_stack() -> libc::stack_t { - libc::stack_t { ss_sp: get_stackp(), ss_flags: 0, ss_size: SIGSTKSZ } - } - - #[cfg(target_os = "dragonfly")] - unsafe fn get_stack() -> libc::stack_t { - libc::stack_t { ss_sp: get_stackp() as *mut i8, ss_flags: 0, ss_size: SIGSTKSZ } - } - - pub unsafe fn make_handler() -> Handler { - let mut stack = mem::zeroed(); - sigaltstack(ptr::null(), &mut stack); - // Configure alternate signal stack, if one is not already set. - if stack.ss_flags & SS_DISABLE != 0 { - stack = get_stack(); - sigaltstack(&stack, ptr::null_mut()); - Handler { _data: stack.ss_sp as *mut libc::c_void } - } else { - Handler { _data: ptr::null_mut() } - } - } - - pub unsafe fn drop_handler(handler: &mut Handler) { - if !handler._data.is_null() { - let stack = libc::stack_t { - ss_sp: ptr::null_mut(), - ss_flags: SS_DISABLE, - // Workaround for bug in macOS implementation of sigaltstack - // UNIX2003 which returns ENOMEM when disabling a stack while - // passing ss_size smaller than MINSIGSTKSZ. According to POSIX - // both ss_sp and ss_size should be ignored in this case. - ss_size: SIGSTKSZ, - }; - sigaltstack(&stack, ptr::null_mut()); - munmap(handler._data, SIGSTKSZ); - } - } -} - -#[cfg(not(any(target_os = "linux", - target_os = "macos", - target_os = "bitrig", - target_os = "dragonfly", - target_os = "freebsd", - target_os = "solaris", - all(target_os = "netbsd", not(target_vendor = "rumprun")), - target_os = "openbsd")))] mod imp { use crate::ptr; diff --git a/src/libstd/sys/vxworks/thread.rs b/src/libstd/sys/vxworks/thread.rs index 810dbad7284e3..58af8cbe48e36 100644 --- a/src/libstd/sys/vxworks/thread.rs +++ b/src/libstd/sys/vxworks/thread.rs @@ -1,4 +1,3 @@ -//use crate::boxed::FnBox; use crate::cmp; use crate::ffi::CStr; use crate::io; @@ -9,10 +8,7 @@ use crate::time::Duration; use crate::sys_common::thread::*; -#[cfg(not(target_os = "l4re"))] pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024; -#[cfg(target_os = "l4re")] -pub const DEFAULT_MIN_STACK_SIZE: usize = 1024 * 1024; pub struct Thread { id: libc::pthread_t, @@ -25,18 +21,11 @@ unsafe impl Sync for Thread {} // The pthread_attr_setstacksize symbol doesn't exist in the emscripten libc, // so we have to not link to it to satisfy emcc's ERROR_ON_UNDEFINED_SYMBOLS. -#[cfg(not(target_os = "emscripten"))] unsafe fn pthread_attr_setstacksize(attr: *mut libc::pthread_attr_t, stack_size: libc::size_t) -> libc::c_int { libc::pthread_attr_setstacksize(attr, stack_size) } -#[cfg(target_os = "emscripten")] -unsafe fn pthread_attr_setstacksize(_attr: *mut libc::pthread_attr_t, - _stack_size: libc::size_t) -> libc::c_int { - panic!() -} - impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements pub unsafe fn new(stack: usize, p: Box) @@ -149,31 +138,6 @@ pub mod guard { pub unsafe fn deinit() {} } -// glibc >= 2.15 has a __pthread_get_minstack() function that returns -// PTHREAD_STACK_MIN plus however many bytes are needed for thread-local -// storage. We need that information to avoid blowing up when a small stack -// is created in an application with big thread-local storage requirements. -// See #6233 for rationale and details. -#[cfg(target_os = "linux")] -#[allow(deprecated)] -fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize { - weak!(fn __pthread_get_minstack(*const libc::pthread_attr_t) -> libc::size_t); - - match __pthread_get_minstack.get() { - None => libc::PTHREAD_STACK_MIN, - Some(f) => unsafe { f(attr) }, - } -} - -// No point in looking up __pthread_get_minstack() on non-glibc -// platforms. -#[cfg(all(not(target_os = "linux"), - not(target_os = "netbsd")))] fn min_stack_size(_: *const libc::pthread_attr_t) -> usize { libc::PTHREAD_STACK_MIN } - -#[cfg(target_os = "netbsd")] -fn min_stack_size(_: *const libc::pthread_attr_t) -> usize { - 2048 // just a guess -} From fe4cdd3078d43fc9d462e27f9dddcdef34ebe98e Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 23 Jul 2019 20:30:57 +0200 Subject: [PATCH 14/22] Disable d32 on armv6 hf targets --- src/librustc_target/spec/arm_unknown_linux_gnueabihf.rs | 2 +- src/librustc_target/spec/arm_unknown_linux_musleabihf.rs | 2 +- src/librustc_target/spec/armv6_unknown_freebsd.rs | 2 +- src/librustc_target/spec/armv6_unknown_netbsd_eabihf.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_target/spec/arm_unknown_linux_gnueabihf.rs b/src/librustc_target/spec/arm_unknown_linux_gnueabihf.rs index 8eb19a6518a3f..3c63371d12192 100644 --- a/src/librustc_target/spec/arm_unknown_linux_gnueabihf.rs +++ b/src/librustc_target/spec/arm_unknown_linux_gnueabihf.rs @@ -16,7 +16,7 @@ pub fn target() -> TargetResult { linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { - features: "+strict-align,+v6,+vfp2".to_string(), + features: "+strict-align,+v6,+vfp2,-d32".to_string(), abi_blacklist: super::arm_base::abi_blacklist(), target_mcount: "\u{1}__gnu_mcount_nc".to_string(), .. base diff --git a/src/librustc_target/spec/arm_unknown_linux_musleabihf.rs b/src/librustc_target/spec/arm_unknown_linux_musleabihf.rs index 496a0c4a43a7e..fb5a16f74c00b 100644 --- a/src/librustc_target/spec/arm_unknown_linux_musleabihf.rs +++ b/src/librustc_target/spec/arm_unknown_linux_musleabihf.rs @@ -5,7 +5,7 @@ pub fn target() -> TargetResult { // Most of these settings are copied from the arm_unknown_linux_gnueabihf // target. - base.features = "+strict-align,+v6,+vfp2".to_string(); + base.features = "+strict-align,+v6,+vfp2,-d32".to_string(); base.max_atomic_width = Some(64); Ok(Target { // It's important we use "gnueabihf" and not "musleabihf" here. LLVM diff --git a/src/librustc_target/spec/armv6_unknown_freebsd.rs b/src/librustc_target/spec/armv6_unknown_freebsd.rs index efbbee959ed95..06233f7caa351 100644 --- a/src/librustc_target/spec/armv6_unknown_freebsd.rs +++ b/src/librustc_target/spec/armv6_unknown_freebsd.rs @@ -15,7 +15,7 @@ pub fn target() -> TargetResult { linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { - features: "+v6,+vfp2".to_string(), + features: "+v6,+vfp2,-d32".to_string(), max_atomic_width: Some(64), abi_blacklist: super::arm_base::abi_blacklist(), target_mcount: "\u{1}__gnu_mcount_nc".to_string(), diff --git a/src/librustc_target/spec/armv6_unknown_netbsd_eabihf.rs b/src/librustc_target/spec/armv6_unknown_netbsd_eabihf.rs index b76c39ac75b8b..40411befcfc2b 100644 --- a/src/librustc_target/spec/armv6_unknown_netbsd_eabihf.rs +++ b/src/librustc_target/spec/armv6_unknown_netbsd_eabihf.rs @@ -16,7 +16,7 @@ pub fn target() -> TargetResult { linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { - features: "+v6,+vfp2".to_string(), + features: "+v6,+vfp2,-d32".to_string(), abi_blacklist: super::arm_base::abi_blacklist(), target_mcount: "__mcount".to_string(), .. base From 71717b951a2f87720d9d8926e9a21353c120f700 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 23 Jul 2019 22:00:25 +0200 Subject: [PATCH 15/22] Initialize the MSP430 AsmParser if available --- src/librustc_llvm/build.rs | 4 ++++ src/librustc_llvm/lib.rs | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 21fa872c8dadb..07d2e6dc28c2c 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -119,6 +119,10 @@ fn main() { println!("cargo:rustc-cfg=llvm_component=\"{}\"", component); } + if major >= 9 { + println!("cargo:rustc-cfg=llvm_has_msp430_asm_parser"); + } + // Link in our own LLVM shims, compiled with the same flags as LLVM let mut cmd = Command::new(&llvm_config); cmd.arg("--cxxflags"); diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index bdf6b09185735..dea7e6ae0a2ab 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -76,6 +76,8 @@ pub fn initialize_available_targets() { LLVMInitializeMSP430Target, LLVMInitializeMSP430TargetMC, LLVMInitializeMSP430AsmPrinter); + init_target!(all(llvm_component = "msp430", llvm_has_msp430_asm_parser), + LLVMInitializeMSP430AsmParser); init_target!(llvm_component = "riscv", LLVMInitializeRISCVTargetInfo, LLVMInitializeRISCVTarget, From 61b680b30ee936312aafeafed4f0593057ba5937 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 23 Jul 2019 07:16:59 -0700 Subject: [PATCH 16/22] Attempt to fix backtrace tests on i686-msvc Some fixes for i686-msvc and Windows have landed on the `backtrace` crate but hadn't made their way here yet. Let's update that and see if it passes CI. --- Cargo.lock | 25 +++++++++--------------- src/test/run-pass/backtrace-debuginfo.rs | 1 - src/test/run-pass/backtrace.rs | 1 - 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bdc746c0bb0e0..cb2d22e7d36f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -97,18 +97,12 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "autocfg" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "backtrace" -version = "0.3.29" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "backtrace-sys 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", @@ -118,7 +112,7 @@ dependencies = [ [[package]] name = "backtrace-sys" -version = "0.1.27" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", @@ -868,7 +862,7 @@ name = "error-chain" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.29 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -883,7 +877,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.29 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2513,7 +2507,7 @@ name = "rustc" version = "0.0.0" dependencies = [ "arena 0.0.0", - "backtrace 0.3.29 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "chalk-engine 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3491,7 +3485,7 @@ name = "std" version = "0.0.0" dependencies = [ "alloc 0.0.0", - "backtrace 0.3.29 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4308,9 +4302,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf" -"checksum backtrace 0.3.29 (registry+https://github.com/rust-lang/crates.io-index)" = "2d631cd7af21b7ff796293f1990104e3cdb606852863bac32f000c193aa35dfb" -"checksum backtrace-sys 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)" = "6ea90dd7b012b3d1a2cb6bec16670a0db2c95d4e931e84f4047e0460c1b34c8d" +"checksum backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)" = "88fb679bc9af8fa639198790a77f52d345fe13656c08b43afa9424c206b731c6" +"checksum backtrace-sys 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "5b3a000b9c543553af61bc01cbfc403b04b5caa9e421033866f2e98061eb3e61" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" "checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" diff --git a/src/test/run-pass/backtrace-debuginfo.rs b/src/test/run-pass/backtrace-debuginfo.rs index a2a934513d2f7..af5ccb45727a1 100644 --- a/src/test/run-pass/backtrace-debuginfo.rs +++ b/src/test/run-pass/backtrace-debuginfo.rs @@ -10,7 +10,6 @@ // ignore-pretty issue #37195 // ignore-cloudabi spawning processes is not supported // ignore-emscripten spawning processes is not supported -// ignore-msvc issue #62844 // ignore-sgx no processes // normalize-stderr-test ".*\n" -> "" diff --git a/src/test/run-pass/backtrace.rs b/src/test/run-pass/backtrace.rs index 93e8c9f172997..c73ba293ee25b 100644 --- a/src/test/run-pass/backtrace.rs +++ b/src/test/run-pass/backtrace.rs @@ -2,7 +2,6 @@ // ignore-cloudabi spawning processes is not supported // ignore-emscripten spawning processes is not supported // ignore-openbsd no support for libbacktrace without filename -// ignore-msvc issue #62844 // ignore-sgx no processes // compile-flags:-g From 70c817aee3aa204122b64cdfc2db05fa182da1c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 24 Jul 2019 16:10:42 -0700 Subject: [PATCH 17/22] Allow lexer to recover from some homoglyphs --- src/libsyntax/parse/lexer/mod.rs | 5 +- src/libsyntax/parse/lexer/unicode_chars.rs | 65 ++++++++++--------- ...nicode-confusable-in-float-literal-expt.rs | 1 + ...de-confusable-in-float-literal-expt.stderr | 11 +++- src/test/ui/parser/recover-from-homoglyph.rs | 4 ++ .../ui/parser/recover-from-homoglyph.stderr | 22 +++++++ 6 files changed, 74 insertions(+), 34 deletions(-) create mode 100644 src/test/ui/parser/recover-from-homoglyph.rs create mode 100644 src/test/ui/parser/recover-from-homoglyph.stderr diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index b97801a50d472..412ed8f04b343 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -389,7 +389,10 @@ impl<'a> StringReader<'a> { self.pos, "unknown start of token", c); - unicode_chars::check_for_substitution(self, start, c, &mut err); + if let Some(t) = unicode_chars::check_for_substitution(self, start, c, &mut err) { + err.emit(); + return Ok(t); + } return Err(err) } }; diff --git a/src/libsyntax/parse/lexer/unicode_chars.rs b/src/libsyntax/parse/lexer/unicode_chars.rs index b728a9e1988c8..bfa1606a0d201 100644 --- a/src/libsyntax/parse/lexer/unicode_chars.rs +++ b/src/libsyntax/parse/lexer/unicode_chars.rs @@ -4,6 +4,7 @@ use super::StringReader; use errors::{Applicability, DiagnosticBuilder}; use syntax_pos::{BytePos, Pos, Span, NO_EXPANSION}; +use crate::parse::token; #[rustfmt::skip] // for line breaks const UNICODE_ARRAY: &[(char, &str, char)] = &[ @@ -297,32 +298,32 @@ const UNICODE_ARRAY: &[(char, &str, char)] = &[ ('>', "Fullwidth Greater-Than Sign", '>'), ]; -const ASCII_ARRAY: &[(char, &str)] = &[ - (' ', "Space"), - ('_', "Underscore"), - ('-', "Minus/Hyphen"), - (',', "Comma"), - (';', "Semicolon"), - (':', "Colon"), - ('!', "Exclamation Mark"), - ('?', "Question Mark"), - ('.', "Period"), - ('\'', "Single Quote"), - ('"', "Quotation Mark"), - ('(', "Left Parenthesis"), - (')', "Right Parenthesis"), - ('[', "Left Square Bracket"), - (']', "Right Square Bracket"), - ('{', "Left Curly Brace"), - ('}', "Right Curly Brace"), - ('*', "Asterisk"), - ('/', "Slash"), - ('\\', "Backslash"), - ('&', "Ampersand"), - ('+', "Plus Sign"), - ('<', "Less-Than Sign"), - ('=', "Equals Sign"), - ('>', "Greater-Than Sign"), +const ASCII_ARRAY: &[(char, &str, Option)] = &[ + (' ', "Space", Some(token::Whitespace)), + ('_', "Underscore", None), + ('-', "Minus/Hyphen", Some(token::BinOp(token::Minus))), + (',', "Comma", Some(token::Comma)), + (';', "Semicolon", Some(token::Semi)), + (':', "Colon", Some(token::Colon)), + ('!', "Exclamation Mark", Some(token::Not)), + ('?', "Question Mark", Some(token::Question)), + ('.', "Period", Some(token::Dot)), + ('\'', "Single Quote", None), // Literals are already lexed by this point, so we can't recover + ('"', "Quotation Mark", None), // gracefully just by spitting the correct token out. + ('(', "Left Parenthesis", Some(token::OpenDelim(token::Paren))), + (')', "Right Parenthesis", Some(token::CloseDelim(token::Paren))), + ('[', "Left Square Bracket", Some(token::OpenDelim(token::Bracket))), + (']', "Right Square Bracket", Some(token::CloseDelim(token::Bracket))), + ('{', "Left Curly Brace", Some(token::OpenDelim(token::Brace))), + ('}', "Right Curly Brace", Some(token::CloseDelim(token::Brace))), + ('*', "Asterisk", Some(token::BinOp(token::Star))), + ('/', "Slash", Some(token::BinOp(token::Slash))), + ('\\', "Backslash", None), + ('&', "Ampersand", Some(token::BinOp(token::And))), + ('+', "Plus Sign", Some(token::BinOp(token::Plus))), + ('<', "Less-Than Sign", Some(token::Lt)), + ('=', "Equals Sign", Some(token::Eq)), + ('>', "Greater-Than Sign", Some(token::Gt)), ]; crate fn check_for_substitution<'a>( @@ -330,20 +331,20 @@ crate fn check_for_substitution<'a>( pos: BytePos, ch: char, err: &mut DiagnosticBuilder<'a>, -) -> bool { +) -> Option { let (u_name, ascii_char) = match UNICODE_ARRAY.iter().find(|&&(c, _, _)| c == ch) { Some(&(_u_char, u_name, ascii_char)) => (u_name, ascii_char), - None => return false, + None => return None, }; let span = Span::new(pos, pos + Pos::from_usize(ch.len_utf8()), NO_EXPANSION); - let ascii_name = match ASCII_ARRAY.iter().find(|&&(c, _)| c == ascii_char) { - Some((_ascii_char, ascii_name)) => ascii_name, + let (ascii_name, token) = match ASCII_ARRAY.iter().find(|&&(c, _, _)| c == ascii_char) { + Some((_ascii_char, ascii_name, token)) => (ascii_name, token), None => { let msg = format!("substitution character not found for '{}'", ch); reader.sess.span_diagnostic.span_bug_no_panic(span, &msg); - return false; + return None; } }; @@ -371,7 +372,7 @@ crate fn check_for_substitution<'a>( ); err.span_suggestion(span, &msg, ascii_char.to_string(), Applicability::MaybeIncorrect); } - true + token.clone() } /// Extract string if found at current position with given delimiters diff --git a/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.rs b/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.rs index 5c2c3b8ec61d5..66d562d2eb519 100644 --- a/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.rs +++ b/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.rs @@ -1,5 +1,6 @@ const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e−11; // m³⋅kg⁻¹⋅s⁻² //~^ ERROR expected at least one digit in exponent //~| ERROR unknown start of token: \u{2212} +//~| ERROR cannot subtract `{integer}` from `{float}` fn main() {} diff --git a/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr b/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr index 07653c791db1c..9ee86adec52d9 100644 --- a/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr +++ b/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr @@ -14,5 +14,14 @@ help: Unicode character '−' (Minus Sign) looks like '-' (Minus/Hyphen), but it LL | const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e-11; // m³⋅kg⁻¹⋅s⁻² | ^ -error: aborting due to 2 previous errors +error[E0277]: cannot subtract `{integer}` from `{float}` + --> $DIR/issue-49746-unicode-confusable-in-float-literal-expt.rs:1:53 + | +LL | const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e−11; // m³⋅kg⁻¹⋅s⁻² + | ^ no implementation for `{float} - {integer}` + | + = help: the trait `std::ops::Sub<{integer}>` is not implemented for `{float}` + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/parser/recover-from-homoglyph.rs b/src/test/ui/parser/recover-from-homoglyph.rs new file mode 100644 index 0000000000000..99ce0d1a630df --- /dev/null +++ b/src/test/ui/parser/recover-from-homoglyph.rs @@ -0,0 +1,4 @@ +fn main() { + println!(""); //~ ERROR unknown start of token: \u{37e} + let x: usize = (); //~ ERROR mismatched types +} diff --git a/src/test/ui/parser/recover-from-homoglyph.stderr b/src/test/ui/parser/recover-from-homoglyph.stderr new file mode 100644 index 0000000000000..424d492b7ba64 --- /dev/null +++ b/src/test/ui/parser/recover-from-homoglyph.stderr @@ -0,0 +1,22 @@ +error: unknown start of token: \u{37e} + --> $DIR/recover-from-homoglyph.rs:2:17 + | +LL | println!(""); + | ^ +help: Unicode character ';' (Greek Question Mark) looks like ';' (Semicolon), but it is not + | +LL | println!(""); + | ^ + +error[E0308]: mismatched types + --> $DIR/recover-from-homoglyph.rs:3:20 + | +LL | let x: usize = (); + | ^^ expected usize, found () + | + = note: expected type `usize` + found type `()` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From b01b5b911f3bb209ee619055a154cd81ca0674be Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Thu, 25 Jul 2019 11:51:08 +0200 Subject: [PATCH 18/22] ci: gate toolstate repo pushes on the TOOLSTATE_PUBLISH envvar Unfortunately due to an Azure quirk the TOOLSTATE_REPO_ACCESS_TOKEN is not suitable to gate whether to push new commits to the repo, as if it's not defined on the Azure side it will actually be set to the literal `$(TOOLSTATE_REPO_ACCESS_TOKEN)`, which screws everything up. This instead adds another, non-secret environment variable to gate publishing: TOOLSTATE_PUBLISH. As non-secret environment variables behave correctly this fixes the issue. --- src/ci/docker/x86_64-gnu-tools/checktools.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/x86_64-gnu-tools/checktools.sh b/src/ci/docker/x86_64-gnu-tools/checktools.sh index 9995d2aac7f24..2191d5d6e4680 100755 --- a/src/ci/docker/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/x86_64-gnu-tools/checktools.sh @@ -112,7 +112,7 @@ $COMMIT\t$(cat "$TOOLSTATE_FILE") } if [ "$RUST_RELEASE_CHANNEL" = nightly ]; then - if [ -n "${TOOLSTATE_REPO_ACCESS_TOKEN+is_set}" ]; then + if [ -n "${TOOLSTATE_PUBLISH+is_set}" ]; then . "$(dirname $0)/repo.sh" MESSAGE_FILE=$(mktemp -t msg.XXXXXX) echo "($OS CI update)" > "$MESSAGE_FILE" From 0e022f87e7103fcb4b62ae32a467b92503abb178 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Thu, 25 Jul 2019 13:26:20 -0400 Subject: [PATCH 19/22] Remove needless indirection through Rc NamedMatch is already cheap to clone due to Lrc's inside. --- src/libsyntax/ext/tt/macro_parser.rs | 8 +++----- src/libsyntax/ext/tt/macro_rules.rs | 4 ++-- src/libsyntax/ext/tt/transcribe.rs | 24 +++++++++++------------- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index ae1979540ff8d..dbf14daa30e75 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -92,7 +92,6 @@ use rustc_data_structures::sync::Lrc; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::mem; use std::ops::{Deref, DerefMut}; -use std::rc::Rc; // To avoid costly uniqueness checks, we require that `MatchSeq` always has a nonempty body. @@ -280,7 +279,7 @@ pub enum ParseResult { /// A `ParseResult` where the `Success` variant contains a mapping of `Ident`s to `NamedMatch`es. /// This represents the mapping of metavars to the token trees they bind to. -pub type NamedParseResult = ParseResult>>; +pub type NamedParseResult = ParseResult>; /// Count how many metavars are named in the given matcher `ms`. pub fn count_names(ms: &[TokenTree]) -> usize { @@ -373,7 +372,7 @@ fn nameize>( sess: &ParseSess, m: &TokenTree, res: &mut I, - ret_val: &mut FxHashMap>, + ret_val: &mut FxHashMap, ) -> Result<(), (syntax_pos::Span, String)> { match *m { TokenTree::Sequence(_, ref seq) => for next_m in &seq.tts { @@ -390,8 +389,7 @@ fn nameize>( TokenTree::MetaVarDecl(sp, bind_name, _) => { match ret_val.entry(bind_name) { Vacant(spot) => { - // FIXME(simulacrum): Don't construct Rc here - spot.insert(Rc::new(res.next().unwrap())); + spot.insert(res.next().unwrap()); } Occupied(..) => { return Err((sp, format!("duplicated bind name: {}", bind_name))) diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 4503cea0f10c8..c96290ce27095 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -308,7 +308,7 @@ pub fn compile( let mut valid = true; // Extract the arguments: - let lhses = match *argument_map[&lhs_nm] { + let lhses = match argument_map[&lhs_nm] { MatchedSeq(ref s, _) => s .iter() .map(|m| { @@ -335,7 +335,7 @@ pub fn compile( _ => sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs"), }; - let rhses = match *argument_map[&rhs_nm] { + let rhses = match argument_map[&rhs_nm] { MatchedSeq(ref s, _) => s .iter() .map(|m| { diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index fa93c5a904eb0..214e721fd1506 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -12,7 +12,6 @@ use smallvec::{smallvec, SmallVec}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use std::mem; -use std::rc::Rc; /// An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`). enum Frame { @@ -65,9 +64,9 @@ impl Iterator for Frame { /// `transcribe` would return a `TokenStream` containing `println!("{}", stringify!(bar));`. /// /// Along the way, we do some additional error checking. -pub fn transcribe( +pub(super) fn transcribe( cx: &ExtCtxt<'_>, - interp: &FxHashMap>, + interp: &FxHashMap, src: Vec, ) -> TokenStream { // Nothing for us to transcribe... @@ -212,7 +211,7 @@ pub fn transcribe( // Find the matched nonterminal from the macro invocation, and use it to replace // the meta-var. if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) { - if let MatchedNonterminal(ref nt) = *cur_matched { + if let MatchedNonterminal(ref nt) = cur_matched { // FIXME #2887: why do we apply a mark when matching a token tree meta-var // (e.g. `$x:tt`), but not when we are matching any other type of token // tree? @@ -273,18 +272,17 @@ pub fn transcribe( /// See the definition of `repeats` in the `transcribe` function. `repeats` is used to descend /// into the right place in nested matchers. If we attempt to descend too far, the macro writer has /// made a mistake, and we return `None`. -fn lookup_cur_matched( +fn lookup_cur_matched<'a>( ident: Ident, - interpolations: &FxHashMap>, + interpolations: &'a FxHashMap, repeats: &[(usize, usize)], -) -> Option> { +) -> Option<&'a NamedMatch> { interpolations.get(&ident).map(|matched| { - let mut matched = matched.clone(); + let mut matched = matched; for &(idx, _) in repeats { - let m = matched.clone(); - match *m { + match matched { MatchedNonterminal(_) => break, - MatchedSeq(ref ads, _) => matched = Rc::new(ads[idx].clone()), + MatchedSeq(ref ads, _) => matched = ads.get(idx).unwrap(), } } @@ -343,7 +341,7 @@ impl LockstepIterSize { /// multiple nested matcher sequences. fn lockstep_iter_size( tree: "ed::TokenTree, - interpolations: &FxHashMap>, + interpolations: &FxHashMap, repeats: &[(usize, usize)], ) -> LockstepIterSize { use quoted::TokenTree; @@ -360,7 +358,7 @@ fn lockstep_iter_size( } TokenTree::MetaVar(_, name) | TokenTree::MetaVarDecl(_, name, _) => { match lookup_cur_matched(name, interpolations, repeats) { - Some(matched) => match *matched { + Some(matched) => match matched { MatchedNonterminal(_) => LockstepIterSize::Unconstrained, MatchedSeq(ref ads, _) => LockstepIterSize::Constraint(ads.len(), name), }, From dd0f2ac250e0f733cfbff5498c04312c96bb34fa Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 25 Jul 2019 21:03:53 +0200 Subject: [PATCH 20/22] librustc_errors: Support ui-testing flag in annotate-snippet emitter This adds support for the `-Z ui-testing` flag to the new annotate-snippet diagnostic emitter. The support for the flag was added to `annotate-snippet-rs` in these PRs: * https://github.com/rust-lang/annotate-snippets-rs/pull/3 * https://github.com/rust-lang/annotate-snippets-rs/pull/5 Closes #61811 --- Cargo.lock | 8 +++++++- src/librustc_errors/Cargo.toml | 2 +- src/librustc_errors/annotate_snippet_emitter_writer.rs | 8 ++------ src/test/ui/annotate-snippet/missing-type.stderr | 10 +++++----- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9a9c89cd9c199..ec26f11c4e5b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -65,6 +65,11 @@ dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "annotate-snippets" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "ansi_term" version = "0.11.0" @@ -3073,7 +3078,7 @@ dependencies = [ name = "rustc_errors" version = "0.0.0" dependencies = [ - "annotate-snippets 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_data_structures 0.0.0", @@ -4492,6 +4497,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ammonia 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8b93ecb80665873703bf3b0a77f369c96b183d8e0afaf30a3ff5ff07dfc6409" "checksum ammonia 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c799ecf1ad77acb48b643e2f45b12d60ee41576287fc575031aa020de88b8f45" "checksum annotate-snippets 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e8bcdcd5b291ce85a78f2b9d082a8de9676c12b1840d386d67bc5eea6f9d2b4e" +"checksum annotate-snippets 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7021ce4924a3f25f802b2cccd1af585e39ea1a363a1aa2e72afe54b67a3a7a7" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arc-swap 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1025aeae2b664ca0ea726a89d574fe8f4e77dd712d443236ad1de00379450cf6" "checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" diff --git a/src/librustc_errors/Cargo.toml b/src/librustc_errors/Cargo.toml index 4df9632cce26b..9f83d46fd815b 100644 --- a/src/librustc_errors/Cargo.toml +++ b/src/librustc_errors/Cargo.toml @@ -17,4 +17,4 @@ rustc_data_structures = { path = "../librustc_data_structures" } unicode-width = "0.1.4" atty = "0.2" termcolor = "1.0" -annotate-snippets = "0.5.0" +annotate-snippets = "0.6.1" diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs index 3641d355ef19c..96a9b6c5c4f7f 100644 --- a/src/librustc_errors/annotate_snippet_emitter_writer.rs +++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs @@ -23,7 +23,7 @@ pub struct AnnotateSnippetEmitterWriter { source_map: Option>, /// If true, hides the longer explanation text short_message: bool, - /// If true, will normalize line numbers with LL to prevent noise in UI test diffs. + /// If true, will normalize line numbers with `LL` to prevent noise in UI test diffs. ui_testing: bool, } @@ -173,10 +173,6 @@ impl AnnotateSnippetEmitterWriter { /// Allows to modify `Self` to enable or disable the `ui_testing` flag. /// /// If this is set to true, line numbers will be normalized as `LL` in the output. - // FIXME(#59346): This method is used via the public interface, but setting the `ui_testing` - // flag currently does not anonymize line numbers. We would have to add the `maybe_anonymized` - // method from `emitter.rs` and implement rust-lang/annotate-snippets-rs#2 in order to - // anonymize line numbers. pub fn ui_testing(mut self, ui_testing: bool) -> Self { self.ui_testing = ui_testing; self @@ -202,7 +198,7 @@ impl AnnotateSnippetEmitterWriter { }; if let Some(snippet) = converter.to_annotation_snippet() { let dl = DisplayList::from(snippet); - let dlf = DisplayListFormatter::new(true); + let dlf = DisplayListFormatter::new(true, self.ui_testing); // FIXME(#59346): Figure out if we can _always_ print to stderr or not. // `emitter.rs` has the `Destination` enum that lists various possible output // destinations. diff --git a/src/test/ui/annotate-snippet/missing-type.stderr b/src/test/ui/annotate-snippet/missing-type.stderr index 8857ae7d85034..806acf0bed5d1 100644 --- a/src/test/ui/annotate-snippet/missing-type.stderr +++ b/src/test/ui/annotate-snippet/missing-type.stderr @@ -1,6 +1,6 @@ error[E0412]: cannot find type `Iter` in this scope - --> $DIR/missing-type.rs:4:11 - | -4 | let x: Iter; - | ^^^^ not found in this scope - | + --> $DIR/missing-type.rs:4:11 + | +LL | let x: Iter; + | ^^^^ not found in this scope + | From 684497648ae22a69df80d410de643385c2cc86d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 25 Jul 2019 11:22:46 -0700 Subject: [PATCH 21/22] review comments: add FIXME comments and formatting --- src/libsyntax/parse/lexer/mod.rs | 15 +++++++++++---- src/libsyntax/parse/lexer/unicode_chars.rs | 14 ++++++++++---- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 412ed8f04b343..52f65e1b47475 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -389,11 +389,18 @@ impl<'a> StringReader<'a> { self.pos, "unknown start of token", c); - if let Some(t) = unicode_chars::check_for_substitution(self, start, c, &mut err) { - err.emit(); - return Ok(t); + // FIXME: the lexer could be used to turn the ASCII version of unicode homoglyphs, + // instead of keeping a table in `check_for_substitution`into the token. Ideally, + // this should be inside `rustc_lexer`. However, we should first remove compound + // tokens like `<<` from `rustc_lexer`, and then add fancier error recovery to it, + // as there will be less overall work to do this way. + return match unicode_chars::check_for_substitution(self, start, c, &mut err) { + Some(token) => { + err.emit(); + Ok(token) + } + None => Err(err), } - return Err(err) } }; Ok(kind) diff --git a/src/libsyntax/parse/lexer/unicode_chars.rs b/src/libsyntax/parse/lexer/unicode_chars.rs index bfa1606a0d201..eaa736c6a3517 100644 --- a/src/libsyntax/parse/lexer/unicode_chars.rs +++ b/src/libsyntax/parse/lexer/unicode_chars.rs @@ -3,7 +3,7 @@ use super::StringReader; use errors::{Applicability, DiagnosticBuilder}; -use syntax_pos::{BytePos, Pos, Span, NO_EXPANSION}; +use syntax_pos::{BytePos, Pos, Span, NO_EXPANSION, symbol::kw}; use crate::parse::token; #[rustfmt::skip] // for line breaks @@ -298,9 +298,13 @@ const UNICODE_ARRAY: &[(char, &str, char)] = &[ ('>', "Fullwidth Greater-Than Sign", '>'), ]; +// FIXME: the lexer could be used to turn the ASCII version of unicode homoglyphs, instead of +// keeping the substitution token in this table. Ideally, this should be inside `rustc_lexer`. +// However, we should first remove compound tokens like `<<` from `rustc_lexer`, and then add +// fancier error recovery to it, as there will be less overall work to do this way. const ASCII_ARRAY: &[(char, &str, Option)] = &[ (' ', "Space", Some(token::Whitespace)), - ('_', "Underscore", None), + ('_', "Underscore", Some(token::Ident(kw::Underscore, false))), ('-', "Minus/Hyphen", Some(token::BinOp(token::Minus))), (',', "Comma", Some(token::Comma)), (';', "Semicolon", Some(token::Semi)), @@ -308,8 +312,6 @@ const ASCII_ARRAY: &[(char, &str, Option)] = &[ ('!', "Exclamation Mark", Some(token::Not)), ('?', "Question Mark", Some(token::Question)), ('.', "Period", Some(token::Dot)), - ('\'', "Single Quote", None), // Literals are already lexed by this point, so we can't recover - ('"', "Quotation Mark", None), // gracefully just by spitting the correct token out. ('(', "Left Parenthesis", Some(token::OpenDelim(token::Paren))), (')', "Right Parenthesis", Some(token::CloseDelim(token::Paren))), ('[', "Left Square Bracket", Some(token::OpenDelim(token::Bracket))), @@ -324,6 +326,10 @@ const ASCII_ARRAY: &[(char, &str, Option)] = &[ ('<', "Less-Than Sign", Some(token::Lt)), ('=', "Equals Sign", Some(token::Eq)), ('>', "Greater-Than Sign", Some(token::Gt)), + // FIXME: Literals are already lexed by this point, so we can't recover gracefully just by + // spitting the correct token out. + ('\'', "Single Quote", None), + ('"', "Quotation Mark", None), ]; crate fn check_for_substitution<'a>( From df4b23e7212b8f7a3f62f469f666021226e29c17 Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Wed, 24 Jul 2019 23:32:26 +0200 Subject: [PATCH 22/22] Implement slow-path for FirstSets::first When 2 or more sequences share the same span, we can't use the precomputed map for their first set. So we compute it recursively. Fixes #62831. --- src/libsyntax/ext/tt/macro_rules.rs | 53 +++++++++---------- .../macros/auxiliary/proc_macro_sequence.rs | 36 +++++++++++++ src/test/ui/macros/same-sequence-span.rs | 23 ++++++++ src/test/ui/macros/same-sequence-span.stderr | 34 ++++++++++++ 4 files changed, 119 insertions(+), 27 deletions(-) create mode 100644 src/test/ui/macros/auxiliary/proc_macro_sequence.rs create mode 100644 src/test/ui/macros/same-sequence-span.rs create mode 100644 src/test/ui/macros/same-sequence-span.stderr diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 4503cea0f10c8..1731c0f713bad 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -625,38 +625,37 @@ impl FirstSets { return first; } TokenTree::Sequence(sp, ref seq_rep) => { - match self.first.get(&sp.entire()) { - Some(&Some(ref subfirst)) => { - // If the sequence contents can be empty, then the first - // token could be the separator token itself. - - if let (Some(sep), true) = (&seq_rep.separator, subfirst.maybe_empty) { - first.add_one_maybe(TokenTree::Token(sep.clone())); - } - - assert!(first.maybe_empty); - first.add_all(subfirst); - if subfirst.maybe_empty - || seq_rep.kleene.op == quoted::KleeneOp::ZeroOrMore - || seq_rep.kleene.op == quoted::KleeneOp::ZeroOrOne - { - // continue scanning for more first - // tokens, but also make sure we - // restore empty-tracking state - first.maybe_empty = true; - continue; - } else { - return first; - } - } - + let subfirst_owned; + let subfirst = match self.first.get(&sp.entire()) { + Some(&Some(ref subfirst)) => subfirst, Some(&None) => { - panic!("assume all sequences have (unique) spans for now"); + subfirst_owned = self.first(&seq_rep.tts[..]); + &subfirst_owned } - None => { panic!("We missed a sequence during FirstSets construction"); } + }; + + // If the sequence contents can be empty, then the first + // token could be the separator token itself. + if let (Some(sep), true) = (&seq_rep.separator, subfirst.maybe_empty) { + first.add_one_maybe(TokenTree::Token(sep.clone())); + } + + assert!(first.maybe_empty); + first.add_all(subfirst); + if subfirst.maybe_empty + || seq_rep.kleene.op == quoted::KleeneOp::ZeroOrMore + || seq_rep.kleene.op == quoted::KleeneOp::ZeroOrOne + { + // Continue scanning for more first + // tokens, but also make sure we + // restore empty-tracking state. + first.maybe_empty = true; + continue; + } else { + return first; } } } diff --git a/src/test/ui/macros/auxiliary/proc_macro_sequence.rs b/src/test/ui/macros/auxiliary/proc_macro_sequence.rs new file mode 100644 index 0000000000000..b50ed7ca92ad5 --- /dev/null +++ b/src/test/ui/macros/auxiliary/proc_macro_sequence.rs @@ -0,0 +1,36 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro_span, proc_macro_hygiene, proc_macro_quote)] + +extern crate proc_macro; + +use proc_macro::{quote, Span, TokenStream}; + +fn assert_same_span(a: Span, b: Span) { + assert_eq!(a.start(), b.start()); + assert_eq!(a.end(), b.end()); +} + +// This macro generates a macro with the same macro definition as `manual_foo` in +// `same-sequence-span.rs` but with the same span for all sequences. +#[proc_macro] +pub fn make_foo(_: TokenStream) -> TokenStream { + let result = quote! { + macro_rules! generated_foo { + (1 $$x:expr $$($$y:tt,)* $$(= $$z:tt)*) => {}; + } + }; + + // Check that all spans are equal. + let mut span = None; + for tt in result.clone() { + match span { + None => span = Some(tt.span()), + Some(span) => assert_same_span(tt.span(), span), + } + } + + result +} diff --git a/src/test/ui/macros/same-sequence-span.rs b/src/test/ui/macros/same-sequence-span.rs new file mode 100644 index 0000000000000..a4f70b6b68d1e --- /dev/null +++ b/src/test/ui/macros/same-sequence-span.rs @@ -0,0 +1,23 @@ +// aux-build:proc_macro_sequence.rs + +// Regression test for issue #62831: Check that multiple sequences with the same span in the +// left-hand side of a macro definition behave as if they had unique spans, and in particular that +// they don't crash the compiler. + +#![feature(proc_macro_hygiene)] +#![allow(unused_macros)] + +extern crate proc_macro_sequence; + +// When ignoring spans, this macro has the same macro definition as `generated_foo` in +// `proc_macro_sequence.rs`. +macro_rules! manual_foo { + (1 $x:expr $($y:tt,)* //~ERROR `$x:expr` may be followed by `$y:tt` + $(= $z:tt)* //~ERROR `$x:expr` may be followed by `=` + ) => {}; +} + +proc_macro_sequence::make_foo!(); //~ERROR `$x:expr` may be followed by `$y:tt` + //~^ERROR `$x:expr` may be followed by `=` + +fn main() {} diff --git a/src/test/ui/macros/same-sequence-span.stderr b/src/test/ui/macros/same-sequence-span.stderr new file mode 100644 index 0000000000000..aee1b4c9c5d99 --- /dev/null +++ b/src/test/ui/macros/same-sequence-span.stderr @@ -0,0 +1,34 @@ +error: `$x:expr` may be followed by `$y:tt`, which is not allowed for `expr` fragments + --> $DIR/same-sequence-span.rs:15:18 + | +LL | (1 $x:expr $($y:tt,)* + | ^^^^^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$x:expr` may be followed by `=`, which is not allowed for `expr` fragments + --> $DIR/same-sequence-span.rs:16:18 + | +LL | $(= $z:tt)* + | ^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$x:expr` may be followed by `$y:tt`, which is not allowed for `expr` fragments + --> $DIR/same-sequence-span.rs:20:1 + | +LL | proc_macro_sequence::make_foo!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: `$x:expr` may be followed by `=`, which is not allowed for `expr` fragments + --> $DIR/same-sequence-span.rs:20:1 + | +LL | proc_macro_sequence::make_foo!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not allowed after `expr` fragments + | + = note: allowed there are: `=>`, `,` or `;` + +error: aborting due to 4 previous errors +