From a35cdd4e41a2bec5d8896653f898aaff61cb0106 Mon Sep 17 00:00:00 2001 From: John Downey Date: Wed, 6 Mar 2019 12:17:26 -0600 Subject: [PATCH 0001/3207] Implement `iter::Sum` and `iter::Product` for `Option` This is similar to the existing implementation for `Result`. It will take each item into the accumulator unless a `None` is returned. --- src/libcore/iter/traits/accum.rs | 113 +++++++++++++++++++++++++++++++ src/libcore/tests/iter.rs | 16 +++++ 2 files changed, 129 insertions(+) diff --git a/src/libcore/iter/traits/accum.rs b/src/libcore/iter/traits/accum.rs index dfe1d2a1006d..b67714ca7790 100644 --- a/src/libcore/iter/traits/accum.rs +++ b/src/libcore/iter/traits/accum.rs @@ -223,3 +223,116 @@ impl Product> for Result ResultShunt::process(iter, |i| i.product()) } } + +/// An iterator adapter that produces output as long as the underlying +/// iterator produces `Option::Some` values. +struct OptionShunt { + iter: I, + exited_early: bool, +} + +impl OptionShunt +where + I: Iterator>, +{ + /// Process the given iterator as if it yielded a `T` instead of a + /// `Option`. Any `None` value will stop the inner iterator and + /// the overall result will be a `None`. + pub fn process(iter: I, mut f: F) -> Option + where + F: FnMut(&mut Self) -> U, + { + let mut shunt = OptionShunt::new(iter); + let value = f(shunt.by_ref()); + shunt.reconstruct(value) + } + + fn new(iter: I) -> Self { + OptionShunt { + iter, + exited_early: false, + } + } + + /// Consume the adapter and rebuild a `Option` value. + fn reconstruct(self, val: U) -> Option { + if self.exited_early { + None + } else { + Some(val) + } + } +} + +impl Iterator for OptionShunt +where + I: Iterator>, +{ + type Item = T; + + fn next(&mut self) -> Option { + match self.iter.next() { + Some(Some(v)) => Some(v), + Some(None) => { + self.exited_early = true; + None + } + None => None, + } + } + + fn size_hint(&self) -> (usize, Option) { + if self.exited_early { + (0, Some(0)) + } else { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } + } +} + +#[stable(feature = "iter_arith_traits_option", since = "1.34.0")] +impl Sum> for Option +where + T: Sum, +{ + /// Takes each element in the `Iterator`: if it is a `None`, no further + /// elements are taken, and the `None` is returned. Should no `None` occur, + /// the sum of all elements is returned. + /// + /// # Examples + /// + /// This sums up every integer in a vector, rejecting the sum if a negative + /// element is encountered: + /// + /// ``` + /// let v = vec![1, 2]; + /// let res: Option = v.iter().map(|&x: &i32| + /// if x < 0 { None } + /// else { Some(x) } + /// ).sum(); + /// assert_eq!(res, Some(3)); + /// ``` + fn sum(iter: I) -> Option + where + I: Iterator>, + { + OptionShunt::process(iter, |i| i.sum()) + } +} + +#[stable(feature = "iter_arith_traits_option", since = "1.34.0")] +impl Product> for Option +where + T: Product, +{ + /// Takes each element in the `Iterator`: if it is a `None`, no further + /// elements are taken, and the `None` is returned. Should no `None` occur, + /// the product of all elements is returned. + fn product(iter: I) -> Option + where + I: Iterator>, + { + OptionShunt::process(iter, |i| i.product()) + } +} diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index d880abb181c2..814f4ec4ca53 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1066,6 +1066,14 @@ fn test_iterator_sum_result() { assert_eq!(v.iter().cloned().sum::>(), Err(())); } +#[test] +fn test_iterator_sum_option() { + let v: &[Option] = &[Some(1), Some(2), Some(3), Some(4)]; + assert_eq!(v.iter().cloned().sum::>(), Some(10)); + let v: &[Option] = &[Some(1), None, Some(3), Some(4)]; + assert_eq!(v.iter().cloned().sum::>(), None); +} + #[test] fn test_iterator_product() { let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; @@ -1082,6 +1090,14 @@ fn test_iterator_product_result() { assert_eq!(v.iter().cloned().product::>(), Err(())); } +#[test] +fn test_iterator_product_option() { + let v: &[Option] = &[Some(1), Some(2), Some(3), Some(4)]; + assert_eq!(v.iter().cloned().product::>(), Some(24)); + let v: &[Option] = &[Some(1), None, Some(3), Some(4)]; + assert_eq!(v.iter().cloned().product::>(), None); +} + #[test] fn test_iterator_max() { let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; From 140bb5d292bb1fd0de95bca223227bad985f893f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 9 Mar 2019 02:27:03 +0100 Subject: [PATCH 0002/3207] Fix duplicated bounds printing in rustdoc --- src/librustdoc/html/format.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index d204a179ca62..d739d6963371 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -9,6 +9,7 @@ use std::borrow::Cow; use std::fmt; use rustc::hir::def_id::DefId; +use rustc::util::nodemap::FxHashSet; use rustc_target::spec::abi::Abi; use rustc::hir; @@ -106,8 +107,10 @@ impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> { impl<'a> fmt::Display for GenericBounds<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut bounds_dup = FxHashSet::default(); let &GenericBounds(bounds) = self; - for (i, bound) in bounds.iter().enumerate() { + + for (i, bound) in bounds.iter().filter(|b| bounds_dup.insert(b.to_string())).enumerate() { if i > 0 { f.write_str(" + ")?; } @@ -205,16 +208,13 @@ impl<'a> fmt::Display for WhereClause<'a> { clause.push_str(&format!("{}: {}", ty, GenericBounds(bounds))); } } - &clean::WherePredicate::RegionPredicate { ref lifetime, - ref bounds } => { - clause.push_str(&format!("{}: ", lifetime)); - for (i, lifetime) in bounds.iter().enumerate() { - if i > 0 { - clause.push_str(" + "); - } - - clause.push_str(&lifetime.to_string()); - } + &clean::WherePredicate::RegionPredicate { ref lifetime, ref bounds } => { + clause.push_str(&format!("{}: {}", + lifetime, + bounds.iter() + .map(|b| b.to_string()) + .collect::>() + .join(" + "))); } &clean::WherePredicate::EqPredicate { ref lhs, ref rhs } => { if f.alternate() { From 8c698763579d5cf78094d2d4495c3d801ed0d2e7 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 19 Mar 2019 17:17:18 -0500 Subject: [PATCH 0003/3207] Update stable attribute to be since 1.35.0 Co-Authored-By: jtdowney --- src/libcore/iter/traits/accum.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/iter/traits/accum.rs b/src/libcore/iter/traits/accum.rs index b67714ca7790..ae51e1bddac0 100644 --- a/src/libcore/iter/traits/accum.rs +++ b/src/libcore/iter/traits/accum.rs @@ -291,7 +291,7 @@ where } } -#[stable(feature = "iter_arith_traits_option", since = "1.34.0")] +#[stable(feature = "iter_arith_traits_option", since = "1.35.0")] impl Sum> for Option where T: Sum, @@ -321,7 +321,7 @@ where } } -#[stable(feature = "iter_arith_traits_option", since = "1.34.0")] +#[stable(feature = "iter_arith_traits_option", since = "1.35.0")] impl Product> for Option where T: Product, From 422a4c07c826fb007f5199031482d5b40d255899 Mon Sep 17 00:00:00 2001 From: John Downey Date: Wed, 20 Mar 2019 20:14:46 -0500 Subject: [PATCH 0004/3207] Add improved doc example for Sum> --- src/libcore/iter/traits/accum.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/libcore/iter/traits/accum.rs b/src/libcore/iter/traits/accum.rs index ae51e1bddac0..88c4820d5839 100644 --- a/src/libcore/iter/traits/accum.rs +++ b/src/libcore/iter/traits/accum.rs @@ -302,16 +302,13 @@ where /// /// # Examples /// - /// This sums up every integer in a vector, rejecting the sum if a negative - /// element is encountered: + /// This sums up the position of the character 'a' in a vector of strings, + /// if a word did not have the character 'a' the operation returns `None`: /// /// ``` - /// let v = vec![1, 2]; - /// let res: Option = v.iter().map(|&x: &i32| - /// if x < 0 { None } - /// else { Some(x) } - /// ).sum(); - /// assert_eq!(res, Some(3)); + /// let words = vec!["have", "a", "great", "day"]; + /// let total: Option = words.iter().map(|w| w.find('a')).sum(); + /// assert_eq!(total, Some(5)); /// ``` fn sum(iter: I) -> Option where From 725199ce6512cc946d5b16c4ef3a845a2926cb09 Mon Sep 17 00:00:00 2001 From: LooMaclin Date: Tue, 2 Apr 2019 05:58:25 +0300 Subject: [PATCH 0005/3207] Improve miri's error reporting in check_in_alloc --- src/librustc/mir/interpret/allocation.rs | 70 +++++++++++++++++++----- src/librustc/mir/interpret/error.rs | 12 ++-- src/librustc/mir/interpret/mod.rs | 2 +- src/librustc/mir/interpret/pointer.rs | 6 +- src/librustc_mir/hair/pattern/_match.rs | 6 +- src/librustc_mir/interpret/memory.rs | 20 +++---- src/librustc_mir/interpret/operand.rs | 4 +- src/librustc_mir/interpret/validity.rs | 4 +- 8 files changed, 82 insertions(+), 42 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 80fef910cc71..f00da804e953 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -7,7 +7,7 @@ use super::{ use crate::ty::layout::{Size, Align}; use syntax::ast::Mutability; -use std::iter; +use std::{iter, fmt::{self, Display}}; use crate::mir; use std::ops::{Deref, DerefMut}; use rustc_data_structures::sorted_map::SortedMap; @@ -22,6 +22,44 @@ pub enum InboundsCheck { MaybeDead, } +/// Used by `check_in_alloc` to indicate whether the pointer needs to be just inbounds +/// or also inbounds of a *live* allocation. +#[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)] +pub enum CheckInAllocMsg { + ReadCStr, + CheckBytes, + WriteBytes, + WriteRepeat, + ReadScalar, + WriteScalar, + SlicePatCoveredByConst, + ReadDiscriminant, + CheckAlign, + ReadBytes, + CopyRepeatedly, + CheckBounds, +} + +impl Display for CheckInAllocMsg { + + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", match *self { + CheckInAllocMsg::ReadCStr => "read C str", + CheckInAllocMsg::CheckBytes => "check bytes", + CheckInAllocMsg::WriteBytes => "write bytes", + CheckInAllocMsg::WriteRepeat => "write repeat", + CheckInAllocMsg::ReadScalar => "read scalar", + CheckInAllocMsg::WriteScalar => "write scalar", + CheckInAllocMsg::SlicePatCoveredByConst => "slice pat covered by const", + CheckInAllocMsg::ReadDiscriminant => "read discriminant", + CheckInAllocMsg::CheckAlign => "check align", + CheckInAllocMsg::ReadBytes => "read bytes", + CheckInAllocMsg::CopyRepeatedly => "copy repeatedly", + CheckInAllocMsg::CheckBounds => "check bounds", + }) + } +} + #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub struct Allocation { /// The actual bytes of the allocation. @@ -140,9 +178,10 @@ impl<'tcx, Tag, Extra> Allocation { fn check_bounds_ptr( &self, ptr: Pointer, + msg: CheckInAllocMsg, ) -> EvalResult<'tcx> { let allocation_size = self.bytes.len() as u64; - ptr.check_in_alloc(Size::from_bytes(allocation_size), InboundsCheck::Live) + ptr.check_in_alloc(Size::from_bytes(allocation_size), msg) } /// Checks if the memory range beginning at `ptr` and of size `Size` is "in-bounds". @@ -152,9 +191,10 @@ impl<'tcx, Tag, Extra> Allocation { cx: &impl HasDataLayout, ptr: Pointer, size: Size, + msg: CheckInAllocMsg, ) -> EvalResult<'tcx> { // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow) - self.check_bounds_ptr(ptr.offset(size, cx)?) + self.check_bounds_ptr(ptr.offset(size, cx)?, msg) } } @@ -173,11 +213,12 @@ impl<'tcx, Tag: Copy, Extra> Allocation { ptr: Pointer, size: Size, check_defined_and_ptr: bool, + msg: CheckInAllocMsg, ) -> EvalResult<'tcx, &[u8]> // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 where Extra: AllocationExtra { - self.check_bounds(cx, ptr, size)?; + self.check_bounds(cx, ptr, size, msg)?; if check_defined_and_ptr { self.check_defined(ptr, size)?; @@ -201,11 +242,12 @@ impl<'tcx, Tag: Copy, Extra> Allocation { cx: &impl HasDataLayout, ptr: Pointer, size: Size, + msg: CheckInAllocMsg, ) -> EvalResult<'tcx, &[u8]> // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 where Extra: AllocationExtra { - self.get_bytes_internal(cx, ptr, size, true) + self.get_bytes_internal(cx, ptr, size, true, msg) } /// It is the caller's responsibility to handle undefined and pointer bytes. @@ -216,11 +258,12 @@ impl<'tcx, Tag: Copy, Extra> Allocation { cx: &impl HasDataLayout, ptr: Pointer, size: Size, + msg: CheckInAllocMsg, ) -> EvalResult<'tcx, &[u8]> // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 where Extra: AllocationExtra { - self.get_bytes_internal(cx, ptr, size, false) + self.get_bytes_internal(cx, ptr, size, false, msg) } /// Just calling this already marks everything as defined and removes relocations, @@ -230,12 +273,13 @@ impl<'tcx, Tag: Copy, Extra> Allocation { cx: &impl HasDataLayout, ptr: Pointer, size: Size, + msg: CheckInAllocMsg, ) -> EvalResult<'tcx, &mut [u8]> // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 where Extra: AllocationExtra { assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); - self.check_bounds(cx, ptr, size)?; + self.check_bounds(cx, ptr, size, msg)?; self.mark_definedness(ptr, size, true)?; self.clear_relocations(cx, ptr, size)?; @@ -269,7 +313,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { // Go through `get_bytes` for checks and AllocationExtra hooks. // We read the null, so we include it in the request, but we want it removed // from the result! - Ok(&self.get_bytes(cx, ptr, size_with_null)?[..size]) + Ok(&self.get_bytes(cx, ptr, size_with_null, CheckInAllocMsg::ReadCStr)?[..size]) } None => err!(UnterminatedCString(ptr.erase_tag())), } @@ -289,7 +333,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { where Extra: AllocationExtra { // Check bounds and relocations on the edges - self.get_bytes_with_undef_and_ptr(cx, ptr, size)?; + self.get_bytes_with_undef_and_ptr(cx, ptr, size, CheckInAllocMsg::CheckBytes)?; // Check undef and ptr if !allow_ptr_and_undef { self.check_defined(ptr, size)?; @@ -310,7 +354,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 where Extra: AllocationExtra { - let bytes = self.get_bytes_mut(cx, ptr, Size::from_bytes(src.len() as u64))?; + let bytes = self.get_bytes_mut(cx, ptr, Size::from_bytes(src.len() as u64), CheckInAllocMsg::WriteBytes)?; bytes.clone_from_slice(src); Ok(()) } @@ -326,7 +370,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 where Extra: AllocationExtra { - let bytes = self.get_bytes_mut(cx, ptr, count)?; + let bytes = self.get_bytes_mut(cx, ptr, count, CheckInAllocMsg::WriteRepeat)?; for b in bytes { *b = val; } @@ -351,7 +395,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { where Extra: AllocationExtra { // get_bytes_unchecked tests relocation edges - let bytes = self.get_bytes_with_undef_and_ptr(cx, ptr, size)?; + let bytes = self.get_bytes_with_undef_and_ptr(cx, ptr, size, CheckInAllocMsg::ReadScalar)?; // Undef check happens *after* we established that the alignment is correct. // We must not return Ok() for unaligned pointers! if self.check_defined(ptr, size).is_err() { @@ -428,7 +472,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { }; let endian = cx.data_layout().endian; - let dst = self.get_bytes_mut(cx, ptr, type_size)?; + let dst = self.get_bytes_mut(cx, ptr, type_size, CheckInAllocMsg::WriteScalar)?; write_target_uint(endian, dst, bytes).unwrap(); // See if we have to also write a relocation diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index fc04c7672db6..a3acc03fb631 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -8,7 +8,7 @@ use crate::ty::layout::{Size, Align, LayoutError}; use rustc_target::spec::abi::Abi; use rustc_macros::HashStable; -use super::{RawConst, Pointer, InboundsCheck, ScalarMaybeUndef}; +use super::{RawConst, Pointer, CheckInAllocMsg, ScalarMaybeUndef}; use backtrace::Backtrace; @@ -243,7 +243,7 @@ pub enum EvalErrorKind<'tcx, O> { InvalidDiscriminant(ScalarMaybeUndef), PointerOutOfBounds { ptr: Pointer, - check: InboundsCheck, + msg: CheckInAllocMsg, allocation_size: Size, }, InvalidNullPointerUsage, @@ -460,13 +460,9 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use self::EvalErrorKind::*; match *self { - PointerOutOfBounds { ptr, check, allocation_size } => { + PointerOutOfBounds { ptr, msg, allocation_size } => { write!(f, "Pointer must be in-bounds{} at offset {}, but is outside bounds of \ - allocation {} which has size {}", - match check { - InboundsCheck::Live => " and live", - InboundsCheck::MaybeDead => "", - }, + allocation {} which has size {}", msg, ptr.offset.bytes(), ptr.alloc_id, allocation_size.bytes()) }, ValidationFailure(ref err) => { diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index 0dd831685278..c6881cfa99f3 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -19,7 +19,7 @@ pub use self::value::{Scalar, ScalarMaybeUndef, RawConst, ConstValue}; pub use self::allocation::{ InboundsCheck, Allocation, AllocationExtra, - Relocations, UndefMask, + Relocations, UndefMask, CheckInAllocMsg, }; pub use self::pointer::{Pointer, PointerArithmetic}; diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs index 9216cb494cef..bf9694693aa1 100644 --- a/src/librustc/mir/interpret/pointer.rs +++ b/src/librustc/mir/interpret/pointer.rs @@ -3,7 +3,7 @@ use crate::ty::layout::{self, HasDataLayout, Size}; use rustc_macros::HashStable; use super::{ - AllocId, EvalResult, InboundsCheck, + AllocId, EvalResult, CheckInAllocMsg }; //////////////////////////////////////////////////////////////////////////////// @@ -157,12 +157,12 @@ impl<'tcx, Tag> Pointer { pub fn check_in_alloc( self, allocation_size: Size, - check: InboundsCheck, + msg: CheckInAllocMsg, ) -> EvalResult<'tcx, ()> { if self.offset > allocation_size { err!(PointerOutOfBounds { ptr: self.erase_tag(), - check, + msg, allocation_size, }) } else { diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 303ffcb3bfb3..014c5ced37b2 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -172,7 +172,7 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, Const}; use rustc::ty::layout::{Integer, IntegerExt, VariantIdx, Size}; use rustc::mir::Field; -use rustc::mir::interpret::{ConstValue, Scalar, truncate}; +use rustc::mir::interpret::{ConstValue, Scalar, truncate, CheckInAllocMsg}; use rustc::util::common::ErrorReported; use syntax::attr::{SignedInt, UnsignedInt}; @@ -1418,7 +1418,7 @@ fn slice_pat_covered_by_const<'tcx>( return Ok(false); } let n = n.assert_usize(tcx).unwrap(); - alloc.get_bytes(&tcx, ptr, Size::from_bytes(n)).unwrap() + alloc.get_bytes(&tcx, ptr, Size::from_bytes(n), CheckInAllocMsg::SlicePatCoveredByConst).unwrap() }, // a slice fat pointer to a zero length slice (ConstValue::Slice(Scalar::Bits { .. }, 0), ty::Slice(t)) => { @@ -1443,7 +1443,7 @@ fn slice_pat_covered_by_const<'tcx>( tcx.alloc_map .lock() .unwrap_memory(ptr.alloc_id) - .get_bytes(&tcx, ptr, Size::from_bytes(n)) + .get_bytes(&tcx, ptr, Size::from_bytes(n), CheckInAllocMsg::SlicePatCoveredByConst) .unwrap() }, _ => bug!( diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 6ea200d4e4fa..302bc84e65c4 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -20,7 +20,7 @@ use syntax::ast::Mutability; use super::{ Pointer, AllocId, Allocation, GlobalId, AllocationExtra, EvalResult, Scalar, EvalErrorKind, AllocKind, PointerArithmetic, - Machine, AllocMap, MayLeak, ErrorHandled, InboundsCheck, + Machine, AllocMap, MayLeak, ErrorHandled, InboundsCheck, CheckInAllocMsg, }; #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] @@ -252,7 +252,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Scalar::Ptr(ptr) => { // check this is not NULL -- which we can ensure only if this is in-bounds // of some (potentially dead) allocation. - let align = self.check_bounds_ptr(ptr, InboundsCheck::MaybeDead)?; + let align = self.check_bounds_ptr(ptr, CheckInAllocMsg::CheckAlign)?; (ptr.offset.bytes(), align) } Scalar::Bits { bits, size } => { @@ -292,10 +292,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn check_bounds_ptr( &self, ptr: Pointer, - liveness: InboundsCheck, + msg: CheckInAllocMsg, ) -> EvalResult<'tcx, Align> { - let (allocation_size, align) = self.get_size_and_align(ptr.alloc_id, liveness)?; - ptr.check_in_alloc(allocation_size, liveness)?; + let (allocation_size, align) = self.get_size_and_align(ptr.alloc_id, msg)?; + ptr.check_in_alloc(allocation_size, msg)?; Ok(align) } } @@ -423,7 +423,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn get_size_and_align( &self, id: AllocId, - liveness: InboundsCheck, + msg: CheckInAllocMsg, ) -> EvalResult<'static, (Size, Align)> { if let Ok(alloc) = self.get(id) { return Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)); @@ -439,7 +439,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap(); Ok((layout.size, layout.align.abi)) } - _ => match liveness { + _ => match msg { InboundsCheck::MaybeDead => { // Must be a deallocated pointer Ok(*self.dead_alloc_map.get(&id).expect( @@ -604,7 +604,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Ok(&[]) } else { let ptr = ptr.to_ptr()?; - self.get(ptr.alloc_id)?.get_bytes(self, ptr, size) + self.get(ptr.alloc_id)?.get_bytes(self, ptr, size, CheckInAllocMsg::ReadBytes) } } } @@ -729,10 +729,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { // This checks relocation edges on the src. let src_bytes = self.get(src.alloc_id)? - .get_bytes_with_undef_and_ptr(&tcx, src, size)? + .get_bytes_with_undef_and_ptr(&tcx, src, size, CheckInAllocMsg::CopyRepeatedly)? .as_ptr(); let dest_bytes = self.get_mut(dest.alloc_id)? - .get_bytes_mut(&tcx, dest, size * length)? + .get_bytes_mut(&tcx, dest, size * length, CheckInAllocMsg::CopyRepeatedly)? .as_mut_ptr(); // SAFE: The above indexing would have panicked if there weren't at least `size` bytes diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 38a9371b9272..b90ec42de7ef 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -7,7 +7,7 @@ use rustc::{mir, ty}; use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt, VariantIdx}; use rustc::mir::interpret::{ - GlobalId, AllocId, InboundsCheck, + GlobalId, AllocId, CheckInAllocMsg, ConstValue, Pointer, Scalar, EvalResult, EvalErrorKind, sign_extend, truncate, @@ -667,7 +667,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) => { // The niche must be just 0 (which an inbounds pointer value never is) let ptr_valid = niche_start == 0 && variants_start == variants_end && - self.memory.check_bounds_ptr(ptr, InboundsCheck::MaybeDead).is_ok(); + self.memory.check_bounds_ptr(ptr, CheckInAllocMsg::ReadDiscriminant).is_ok(); if !ptr_valid { return err!(InvalidDiscriminant(raw_discr.erase_tag())); } diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 3323ec387bfd..23c1681cbd87 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -7,7 +7,7 @@ use rustc::ty::layout::{self, Size, Align, TyLayout, LayoutOf, VariantIdx}; use rustc::ty; use rustc_data_structures::fx::FxHashSet; use rustc::mir::interpret::{ - Scalar, AllocKind, EvalResult, EvalErrorKind, + Scalar, AllocKind, EvalResult, EvalErrorKind, CheckInAllocMsg, }; use super::{ @@ -394,7 +394,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> try_validation!( self.ecx.memory .get(ptr.alloc_id)? - .check_bounds(self.ecx, ptr, size), + .check_bounds(self.ecx, ptr, size, CheckInAllocMsg::CheckBounds), "dangling (not entirely in bounds) reference", self.path); } // Check if we have encountered this pointer+layout combination From 7b4bc6974a16df46e5d50a1191c124fc8c1f56ae Mon Sep 17 00:00:00 2001 From: LooMaclin Date: Tue, 2 Apr 2019 06:16:11 +0300 Subject: [PATCH 0006/3207] Improve miri's error reporting in check_in_alloc --- src/librustc/mir/interpret/allocation.rs | 3 +-- src/librustc_mir/interpret/memory.rs | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index f00da804e953..a04316b719e8 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -22,8 +22,7 @@ pub enum InboundsCheck { MaybeDead, } -/// Used by `check_in_alloc` to indicate whether the pointer needs to be just inbounds -/// or also inbounds of a *live* allocation. +/// Used by `check_in_alloc` to indicate context of check #[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)] pub enum CheckInAllocMsg { ReadCStr, diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 302bc84e65c4..80efafa65503 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -20,7 +20,7 @@ use syntax::ast::Mutability; use super::{ Pointer, AllocId, Allocation, GlobalId, AllocationExtra, EvalResult, Scalar, EvalErrorKind, AllocKind, PointerArithmetic, - Machine, AllocMap, MayLeak, ErrorHandled, InboundsCheck, CheckInAllocMsg, + Machine, AllocMap, MayLeak, ErrorHandled, CheckInAllocMsg, }; #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] @@ -440,13 +440,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Ok((layout.size, layout.align.abi)) } _ => match msg { - InboundsCheck::MaybeDead => { + CheckInAllocMsg::CheckAlign | CheckInAllocMsg::ReadDiscriminant => { // Must be a deallocated pointer Ok(*self.dead_alloc_map.get(&id).expect( "allocation missing in dead_alloc_map" )) }, - InboundsCheck::Live => err!(DanglingPointerDeref), + _ => err!(DanglingPointerDeref), }, } } From 705d75ef1aa20c124975786cf1ad9764a82b12ef Mon Sep 17 00:00:00 2001 From: LooMaclin Date: Tue, 2 Apr 2019 06:33:54 +0300 Subject: [PATCH 0007/3207] Improve miri's error reporting in check_in_alloc --- src/librustc/mir/interpret/allocation.rs | 3 ++- src/librustc_mir/hair/pattern/_match.rs | 3 ++- src/librustc_mir/interpret/operand.rs | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index a04316b719e8..50f5da77c0fb 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -353,7 +353,8 @@ impl<'tcx, Tag: Copy, Extra> Allocation { // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 where Extra: AllocationExtra { - let bytes = self.get_bytes_mut(cx, ptr, Size::from_bytes(src.len() as u64), CheckInAllocMsg::WriteBytes)?; + let bytes = self.get_bytes_mut(cx, ptr, Size::from_bytes(src.len() as u64), + CheckInAllocMsg::WriteBytes)?; bytes.clone_from_slice(src); Ok(()) } diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 014c5ced37b2..561ac207b6bc 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -1418,7 +1418,8 @@ fn slice_pat_covered_by_const<'tcx>( return Ok(false); } let n = n.assert_usize(tcx).unwrap(); - alloc.get_bytes(&tcx, ptr, Size::from_bytes(n), CheckInAllocMsg::SlicePatCoveredByConst).unwrap() + alloc.get_bytes(&tcx, ptr, Size::from_bytes(n), + CheckInAllocMsg::SlicePatCoveredByConst).unwrap() }, // a slice fat pointer to a zero length slice (ConstValue::Slice(Scalar::Bits { .. }, 0), ty::Slice(t)) => { diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index b90ec42de7ef..7529ec0aee59 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -667,7 +667,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) => { // The niche must be just 0 (which an inbounds pointer value never is) let ptr_valid = niche_start == 0 && variants_start == variants_end && - self.memory.check_bounds_ptr(ptr, CheckInAllocMsg::ReadDiscriminant).is_ok(); + self.memory.check_bounds_ptr(ptr, + CheckInAllocMsg::ReadDiscriminant).is_ok(); if !ptr_valid { return err!(InvalidDiscriminant(raw_discr.erase_tag())); } From 4c4dbb12d35c502c27b6cf284fcc4d0000661f8c Mon Sep 17 00:00:00 2001 From: LooMaclin Date: Tue, 2 Apr 2019 18:24:57 +0300 Subject: [PATCH 0008/3207] Improve miri's error reporting in check_in_alloc --- src/librustc/mir/interpret/allocation.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 50f5da77c0fb..3f7730a8bbc0 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -40,7 +40,6 @@ pub enum CheckInAllocMsg { } impl Display for CheckInAllocMsg { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", match *self { CheckInAllocMsg::ReadCStr => "read C str", From 2a738bb8edc7c0ed77bb12657a55db666cffeda3 Mon Sep 17 00:00:00 2001 From: LooMaclin Date: Mon, 8 Apr 2019 23:34:28 +0300 Subject: [PATCH 0009/3207] Improve miri's error reporting in check_in_alloc --- src/librustc/mir/interpret/allocation.rs | 44 ++++++++---------------- src/librustc_mir/hair/pattern/_match.rs | 4 +-- src/librustc_mir/interpret/memory.rs | 10 +++--- src/librustc_mir/interpret/operand.rs | 2 +- src/librustc_mir/interpret/validity.rs | 2 +- 5 files changed, 23 insertions(+), 39 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 3f7730a8bbc0..ca680187b37d 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -25,35 +25,19 @@ pub enum InboundsCheck { /// Used by `check_in_alloc` to indicate context of check #[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)] pub enum CheckInAllocMsg { - ReadCStr, - CheckBytes, - WriteBytes, - WriteRepeat, - ReadScalar, - WriteScalar, - SlicePatCoveredByConst, - ReadDiscriminant, - CheckAlign, - ReadBytes, - CopyRepeatedly, - CheckBounds, + MemoryAccess, + NullPointer, + PointerArithmetic, + OutOfBounds, } impl Display for CheckInAllocMsg { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", match *self { - CheckInAllocMsg::ReadCStr => "read C str", - CheckInAllocMsg::CheckBytes => "check bytes", - CheckInAllocMsg::WriteBytes => "write bytes", - CheckInAllocMsg::WriteRepeat => "write repeat", - CheckInAllocMsg::ReadScalar => "read scalar", - CheckInAllocMsg::WriteScalar => "write scalar", - CheckInAllocMsg::SlicePatCoveredByConst => "slice pat covered by const", - CheckInAllocMsg::ReadDiscriminant => "read discriminant", - CheckInAllocMsg::CheckAlign => "check align", - CheckInAllocMsg::ReadBytes => "read bytes", - CheckInAllocMsg::CopyRepeatedly => "copy repeatedly", - CheckInAllocMsg::CheckBounds => "check bounds", + CheckInAllocMsg::MemoryAccess => "memory access", + CheckInAllocMsg::NullPointer => "null pointer", + CheckInAllocMsg::PointerArithmetic => "pointer arithmetic", + CheckInAllocMsg::OutOfBounds => "out of bounds", }) } } @@ -311,7 +295,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { // Go through `get_bytes` for checks and AllocationExtra hooks. // We read the null, so we include it in the request, but we want it removed // from the result! - Ok(&self.get_bytes(cx, ptr, size_with_null, CheckInAllocMsg::ReadCStr)?[..size]) + Ok(&self.get_bytes(cx, ptr, size_with_null, CheckInAllocMsg::NullPointer)?[..size]) } None => err!(UnterminatedCString(ptr.erase_tag())), } @@ -331,7 +315,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { where Extra: AllocationExtra { // Check bounds and relocations on the edges - self.get_bytes_with_undef_and_ptr(cx, ptr, size, CheckInAllocMsg::CheckBytes)?; + self.get_bytes_with_undef_and_ptr(cx, ptr, size, CheckInAllocMsg::OutOfBounds)?; // Check undef and ptr if !allow_ptr_and_undef { self.check_defined(ptr, size)?; @@ -353,7 +337,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { where Extra: AllocationExtra { let bytes = self.get_bytes_mut(cx, ptr, Size::from_bytes(src.len() as u64), - CheckInAllocMsg::WriteBytes)?; + CheckInAllocMsg::MemoryAccess)?; bytes.clone_from_slice(src); Ok(()) } @@ -369,7 +353,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 where Extra: AllocationExtra { - let bytes = self.get_bytes_mut(cx, ptr, count, CheckInAllocMsg::WriteRepeat)?; + let bytes = self.get_bytes_mut(cx, ptr, count, CheckInAllocMsg::MemoryAccess)?; for b in bytes { *b = val; } @@ -394,7 +378,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { where Extra: AllocationExtra { // get_bytes_unchecked tests relocation edges - let bytes = self.get_bytes_with_undef_and_ptr(cx, ptr, size, CheckInAllocMsg::ReadScalar)?; + let bytes = self.get_bytes_with_undef_and_ptr(cx, ptr, size, CheckInAllocMsg::PointerArithmetic)?; // Undef check happens *after* we established that the alignment is correct. // We must not return Ok() for unaligned pointers! if self.check_defined(ptr, size).is_err() { @@ -471,7 +455,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { }; let endian = cx.data_layout().endian; - let dst = self.get_bytes_mut(cx, ptr, type_size, CheckInAllocMsg::WriteScalar)?; + let dst = self.get_bytes_mut(cx, ptr, type_size, CheckInAllocMsg::PointerArithmetic)?; write_target_uint(endian, dst, bytes).unwrap(); // See if we have to also write a relocation diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 561ac207b6bc..1e2ffa5db440 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -1419,7 +1419,7 @@ fn slice_pat_covered_by_const<'tcx>( } let n = n.assert_usize(tcx).unwrap(); alloc.get_bytes(&tcx, ptr, Size::from_bytes(n), - CheckInAllocMsg::SlicePatCoveredByConst).unwrap() + CheckInAllocMsg::OutOfBounds).unwrap() }, // a slice fat pointer to a zero length slice (ConstValue::Slice(Scalar::Bits { .. }, 0), ty::Slice(t)) => { @@ -1444,7 +1444,7 @@ fn slice_pat_covered_by_const<'tcx>( tcx.alloc_map .lock() .unwrap_memory(ptr.alloc_id) - .get_bytes(&tcx, ptr, Size::from_bytes(n), CheckInAllocMsg::SlicePatCoveredByConst) + .get_bytes(&tcx, ptr, Size::from_bytes(n), CheckInAllocMsg::OutOfBounds) .unwrap() }, _ => bug!( diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index b5e3f8186991..a911479a15a2 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -252,7 +252,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Scalar::Ptr(ptr) => { // check this is not NULL -- which we can ensure only if this is in-bounds // of some (potentially dead) allocation. - let align = self.check_bounds_ptr(ptr, CheckInAllocMsg::CheckAlign)?; + let align = self.check_bounds_ptr(ptr, CheckInAllocMsg::NullPointer)?; (ptr.offset.bytes(), align) } Scalar::Bits { bits, size } => { @@ -440,7 +440,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Ok((layout.size, layout.align.abi)) } _ => match msg { - CheckInAllocMsg::CheckAlign | CheckInAllocMsg::ReadDiscriminant => { + CheckInAllocMsg::NullPointer | CheckInAllocMsg::OutOfBounds => { // Must be a deallocated pointer Ok(*self.dead_alloc_map.get(&id).expect( "allocation missing in dead_alloc_map" @@ -604,7 +604,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Ok(&[]) } else { let ptr = ptr.to_ptr()?; - self.get(ptr.alloc_id)?.get_bytes(self, ptr, size, CheckInAllocMsg::ReadBytes) + self.get(ptr.alloc_id)?.get_bytes(self, ptr, size, CheckInAllocMsg::MemoryAccess) } } } @@ -729,10 +729,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { // This checks relocation edges on the src. let src_bytes = self.get(src.alloc_id)? - .get_bytes_with_undef_and_ptr(&tcx, src, size, CheckInAllocMsg::CopyRepeatedly)? + .get_bytes_with_undef_and_ptr(&tcx, src, size, CheckInAllocMsg::MemoryAccess)? .as_ptr(); let dest_bytes = self.get_mut(dest.alloc_id)? - .get_bytes_mut(&tcx, dest, size * length, CheckInAllocMsg::CopyRepeatedly)? + .get_bytes_mut(&tcx, dest, size * length, CheckInAllocMsg::MemoryAccess)? .as_mut_ptr(); // SAFE: The above indexing would have panicked if there weren't at least `size` bytes diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 166e79c12d80..e7e22a12cd68 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -668,7 +668,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> // The niche must be just 0 (which an inbounds pointer value never is) let ptr_valid = niche_start == 0 && variants_start == variants_end && self.memory.check_bounds_ptr(ptr, - CheckInAllocMsg::ReadDiscriminant).is_ok(); + CheckInAllocMsg::OutOfBounds).is_ok(); if !ptr_valid { return err!(InvalidDiscriminant(raw_discr.erase_tag())); } diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 37c880ccf72b..965b2898cad5 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -394,7 +394,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> try_validation!( self.ecx.memory .get(ptr.alloc_id)? - .check_bounds(self.ecx, ptr, size, CheckInAllocMsg::CheckBounds), + .check_bounds(self.ecx, ptr, size, CheckInAllocMsg::OutOfBounds), "dangling (not entirely in bounds) reference", self.path); } // Check if we have encountered this pointer+layout combination From 980db98b6440779ed714e454f544faf707b2ab9c Mon Sep 17 00:00:00 2001 From: LooMaclin Date: Tue, 9 Apr 2019 00:01:08 +0300 Subject: [PATCH 0010/3207] Improve miri's error reporting in check_in_alloc --- src/librustc/mir/interpret/allocation.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index ca680187b37d..19f28b96c3a7 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -378,7 +378,8 @@ impl<'tcx, Tag: Copy, Extra> Allocation { where Extra: AllocationExtra { // get_bytes_unchecked tests relocation edges - let bytes = self.get_bytes_with_undef_and_ptr(cx, ptr, size, CheckInAllocMsg::PointerArithmetic)?; + let bytes = self.get_bytes_with_undef_and_ptr(cx, ptr, size, + CheckInAllocMsg::PointerArithmetic)?; // Undef check happens *after* we established that the alignment is correct. // We must not return Ok() for unaligned pointers! if self.check_defined(ptr, size).is_err() { From e5b6fab5768d3e2079c3a06e4206d3a199507be4 Mon Sep 17 00:00:00 2001 From: LooMaclin Date: Tue, 9 Apr 2019 00:39:57 +0300 Subject: [PATCH 0011/3207] Improve miri's error reporting in check_in_alloc --- src/librustc_mir/interpret/memory.rs | 15 ++++++++------- src/librustc_mir/interpret/operand.rs | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index a911479a15a2..6475eac41e3a 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -20,7 +20,7 @@ use syntax::ast::Mutability; use super::{ Pointer, AllocId, Allocation, GlobalId, AllocationExtra, EvalResult, Scalar, InterpError, AllocKind, PointerArithmetic, - Machine, AllocMap, MayLeak, ErrorHandled, CheckInAllocMsg, + Machine, AllocMap, MayLeak, ErrorHandled, CheckInAllocMsg, InboundsCheck, }; #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] @@ -252,7 +252,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Scalar::Ptr(ptr) => { // check this is not NULL -- which we can ensure only if this is in-bounds // of some (potentially dead) allocation. - let align = self.check_bounds_ptr(ptr, CheckInAllocMsg::NullPointer)?; + let align = self.check_bounds_ptr(ptr, InboundsCheck::MaybeDead, CheckInAllocMsg::NullPointer)?; (ptr.offset.bytes(), align) } Scalar::Bits { bits, size } => { @@ -292,9 +292,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { pub fn check_bounds_ptr( &self, ptr: Pointer, + liveness: InboundsCheck, msg: CheckInAllocMsg, ) -> EvalResult<'tcx, Align> { - let (allocation_size, align) = self.get_size_and_align(ptr.alloc_id, msg)?; + let (allocation_size, align) = self.get_size_and_align(ptr.alloc_id, liveness)?; ptr.check_in_alloc(allocation_size, msg)?; Ok(align) } @@ -419,11 +420,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { /// Obtain the size and alignment of an allocation, even if that allocation has been deallocated /// - /// If `liveness` is `InboundsCheck::Dead`, this function always returns `Ok` + /// If `liveness` is `InboundsCheck::MaybeDead`, this function always returns `Ok` pub fn get_size_and_align( &self, id: AllocId, - msg: CheckInAllocMsg, + liveness: InboundsCheck, ) -> EvalResult<'static, (Size, Align)> { if let Ok(alloc) = self.get(id) { return Ok((Size::from_bytes(alloc.bytes.len() as u64), alloc.align)); @@ -439,8 +440,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap(); Ok((layout.size, layout.align.abi)) } - _ => match msg { - CheckInAllocMsg::NullPointer | CheckInAllocMsg::OutOfBounds => { + _ => match liveness { + InboundsCheck::MaybeDead => { // Must be a deallocated pointer Ok(*self.dead_alloc_map.get(&id).expect( "allocation missing in dead_alloc_map" diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index e7e22a12cd68..38fe1caa41f6 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -9,7 +9,7 @@ use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerEx use rustc::mir::interpret::{ GlobalId, AllocId, CheckInAllocMsg, ConstValue, Pointer, Scalar, - EvalResult, InterpError, + EvalResult, InterpError, InboundsCheck, sign_extend, truncate, }; use super::{ @@ -667,7 +667,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> ScalarMaybeUndef::Scalar(Scalar::Ptr(ptr)) => { // The niche must be just 0 (which an inbounds pointer value never is) let ptr_valid = niche_start == 0 && variants_start == variants_end && - self.memory.check_bounds_ptr(ptr, + self.memory.check_bounds_ptr(ptr, InboundsCheck::MaybeDead, CheckInAllocMsg::OutOfBounds).is_ok(); if !ptr_valid { return err!(InvalidDiscriminant(raw_discr.erase_tag())); From 11464e714a670c6304cd00d20c0e31cc66290866 Mon Sep 17 00:00:00 2001 From: LooMaclin Date: Tue, 9 Apr 2019 00:42:45 +0300 Subject: [PATCH 0012/3207] Improve miri's error reporting in check_in_alloc --- src/librustc_mir/interpret/memory.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 6475eac41e3a..3c7cded5ba60 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -252,7 +252,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Scalar::Ptr(ptr) => { // check this is not NULL -- which we can ensure only if this is in-bounds // of some (potentially dead) allocation. - let align = self.check_bounds_ptr(ptr, InboundsCheck::MaybeDead, CheckInAllocMsg::NullPointer)?; + let align = self.check_bounds_ptr(ptr, InboundsCheck::MaybeDead, + CheckInAllocMsg::NullPointer)?; (ptr.offset.bytes(), align) } Scalar::Bits { bits, size } => { From 32ba4bda7aa1b8e66714090d5a8e7253c83f8161 Mon Sep 17 00:00:00 2001 From: LooMaclin Date: Tue, 9 Apr 2019 01:11:02 +0300 Subject: [PATCH 0013/3207] Improve miri's error reporting in check_in_alloc --- src/librustc_mir/interpret/memory.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 3c7cded5ba60..cc8bed770c46 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -448,7 +448,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { "allocation missing in dead_alloc_map" )) }, - _ => err!(DanglingPointerDeref), + InboundsCheck::Live => err!(DanglingPointerDeref), }, } } From 9147e26fcb8d0f140d5c7f97a6063758ff5aeac4 Mon Sep 17 00:00:00 2001 From: LooMaclin Date: Tue, 9 Apr 2019 12:38:14 +0300 Subject: [PATCH 0014/3207] Improve miri's error reporting in check_in_alloc --- src/librustc/mir/interpret/allocation.rs | 9 ++++----- src/librustc_mir/hair/pattern/_match.rs | 7 +++---- src/librustc_mir/interpret/memory.rs | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 19f28b96c3a7..61f77171ce35 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -224,12 +224,11 @@ impl<'tcx, Tag: Copy, Extra> Allocation { cx: &impl HasDataLayout, ptr: Pointer, size: Size, - msg: CheckInAllocMsg, ) -> EvalResult<'tcx, &[u8]> // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 where Extra: AllocationExtra { - self.get_bytes_internal(cx, ptr, size, true, msg) + self.get_bytes_internal(cx, ptr, size, true, CheckInAllocMsg::MemoryAccess) } /// It is the caller's responsibility to handle undefined and pointer bytes. @@ -295,7 +294,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { // Go through `get_bytes` for checks and AllocationExtra hooks. // We read the null, so we include it in the request, but we want it removed // from the result! - Ok(&self.get_bytes(cx, ptr, size_with_null, CheckInAllocMsg::NullPointer)?[..size]) + Ok(&self.get_bytes(cx, ptr, size_with_null)?[..size]) } None => err!(UnterminatedCString(ptr.erase_tag())), } @@ -379,7 +378,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { { // get_bytes_unchecked tests relocation edges let bytes = self.get_bytes_with_undef_and_ptr(cx, ptr, size, - CheckInAllocMsg::PointerArithmetic)?; + CheckInAllocMsg::MemoryAccess)?; // Undef check happens *after* we established that the alignment is correct. // We must not return Ok() for unaligned pointers! if self.check_defined(ptr, size).is_err() { @@ -456,7 +455,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { }; let endian = cx.data_layout().endian; - let dst = self.get_bytes_mut(cx, ptr, type_size, CheckInAllocMsg::PointerArithmetic)?; + let dst = self.get_bytes_mut(cx, ptr, type_size, CheckInAllocMsg::MemoryAccess)?; write_target_uint(endian, dst, bytes).unwrap(); // See if we have to also write a relocation diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 1e2ffa5db440..303ffcb3bfb3 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -172,7 +172,7 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, Const}; use rustc::ty::layout::{Integer, IntegerExt, VariantIdx, Size}; use rustc::mir::Field; -use rustc::mir::interpret::{ConstValue, Scalar, truncate, CheckInAllocMsg}; +use rustc::mir::interpret::{ConstValue, Scalar, truncate}; use rustc::util::common::ErrorReported; use syntax::attr::{SignedInt, UnsignedInt}; @@ -1418,8 +1418,7 @@ fn slice_pat_covered_by_const<'tcx>( return Ok(false); } let n = n.assert_usize(tcx).unwrap(); - alloc.get_bytes(&tcx, ptr, Size::from_bytes(n), - CheckInAllocMsg::OutOfBounds).unwrap() + alloc.get_bytes(&tcx, ptr, Size::from_bytes(n)).unwrap() }, // a slice fat pointer to a zero length slice (ConstValue::Slice(Scalar::Bits { .. }, 0), ty::Slice(t)) => { @@ -1444,7 +1443,7 @@ fn slice_pat_covered_by_const<'tcx>( tcx.alloc_map .lock() .unwrap_memory(ptr.alloc_id) - .get_bytes(&tcx, ptr, Size::from_bytes(n), CheckInAllocMsg::OutOfBounds) + .get_bytes(&tcx, ptr, Size::from_bytes(n)) .unwrap() }, _ => bug!( diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index cc8bed770c46..b9e2b9d499e5 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -606,7 +606,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { Ok(&[]) } else { let ptr = ptr.to_ptr()?; - self.get(ptr.alloc_id)?.get_bytes(self, ptr, size, CheckInAllocMsg::MemoryAccess) + self.get(ptr.alloc_id)?.get_bytes(self, ptr, size) } } } From 30a96267a6050c55e1f2bb1c540458a88fdb9567 Mon Sep 17 00:00:00 2001 From: LooMaclin Date: Wed, 10 Apr 2019 04:18:19 +0300 Subject: [PATCH 0015/3207] Improve miri's error reporting in check_in_alloc --- src/librustc/mir/interpret/allocation.rs | 18 +++++++----------- src/librustc_mir/interpret/memory.rs | 4 ++-- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 61f77171ce35..433c105231e0 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -239,12 +239,11 @@ impl<'tcx, Tag: Copy, Extra> Allocation { cx: &impl HasDataLayout, ptr: Pointer, size: Size, - msg: CheckInAllocMsg, ) -> EvalResult<'tcx, &[u8]> // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 where Extra: AllocationExtra { - self.get_bytes_internal(cx, ptr, size, false, msg) + self.get_bytes_internal(cx, ptr, size, false, CheckInAllocMsg::MemoryAccess) } /// Just calling this already marks everything as defined and removes relocations, @@ -254,13 +253,12 @@ impl<'tcx, Tag: Copy, Extra> Allocation { cx: &impl HasDataLayout, ptr: Pointer, size: Size, - msg: CheckInAllocMsg, ) -> EvalResult<'tcx, &mut [u8]> // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 where Extra: AllocationExtra { assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); - self.check_bounds(cx, ptr, size, msg)?; + self.check_bounds(cx, ptr, size, CheckInAllocMsg::MemoryAccess)?; self.mark_definedness(ptr, size, true)?; self.clear_relocations(cx, ptr, size)?; @@ -314,7 +312,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { where Extra: AllocationExtra { // Check bounds and relocations on the edges - self.get_bytes_with_undef_and_ptr(cx, ptr, size, CheckInAllocMsg::OutOfBounds)?; + self.get_bytes_with_undef_and_ptr(cx, ptr, size)?; // Check undef and ptr if !allow_ptr_and_undef { self.check_defined(ptr, size)?; @@ -335,8 +333,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 where Extra: AllocationExtra { - let bytes = self.get_bytes_mut(cx, ptr, Size::from_bytes(src.len() as u64), - CheckInAllocMsg::MemoryAccess)?; + let bytes = self.get_bytes_mut(cx, ptr, Size::from_bytes(src.len() as u64))?; bytes.clone_from_slice(src); Ok(()) } @@ -352,7 +349,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 where Extra: AllocationExtra { - let bytes = self.get_bytes_mut(cx, ptr, count, CheckInAllocMsg::MemoryAccess)?; + let bytes = self.get_bytes_mut(cx, ptr, count)?; for b in bytes { *b = val; } @@ -377,8 +374,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { where Extra: AllocationExtra { // get_bytes_unchecked tests relocation edges - let bytes = self.get_bytes_with_undef_and_ptr(cx, ptr, size, - CheckInAllocMsg::MemoryAccess)?; + let bytes = self.get_bytes_with_undef_and_ptr(cx, ptr, size)?; // Undef check happens *after* we established that the alignment is correct. // We must not return Ok() for unaligned pointers! if self.check_defined(ptr, size).is_err() { @@ -455,7 +451,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { }; let endian = cx.data_layout().endian; - let dst = self.get_bytes_mut(cx, ptr, type_size, CheckInAllocMsg::MemoryAccess)?; + let dst = self.get_bytes_mut(cx, ptr, type_size)?; write_target_uint(endian, dst, bytes).unwrap(); // See if we have to also write a relocation diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index b9e2b9d499e5..e8ae7ab579b9 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -731,10 +731,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { // This checks relocation edges on the src. let src_bytes = self.get(src.alloc_id)? - .get_bytes_with_undef_and_ptr(&tcx, src, size, CheckInAllocMsg::MemoryAccess)? + .get_bytes_with_undef_and_ptr(&tcx, src, size)? .as_ptr(); let dest_bytes = self.get_mut(dest.alloc_id)? - .get_bytes_mut(&tcx, dest, size * length, CheckInAllocMsg::MemoryAccess)? + .get_bytes_mut(&tcx, dest, size * length)? .as_mut_ptr(); // SAFE: The above indexing would have panicked if there weren't at least `size` bytes From a4a07e00ced90e076dbadd8b350db527bcc588bd Mon Sep 17 00:00:00 2001 From: Tobia Date: Mon, 1 Apr 2019 18:16:03 +0900 Subject: [PATCH 0016/3207] Replaced linear token counting macros with optimized implementation --- src/librustc/hir/map/definitions.rs | 12 ++++++++++-- src/libserialize/serialize.rs | 17 ++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 1006d813e65e..c72edb6cc6d7 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -696,9 +696,17 @@ impl DefPathData { } } +/// Evaluates to the number of tokens passed to it. +/// +/// Logarithmic counting: every one or two recursive expansions, the number of +/// tokens to count is divided by two, instead of being reduced by one. +/// Therefore, the recursion depth is the binary logarithm of the number of +/// tokens to count, and the expanded tree is likewise very small. macro_rules! count { - () => (0usize); - ( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*)); + () => (0usize); + ($one:tt) => (1usize); + ($($pairs:tt $_p:tt)*) => (count!($($pairs)*) << 1usize); + ($odd:tt $($rest:tt)*) => (count!($($rest)*) | 1usize); } // We define the GlobalMetaDataKind enum with this macro because we want to diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index cf948078b08c..d53891828f1c 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -723,10 +723,17 @@ macro_rules! peel { ($name:ident, $($other:ident,)*) => (tuple! { $($other,)* }) } -/// Evaluates to the number of identifiers passed to it, for example: `count_idents!(a, b, c) == 3 -macro_rules! count_idents { - () => { 0 }; - ($_i:ident, $($rest:ident,)*) => { 1 + count_idents!($($rest,)*) } +/// Evaluates to the number of tokens passed to it. +/// +/// Logarithmic counting: every one or two recursive expansions, the number of +/// tokens to count is divided by two, instead of being reduced by one. +/// Therefore, the recursion depth is the binary logarithm of the number of +/// tokens to count, and the expanded tree is likewise very small. +macro_rules! count { + () => (0usize); + ($one:tt) => (1usize); + ($($pairs:tt $_p:tt)*) => (count!($($pairs)*) << 1usize); + ($odd:tt $($rest:tt)*) => (count!($($rest)*) | 1usize); } macro_rules! tuple { @@ -735,7 +742,7 @@ macro_rules! tuple { impl<$($name:Decodable),*> Decodable for ($($name,)*) { #[allow(non_snake_case)] fn decode(d: &mut D) -> Result<($($name,)*), D::Error> { - let len: usize = count_idents!($($name,)*); + let len: usize = count!($($name)*); d.read_tuple(len, |d| { let mut i = 0; let ret = ($(d.read_tuple_arg({ i+=1; i-1 }, |d| -> Result<$name, D::Error> { From 0d97ad383412970b39275226bdfde7393d73867f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 16 Apr 2019 19:24:28 +0300 Subject: [PATCH 0017/3207] Update src/librustc/mir/interpret/allocation.rs Co-Authored-By: LooMaclin --- src/librustc/mir/interpret/allocation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 433c105231e0..35b8a5fda4fe 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -26,7 +26,7 @@ pub enum InboundsCheck { #[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)] pub enum CheckInAllocMsg { MemoryAccess, - NullPointer, + NullPointerTest, PointerArithmetic, OutOfBounds, } From 89feb6d5fd38aa9b493d6fc3ca5b546c373aac31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Romanowski?= Date: Thu, 18 Apr 2019 15:30:50 +0200 Subject: [PATCH 0018/3207] Clean up unicode.py script --- .gitignore | 1 + src/libcore/unicode/unicode.py | 372 ++++++++++++++++++++++++--------- 2 files changed, 270 insertions(+), 103 deletions(-) diff --git a/.gitignore b/.gitignore index 67e0dd8e795b..51f3e722ca7d 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ __pycache__/ /src/libcore/unicode/Scripts.txt /src/libcore/unicode/SpecialCasing.txt /src/libcore/unicode/UnicodeData.txt +/src/libcore/unicode/downloaded /stage[0-9]+/ /target target/ diff --git a/src/libcore/unicode/unicode.py b/src/libcore/unicode/unicode.py index ae356c3ff445..97c11fb795ea 100755 --- a/src/libcore/unicode/unicode.py +++ b/src/libcore/unicode/unicode.py @@ -1,35 +1,71 @@ #!/usr/bin/env python -# This script uses the following Unicode tables: -# - DerivedCoreProperties.txt -# - DerivedNormalizationProps.txt -# - EastAsianWidth.txt -# - auxiliary/GraphemeBreakProperty.txt -# - PropList.txt -# - ReadMe.txt -# - Scripts.txt -# - UnicodeData.txt -# +""" +Regenerate Unicode tables (tables.rs). +""" + +# This script uses the Unicode tables as defined +# in the UnicodeFiles class. + # Since this should not require frequent updates, we just store this # out-of-line and check the tables.rs file into git. -import fileinput, re, os, sys, operator, math, datetime +# Note that the "curl" program is required for operation. +# This script is compatible with Python 2.7 and 3.x. -# The directory in which this file resides. -fdir = os.path.dirname(os.path.realpath(__file__)) + "/" +import argparse +import datetime +import fileinput +import operator +import os +import re +import textwrap +import subprocess -preamble = ''' +from collections import namedtuple + + +# we don't use enum.Enum because of Python 2.7 compatibility +class UnicodeFiles(object): + # ReadMe does not contain any unicode data, we + # use it to extract versions. + README = "ReadMe.txt" + + DERIVED_CORE_PROPERTIES = "DerivedCoreProperties.txt" + DERIVED_NORMALIZATION_PROPS = "DerivedNormalizationProps.txt" + SPECIAL_CASING = "SpecialCasing.txt" + SCRIPTS = "Scripts.txt" + PROPS = "PropList.txt" + UNICODE_DATA = "UnicodeData.txt" + + +UnicodeFiles.ALL_FILES = tuple( + getattr(UnicodeFiles, name) for name in dir(UnicodeFiles) + if not name.startswith("_") +) + +# The directory this file is located in. +THIS_DIR = os.path.dirname(os.path.realpath(__file__)) + +# Where to download the Unicode data. The downloaded files +# will be placed in sub-directories named after Unicode version. +FETCH_DIR = os.path.join(THIS_DIR, "downloaded") + +FETCH_URL_LATEST = "ftp://ftp.unicode.org/Public/UNIDATA/{filename}" +FETCH_URL_VERSION = "ftp://ftp.unicode.org/Public/{version}/ucd/{filename}" + +PREAMBLE = """\ // NOTE: The following code was generated by "./unicode.py", do not edit directly #![allow(missing_docs, non_upper_case_globals, non_snake_case)] use unicode::version::UnicodeVersion; use unicode::bool_trie::{{BoolTrie, SmallBoolTrie}}; -'''.format(year = datetime.datetime.now().year) +""".format(year=datetime.datetime.now().year) # Mapping taken from Table 12 from: # http://www.unicode.org/reports/tr44/#General_Category_Values -expanded_categories = { +EXPANDED_CATEGORIES = { 'Lu': ['LC', 'L'], 'Ll': ['LC', 'L'], 'Lt': ['LC', 'L'], 'Lm': ['L'], 'Lo': ['L'], 'Mn': ['M'], 'Mc': ['M'], 'Me': ['M'], @@ -42,22 +78,101 @@ expanded_categories = { } # these are the surrogate codepoints, which are not valid rust characters -surrogate_codepoints = (0xd800, 0xdfff) +SURROGATE_CODEPOINTS = (0xd800, 0xdfff) -def fetch(f): - path = fdir + os.path.basename(f) - if not os.path.exists(path): - os.system("curl -o {0}{1} ftp://ftp.unicode.org/Public/UNIDATA/{1}".format(fdir, f)) +UnicodeData = namedtuple( + "UnicodeData", ("canon_decomp", "compat_decomp", "gencats", "combines", + "to_upper", "to_lower", "to_title", ) +) + +UnicodeVersion = namedtuple( + "UnicodeVersion", ("major", "minor", "micro", "as_str") +) + + +def fetch_files(version=None): + """ + Fetch all the Unicode files from unicode.org + + :param version: The desired Unicode version, as string. + (If None, defaults to latest final release available). + :return: The version downloaded (UnicodeVersion object). + """ + have_version = should_skip_fetch(version) + if have_version: + return have_version + + if version: + # check if the desired version exists on the server + get_fetch_url = lambda name: FETCH_URL_VERSION.format(version=version, filename=name) + else: + # extract the latest version + get_fetch_url = lambda name: FETCH_URL_LATEST.format(filename=name) + + readme_url = get_fetch_url(UnicodeFiles.README) + + print("Fetching: {}".format(readme_url)) + readme_content = subprocess.check_output(("curl", readme_url)) + + unicode_version = parse_unicode_version( + str(readme_content, "utf8") + ) + + download_dir = os.path.join(FETCH_DIR, unicode_version.as_str) + if not os.path.exists(download_dir): + # for 2.7 compat, we don't use exist_ok=True + os.makedirs(download_dir) + + for filename in UnicodeFiles.ALL_FILES: + file_path = os.path.join(download_dir, filename) + + if filename == UnicodeFiles.README: + with open(file_path, "wb") as fd: + fd.write(readme_content) + elif not os.path.exists(file_path): + url = get_fetch_url(filename) + print("Fetching: {}".format(url)) + subprocess.check_call(("curl", "-o", file_path, url)) + + return unicode_version + + +def should_skip_fetch(version): + if not version: + # should always check latest version + return False + + fetch_dir = os.path.join(FETCH_DIR, version) + + for filename in UnicodeFiles.ALL_FILES: + file_path = os.path.join(fetch_dir, filename) + + if not os.path.exists(file_path): + return False + + with open(os.path.join(fetch_dir, UnicodeFiles.README)) as fd: + return parse_unicode_version(fd.read()) + + +def parse_unicode_version(readme_content): + # "raw string" is necessary for \d not being treated as escape char + # (for the sake of compat with future Python versions) + # see: https://docs.python.org/3.6/whatsnew/3.6.html#deprecated-python-behavior + pattern = r"for Version (\d+)\.(\d+)\.(\d+) of the Unicode" + groups = re.search(pattern, readme_content).groups() + + return UnicodeVersion(*map(int, groups), as_str=".".join(groups)) + + +def get_unicode_file_path(unicode_version, filename): + return os.path.join(FETCH_DIR, unicode_version.as_str, filename) - if not os.path.exists(path): - sys.stderr.write("cannot load %s" % f) - exit(1) def is_surrogate(n): - return surrogate_codepoints[0] <= n <= surrogate_codepoints[1] + return SURROGATE_CODEPOINTS[0] <= n <= SURROGATE_CODEPOINTS[1] -def load_unicode_data(f): - fetch(f) + +def load_unicode_data(file_path): gencats = {} to_lower = {} to_upper = {} @@ -68,8 +183,8 @@ def load_unicode_data(f): udict = {} range_start = -1 - for line in fileinput.input(fdir + f): - data = line.split(';') + for line in fileinput.input(file_path): + data = line.split(";") if len(data) != 15: continue cp = int(data[0], 16) @@ -104,7 +219,7 @@ def load_unicode_data(f): # store decomposition, if given if decomp != "": - if decomp.startswith('<'): + if decomp.startswith("<"): seq = [] for i in decomp.split()[1:]: seq.append(int(i, 16)) @@ -116,7 +231,7 @@ def load_unicode_data(f): canon_decomp[code] = seq # place letter in categories as appropriate - for cat in [gencat, "Assigned"] + expanded_categories.get(gencat, []): + for cat in [gencat, "Assigned"] + EXPANDED_CATEGORIES.get(gencat, []): if cat not in gencats: gencats[cat] = [] gencats[cat].append(code) @@ -136,12 +251,15 @@ def load_unicode_data(f): gencats = group_cats(gencats) combines = to_combines(group_cats(combines)) - return (canon_decomp, compat_decomp, gencats, combines, to_upper, to_lower, to_title) + return UnicodeData( + canon_decomp, compat_decomp, gencats, combines, to_upper, + to_lower, to_title, + ) -def load_special_casing(f, to_upper, to_lower, to_title): - fetch(f) - for line in fileinput.input(fdir + f): - data = line.split('#')[0].split(';') + +def load_special_casing(file_path, unicode_data): + for line in fileinput.input(file_path): + data = line.split("#")[0].split(";") if len(data) == 5: code, lower, title, upper, _comment = data elif len(data) == 6: @@ -155,7 +273,9 @@ def load_special_casing(f, to_upper, to_lower, to_title): title = title.strip() upper = upper.strip() key = int(code, 16) - for (map_, values) in [(to_lower, lower), (to_upper, upper), (to_title, title)]: + for (map_, values) in ((unicode_data.to_lower, lower), + (unicode_data.to_upper, upper), + (unicode_data.to_title, title)): if values != code: values = [int(i, 16) for i in values.split()] for _ in range(len(values), 3): @@ -163,12 +283,14 @@ def load_special_casing(f, to_upper, to_lower, to_title): assert len(values) == 3 map_[key] = values + def group_cats(cats): cats_out = {} for cat in cats: cats_out[cat] = group_cat(cats[cat]) return cats_out + def group_cat(cat): cat_out = [] letters = sorted(set(cat)) @@ -185,6 +307,7 @@ def group_cat(cat): cat_out.append((cur_start, cur_end)) return cat_out + def ungroup_cat(cat): cat_out = [] for (lo, hi) in cat: @@ -193,21 +316,24 @@ def ungroup_cat(cat): lo += 1 return cat_out + def gen_unassigned(assigned): assigned = set(assigned) return ([i for i in range(0, 0xd800) if i not in assigned] + [i for i in range(0xe000, 0x110000) if i not in assigned]) + def to_combines(combs): combs_out = [] for comb in combs: for (lo, hi) in combs[comb]: combs_out.append((lo, hi, comb)) - combs_out.sort(key=lambda comb: comb[0]) + combs_out.sort(key=lambda c: c[0]) return combs_out + def format_table_content(f, content, indent): - line = " "*indent + line = " " * indent first = True for chunk in content.split(","): if len(line) + len(chunk) < 98: @@ -218,16 +344,19 @@ def format_table_content(f, content, indent): first = False else: f.write(line + ",\n") - line = " "*indent + chunk + line = " " * indent + chunk f.write(line) -def load_properties(f, interestingprops): - fetch(f) - props = {} - re1 = re.compile("^ *([0-9A-F]+) *; *(\w+)") - re2 = re.compile("^ *([0-9A-F]+)\.\.([0-9A-F]+) *; *(\w+)") - for line in fileinput.input(fdir + os.path.basename(f)): +def load_properties(file_path, interestingprops): + props = {} + # "raw string" is necessary for \w not to be treated as escape char + # (for the sake of compat with future Python versions) + # see: https://docs.python.org/3.6/whatsnew/3.6.html#deprecated-python-behavior + re1 = re.compile(r"^ *([0-9A-F]+) *; *(\w+)") + re2 = re.compile(r"^ *([0-9A-F]+)\.\.([0-9A-F]+) *; *(\w+)") + + for line in fileinput.input(file_path): prop = None d_lo = 0 d_hi = 0 @@ -258,10 +387,12 @@ def load_properties(f, interestingprops): return props + def escape_char(c): return "'\\u{%x}'" % c if c != 0 else "'\\0'" -def emit_table(f, name, t_data, t_type = "&[(char, char)]", is_pub=True, + +def emit_table(f, name, t_data, t_type="&[(char, char)]", is_pub=True, pfun=lambda x: "(%s,%s)" % (escape_char(x[0]), escape_char(x[1]))): pub_string = "" if is_pub: @@ -277,6 +408,7 @@ def emit_table(f, name, t_data, t_type = "&[(char, char)]", is_pub=True, format_table_content(f, data, 8) f.write("\n ];\n\n") + def compute_trie(rawdata, chunksize): root = [] childmap = {} @@ -288,10 +420,11 @@ def compute_trie(rawdata, chunksize): childmap[child] = len(childmap) child_data.extend(data) root.append(childmap[child]) - return (root, child_data) + return root, child_data + def emit_bool_trie(f, name, t_data, is_pub=True): - CHUNK = 64 + chunk_size = 64 rawdata = [False] * 0x110000 for (lo, hi) in t_data: for cp in range(lo, hi + 1): @@ -299,7 +432,7 @@ def emit_bool_trie(f, name, t_data, is_pub=True): # convert to bitmap chunks of 64 bits each chunks = [] - for i in range(0x110000 // CHUNK): + for i in range(0x110000 // chunk_size): chunk = 0 for j in range(64): if rawdata[i * 64 + j]: @@ -311,12 +444,12 @@ def emit_bool_trie(f, name, t_data, is_pub=True): pub_string = "pub " f.write(" %sconst %s: &super::BoolTrie = &super::BoolTrie {\n" % (pub_string, name)) f.write(" r1: [\n") - data = ','.join('0x%016x' % chunk for chunk in chunks[0:0x800 // CHUNK]) + data = ','.join('0x%016x' % chunk for chunk in chunks[0:0x800 // chunk_size]) format_table_content(f, data, 12) f.write("\n ],\n") # 0x800..0x10000 trie - (r2, r3) = compute_trie(chunks[0x800 // CHUNK : 0x10000 // CHUNK], 64 // CHUNK) + (r2, r3) = compute_trie(chunks[0x800 // chunk_size : 0x10000 // chunk_size], 64 // chunk_size) f.write(" r2: [\n") data = ','.join(str(node) for node in r2) format_table_content(f, data, 12) @@ -327,7 +460,7 @@ def emit_bool_trie(f, name, t_data, is_pub=True): f.write("\n ],\n") # 0x10000..0x110000 trie - (mid, r6) = compute_trie(chunks[0x10000 // CHUNK : 0x110000 // CHUNK], 64 // CHUNK) + (mid, r6) = compute_trie(chunks[0x10000 // chunk_size : 0x110000 // chunk_size], 64 // chunk_size) (r4, r5) = compute_trie(mid, 64) f.write(" r4: [\n") data = ','.join(str(node) for node in r4) @@ -344,6 +477,7 @@ def emit_bool_trie(f, name, t_data, is_pub=True): f.write(" };\n\n") + def emit_small_bool_trie(f, name, t_data, is_pub=True): last_chunk = max(hi // 64 for (lo, hi) in t_data) n_chunks = last_chunk + 1 @@ -374,6 +508,7 @@ def emit_small_bool_trie(f, name, t_data, is_pub=True): f.write(" };\n\n") + def emit_property_module(f, mod, tbl, emit): f.write("pub mod %s {\n" % mod) for cat in sorted(emit): @@ -389,7 +524,8 @@ def emit_property_module(f, mod, tbl, emit): f.write(" }\n\n") f.write("}\n\n") -def emit_conversions_module(f, to_upper, to_lower, to_title): + +def emit_conversions_module(f, unicode_data): f.write("pub mod conversions {") f.write(""" pub fn to_lower(c: char) -> [char; 3] { @@ -414,74 +550,104 @@ def emit_conversions_module(f, to_upper, to_lower, to_title): t_type = "&[(char, [char; 3])]" pfun = lambda x: "(%s,[%s,%s,%s])" % ( escape_char(x[0]), escape_char(x[1][0]), escape_char(x[1][1]), escape_char(x[1][2])) - emit_table(f, "to_lowercase_table", - sorted(to_lower.items(), key=operator.itemgetter(0)), - is_pub=False, t_type = t_type, pfun=pfun) - emit_table(f, "to_uppercase_table", - sorted(to_upper.items(), key=operator.itemgetter(0)), - is_pub=False, t_type = t_type, pfun=pfun) - f.write("}\n\n") -def emit_norm_module(f, canon, compat, combine, norm_props): - canon_keys = sorted(canon.keys()) + emit_table(f, + name="to_lowercase_table", + t_data=sorted(unicode_data.to_lower.items(), key=operator.itemgetter(0)), + t_type=t_type, + is_pub=False, + pfun=pfun) - compat_keys = sorted(compat.keys()) + emit_table(f, + name="to_uppercase_table", + t_data=sorted(unicode_data.to_upper.items(), key=operator.itemgetter(0)), + t_type=t_type, + is_pub=False, + pfun=pfun) + + f.write("}\n") + + +def emit_norm_module(f, unicode_data, norm_props): + canon_keys = sorted(unicode_data.canon_decomp.keys()) canon_comp = {} comp_exclusions = norm_props["Full_Composition_Exclusion"] for char in canon_keys: if any(lo <= char <= hi for lo, hi in comp_exclusions): continue - decomp = canon[char] + decomp = unicode_data.canon_decomp[char] if len(decomp) == 2: if decomp[0] not in canon_comp: canon_comp[decomp[0]] = [] - canon_comp[decomp[0]].append( (decomp[1], char) ) - canon_comp_keys = sorted(canon_comp.keys()) + canon_comp[decomp[0]].append((decomp[1], char)) -if __name__ == "__main__": - r = fdir + "tables.rs" - if os.path.exists(r): - os.remove(r) - with open(r, "w") as rf: + +def parse_args(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("-v", "--version", default=None, type=str, + help="Unicode version to use (if not specified," + " defaults to latest available final release).") + + return parser.parse_args() + + +def main(): + args = parse_args() + + unicode_version = fetch_files(args.version) + print("Using Unicode version: {}".format(unicode_version.as_str)) + + tables_rs_path = os.path.join(THIS_DIR, "tables.rs") + if os.path.exists(tables_rs_path): + os.remove(tables_rs_path) + + with open(tables_rs_path, "w") as rf: # write the file's preamble - rf.write(preamble) + rf.write(PREAMBLE) + + unicode_version_notice = textwrap.dedent(""" + /// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of + /// `char` and `str` methods are based on. + #[unstable(feature = "unicode_version", issue = "49726")] + pub const UNICODE_VERSION: UnicodeVersion = UnicodeVersion {{ + major: {version.major}, + minor: {version.minor}, + micro: {version.micro}, + _priv: (), + }}; + """).format(version=unicode_version) + rf.write(unicode_version_notice) + + get_path = lambda f: get_unicode_file_path(unicode_version, f) + + unicode_data = load_unicode_data(get_path(UnicodeFiles.UNICODE_DATA)) + load_special_casing(get_path(UnicodeFiles.SPECIAL_CASING), unicode_data) - # download and parse all the data - fetch("ReadMe.txt") - with open(fdir + "ReadMe.txt") as readme: - pattern = "for Version (\d+)\.(\d+)\.(\d+) of the Unicode" - unicode_version = re.search(pattern, readme.read()).groups() - rf.write(""" -/// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of -/// `char` and `str` methods are based on. -#[unstable(feature = "unicode_version", issue = "49726")] -pub const UNICODE_VERSION: UnicodeVersion = UnicodeVersion { - major: %s, - minor: %s, - micro: %s, - _priv: (), -}; -""" % unicode_version) - (canon_decomp, compat_decomp, gencats, combines, - to_upper, to_lower, to_title) = load_unicode_data("UnicodeData.txt") - load_special_casing("SpecialCasing.txt", to_upper, to_lower, to_title) want_derived = ["XID_Start", "XID_Continue", "Alphabetic", "Lowercase", "Uppercase", "Cased", "Case_Ignorable", "Grapheme_Extend"] - derived = load_properties("DerivedCoreProperties.txt", want_derived) - scripts = load_properties("Scripts.txt", []) - props = load_properties("PropList.txt", - ["White_Space", "Join_Control", "Noncharacter_Code_Point", "Pattern_White_Space"]) - norm_props = load_properties("DerivedNormalizationProps.txt", - ["Full_Composition_Exclusion"]) + derived = load_properties(get_path(UnicodeFiles.DERIVED_CORE_PROPERTIES), want_derived) + + # TODO scripts not used? + scripts = load_properties(get_path(UnicodeFiles.SCRIPTS), []) + props = load_properties(get_path(UnicodeFiles.PROPS), + ["White_Space", "Join_Control", "Noncharacter_Code_Point", + "Pattern_White_Space"]) + norm_props = load_properties(get_path(UnicodeFiles.DERIVED_NORMALIZATION_PROPS), + ["Full_Composition_Exclusion"]) # category tables - for (name, cat, pfuns) in ("general_category", gencats, ["N", "Cc"]), \ - ("derived_property", derived, want_derived), \ - ("property", props, ["White_Space", "Pattern_White_Space"]): + for (name, cat, pfuns) in (("general_category", unicode_data.gencats, ["N", "Cc"]), + ("derived_property", derived, want_derived), + ("property", props, ["White_Space", "Pattern_White_Space"])): emit_property_module(rf, name, cat, pfuns) # normalizations and conversions module - emit_norm_module(rf, canon_decomp, compat_decomp, combines, norm_props) - emit_conversions_module(rf, to_upper, to_lower, to_title) + emit_norm_module(rf, unicode_data, norm_props) + emit_conversions_module(rf, unicode_data) + print("Regenerated tables.rs.") + + +if __name__ == "__main__": + main() From a580421afbd6ee93aaab0ad01dee3df8343a88dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Romanowski?= Date: Thu, 18 Apr 2019 16:16:34 +0200 Subject: [PATCH 0019/3207] More cleanups for unicode.py --- src/libcore/unicode/unicode.py | 48 ++++++++++++++++------------------ 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/src/libcore/unicode/unicode.py b/src/libcore/unicode/unicode.py index 97c11fb795ea..447f4274c18d 100755 --- a/src/libcore/unicode/unicode.py +++ b/src/libcore/unicode/unicode.py @@ -28,14 +28,14 @@ from collections import namedtuple # we don't use enum.Enum because of Python 2.7 compatibility class UnicodeFiles(object): # ReadMe does not contain any unicode data, we - # use it to extract versions. + # only use it to extract versions. README = "ReadMe.txt" DERIVED_CORE_PROPERTIES = "DerivedCoreProperties.txt" DERIVED_NORMALIZATION_PROPS = "DerivedNormalizationProps.txt" - SPECIAL_CASING = "SpecialCasing.txt" - SCRIPTS = "Scripts.txt" PROPS = "PropList.txt" + SCRIPTS = "Scripts.txt" + SPECIAL_CASING = "SpecialCasing.txt" UNICODE_DATA = "UnicodeData.txt" @@ -66,15 +66,15 @@ use unicode::bool_trie::{{BoolTrie, SmallBoolTrie}}; # Mapping taken from Table 12 from: # http://www.unicode.org/reports/tr44/#General_Category_Values EXPANDED_CATEGORIES = { - 'Lu': ['LC', 'L'], 'Ll': ['LC', 'L'], 'Lt': ['LC', 'L'], - 'Lm': ['L'], 'Lo': ['L'], - 'Mn': ['M'], 'Mc': ['M'], 'Me': ['M'], - 'Nd': ['N'], 'Nl': ['N'], 'No': ['N'], - 'Pc': ['P'], 'Pd': ['P'], 'Ps': ['P'], 'Pe': ['P'], - 'Pi': ['P'], 'Pf': ['P'], 'Po': ['P'], - 'Sm': ['S'], 'Sc': ['S'], 'Sk': ['S'], 'So': ['S'], - 'Zs': ['Z'], 'Zl': ['Z'], 'Zp': ['Z'], - 'Cc': ['C'], 'Cf': ['C'], 'Cs': ['C'], 'Co': ['C'], 'Cn': ['C'], + "Lu": ["LC", "L"], "Ll": ["LC", "L"], "Lt": ["LC", "L"], + "Lm": ["L"], "Lo": ["L"], + "Mn": ["M"], "Mc": ["M"], "Me": ["M"], + "Nd": ["N"], "Nl": ["N"], "No": ["N"], + "Pc": ["P"], "Pd": ["P"], "Ps": ["P"], "Pe": ["P"], + "Pi": ["P"], "Pf": ["P"], "Po": ["P"], + "Sm": ["S"], "Sc": ["S"], "Sk": ["S"], "So": ["S"], + "Zs": ["Z"], "Zl": ["Z"], "Zp": ["Z"], + "Cc": ["C"], "Cf": ["C"], "Cs": ["C"], "Co": ["C"], "Cn": ["C"], } # these are the surrogate codepoints, which are not valid rust characters @@ -115,7 +115,7 @@ def fetch_files(version=None): readme_content = subprocess.check_output(("curl", readme_url)) unicode_version = parse_unicode_version( - str(readme_content, "utf8") + readme_content.decode("utf8") ) download_dir = os.path.join(FETCH_DIR, unicode_version.as_str) @@ -415,7 +415,7 @@ def compute_trie(rawdata, chunksize): child_data = [] for i in range(len(rawdata) // chunksize): data = rawdata[i * chunksize: (i + 1) * chunksize] - child = '|'.join(map(str, data)) + child = "|".join(map(str, data)) if child not in childmap: childmap[child] = len(childmap) child_data.extend(data) @@ -444,18 +444,18 @@ def emit_bool_trie(f, name, t_data, is_pub=True): pub_string = "pub " f.write(" %sconst %s: &super::BoolTrie = &super::BoolTrie {\n" % (pub_string, name)) f.write(" r1: [\n") - data = ','.join('0x%016x' % chunk for chunk in chunks[0:0x800 // chunk_size]) + data = ",".join("0x%016x" % chunk for chunk in chunks[0:0x800 // chunk_size]) format_table_content(f, data, 12) f.write("\n ],\n") # 0x800..0x10000 trie (r2, r3) = compute_trie(chunks[0x800 // chunk_size : 0x10000 // chunk_size], 64 // chunk_size) f.write(" r2: [\n") - data = ','.join(str(node) for node in r2) + data = ",".join(str(node) for node in r2) format_table_content(f, data, 12) f.write("\n ],\n") f.write(" r3: &[\n") - data = ','.join('0x%016x' % chunk for chunk in r3) + data = ",".join("0x%016x" % chunk for chunk in r3) format_table_content(f, data, 12) f.write("\n ],\n") @@ -463,15 +463,15 @@ def emit_bool_trie(f, name, t_data, is_pub=True): (mid, r6) = compute_trie(chunks[0x10000 // chunk_size : 0x110000 // chunk_size], 64 // chunk_size) (r4, r5) = compute_trie(mid, 64) f.write(" r4: [\n") - data = ','.join(str(node) for node in r4) + data = ",".join(str(node) for node in r4) format_table_content(f, data, 12) f.write("\n ],\n") f.write(" r5: &[\n") - data = ','.join(str(node) for node in r5) + data = ",".join(str(node) for node in r5) format_table_content(f, data, 12) f.write("\n ],\n") f.write(" r6: &[\n") - data = ','.join('0x%016x' % chunk for chunk in r6) + data = ",".join("0x%016x" % chunk for chunk in r6) format_table_content(f, data, 12) f.write("\n ],\n") @@ -497,12 +497,12 @@ def emit_small_bool_trie(f, name, t_data, is_pub=True): (r1, r2) = compute_trie(chunks, 1) f.write(" r1: &[\n") - data = ','.join(str(node) for node in r1) + data = ",".join(str(node) for node in r1) format_table_content(f, data, 12) f.write("\n ],\n") f.write(" r2: &[\n") - data = ','.join('0x%016x' % node for node in r2) + data = ",".join("0x%016x" % node for node in r2) format_table_content(f, data, 12) f.write("\n ],\n") @@ -599,11 +599,9 @@ def main(): print("Using Unicode version: {}".format(unicode_version.as_str)) tables_rs_path = os.path.join(THIS_DIR, "tables.rs") - if os.path.exists(tables_rs_path): - os.remove(tables_rs_path) + # will overwrite the file if it exists with open(tables_rs_path, "w") as rf: - # write the file's preamble rf.write(PREAMBLE) unicode_version_notice = textwrap.dedent(""" From edbc27da2dc5a75f8e0ac70e7a5e07aa6f6f0a16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Romanowski?= Date: Thu, 18 Apr 2019 17:14:31 +0200 Subject: [PATCH 0020/3207] Fix tidy errors --- src/libcore/unicode/unicode.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libcore/unicode/unicode.py b/src/libcore/unicode/unicode.py index 447f4274c18d..e645c3f33c84 100755 --- a/src/libcore/unicode/unicode.py +++ b/src/libcore/unicode/unicode.py @@ -460,7 +460,8 @@ def emit_bool_trie(f, name, t_data, is_pub=True): f.write("\n ],\n") # 0x10000..0x110000 trie - (mid, r6) = compute_trie(chunks[0x10000 // chunk_size : 0x110000 // chunk_size], 64 // chunk_size) + (mid, r6) = compute_trie(chunks[0x10000 // chunk_size : 0x110000 // chunk_size], + 64 // chunk_size) (r4, r5) = compute_trie(mid, 64) f.write(" r4: [\n") data = ",".join(str(node) for node in r4) @@ -626,7 +627,7 @@ def main(): "Cased", "Case_Ignorable", "Grapheme_Extend"] derived = load_properties(get_path(UnicodeFiles.DERIVED_CORE_PROPERTIES), want_derived) - # TODO scripts not used? + # FIXME scripts not used? scripts = load_properties(get_path(UnicodeFiles.SCRIPTS), []) props = load_properties(get_path(UnicodeFiles.PROPS), ["White_Space", "Join_Control", "Noncharacter_Code_Point", From 15d50deeb457d5761802dd1066f7bfbeaf71c2cb Mon Sep 17 00:00:00 2001 From: LooMaclin Date: Fri, 19 Apr 2019 02:10:59 +0300 Subject: [PATCH 0021/3207] Improve miri's error reporting in check_in_alloc --- src/librustc/mir/interpret/allocation.rs | 14 +++++++------- src/librustc/mir/interpret/error.rs | 2 +- src/librustc_mir/interpret/memory.rs | 2 +- src/librustc_mir/interpret/operand.rs | 2 +- src/librustc_mir/interpret/validity.rs | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 35b8a5fda4fe..79ef81e81eb1 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -25,19 +25,19 @@ pub enum InboundsCheck { /// Used by `check_in_alloc` to indicate context of check #[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)] pub enum CheckInAllocMsg { - MemoryAccess, + MemoryAccessTest, NullPointerTest, - PointerArithmetic, - OutOfBounds, + PointerArithmeticTest, + InboundsTest, } impl Display for CheckInAllocMsg { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", match *self { - CheckInAllocMsg::MemoryAccess => "memory access", - CheckInAllocMsg::NullPointer => "null pointer", - CheckInAllocMsg::PointerArithmetic => "pointer arithmetic", - CheckInAllocMsg::OutOfBounds => "out of bounds", + CheckInAllocMsg::MemoryAccessTest => "Memory access", + CheckInAllocMsg::NullPointerTest => "Null pointer", + CheckInAllocMsg::PointerArithmeticTest => "Pointer arithmetic", + CheckInAllocMsg::InboundsTest => "Inbounds", }) } } diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 23a47fb1a35e..2fe6982fdf82 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -461,7 +461,7 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for InterpError<'tcx, O> { use self::InterpError::*; match *self { PointerOutOfBounds { ptr, msg, allocation_size } => { - write!(f, "Pointer must be in-bounds{} at offset {}, but is outside bounds of \ + write!(f, "{} test failed: pointer must be in-bounds at offset {}, but is outside bounds of \ allocation {} which has size {}", msg, ptr.offset.bytes(), ptr.alloc_id, allocation_size.bytes()) }, diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index e8ae7ab579b9..b176a0ac61f3 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -253,7 +253,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { // check this is not NULL -- which we can ensure only if this is in-bounds // of some (potentially dead) allocation. let align = self.check_bounds_ptr(ptr, InboundsCheck::MaybeDead, - CheckInAllocMsg::NullPointer)?; + CheckInAllocMsg::NullPointerTest)?; (ptr.offset.bytes(), align) } Scalar::Bits { bits, size } => { diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 38fe1caa41f6..8d9550e8f07b 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -668,7 +668,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> // The niche must be just 0 (which an inbounds pointer value never is) let ptr_valid = niche_start == 0 && variants_start == variants_end && self.memory.check_bounds_ptr(ptr, InboundsCheck::MaybeDead, - CheckInAllocMsg::OutOfBounds).is_ok(); + CheckInAllocMsg::NullPointerTest).is_ok(); if !ptr_valid { return err!(InvalidDiscriminant(raw_discr.erase_tag())); } diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 965b2898cad5..ebba704e4f4d 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -394,7 +394,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> try_validation!( self.ecx.memory .get(ptr.alloc_id)? - .check_bounds(self.ecx, ptr, size, CheckInAllocMsg::OutOfBounds), + .check_bounds(self.ecx, ptr, size, CheckInAllocMsg::InboundsTest), "dangling (not entirely in bounds) reference", self.path); } // Check if we have encountered this pointer+layout combination From a54e3cc9e7aa938ef6e4aa3ba00864bcefc717df Mon Sep 17 00:00:00 2001 From: LooMaclin Date: Fri, 19 Apr 2019 02:26:57 +0300 Subject: [PATCH 0022/3207] Improve miri's error reporting in check_in_alloc --- src/librustc/mir/interpret/allocation.rs | 6 +++--- src/librustc/mir/interpret/error.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 79ef81e81eb1..84733f9af6d5 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -228,7 +228,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 where Extra: AllocationExtra { - self.get_bytes_internal(cx, ptr, size, true, CheckInAllocMsg::MemoryAccess) + self.get_bytes_internal(cx, ptr, size, true, CheckInAllocMsg::MemoryAccessTest) } /// It is the caller's responsibility to handle undefined and pointer bytes. @@ -243,7 +243,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 where Extra: AllocationExtra { - self.get_bytes_internal(cx, ptr, size, false, CheckInAllocMsg::MemoryAccess) + self.get_bytes_internal(cx, ptr, size, false, CheckInAllocMsg::MemoryAccessTest) } /// Just calling this already marks everything as defined and removes relocations, @@ -258,7 +258,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation { where Extra: AllocationExtra { assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); - self.check_bounds(cx, ptr, size, CheckInAllocMsg::MemoryAccess)?; + self.check_bounds(cx, ptr, size, CheckInAllocMsg::MemoryAccessTest)?; self.mark_definedness(ptr, size, true)?; self.clear_relocations(cx, ptr, size)?; diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 2fe6982fdf82..cf2d12b59359 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -461,9 +461,9 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for InterpError<'tcx, O> { use self::InterpError::*; match *self { PointerOutOfBounds { ptr, msg, allocation_size } => { - write!(f, "{} test failed: pointer must be in-bounds at offset {}, but is outside bounds of \ - allocation {} which has size {}", msg, - ptr.offset.bytes(), ptr.alloc_id, allocation_size.bytes()) + write!(f, "{} test failed: pointer must be in-bounds at offset {}, \ + but is outside bounds of allocation {} which has size {}", + msg, ptr.offset.bytes(), ptr.alloc_id, allocation_size.bytes()) }, ValidationFailure(ref err) => { write!(f, "type validation failed: {}", err) From 2c9c978e1d4a3541d8df593346c7520c8ef4d69e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Romanowski?= Date: Fri, 19 Apr 2019 11:42:08 +0200 Subject: [PATCH 0023/3207] Refactor and document unicode.py script --- src/libcore/unicode/unicode.py | 798 +++++++++++++++++++++------------ 1 file changed, 507 insertions(+), 291 deletions(-) diff --git a/src/libcore/unicode/unicode.py b/src/libcore/unicode/unicode.py index e645c3f33c84..f66e82299100 100755 --- a/src/libcore/unicode/unicode.py +++ b/src/libcore/unicode/unicode.py @@ -16,13 +16,31 @@ Regenerate Unicode tables (tables.rs). import argparse import datetime import fileinput -import operator +import itertools import os import re import textwrap import subprocess -from collections import namedtuple +from collections import defaultdict, namedtuple + +try: + # Python 3 + from itertools import zip_longest + from io import StringIO +except ImportError: + # Python 2 compatibility + zip_longest = itertools.izip_longest + from StringIO import StringIO + +try: + # completely optional type hinting + # (Python 2 compatible using comments, + # see: https://mypy.readthedocs.io/en/latest/python2.html) + # This is very helpful in typing-aware IDE like PyCharm. + from typing import Any, Callable, Dict, Iterable, Iterator, List, Optional, Set, Tuple +except ImportError: + pass # we don't use enum.Enum because of Python 2.7 compatibility @@ -77,12 +95,21 @@ EXPANDED_CATEGORIES = { "Cc": ["C"], "Cf": ["C"], "Cs": ["C"], "Co": ["C"], "Cn": ["C"], } -# these are the surrogate codepoints, which are not valid rust characters -SURROGATE_CODEPOINTS = (0xd800, 0xdfff) +# this is the surrogate codepoints range (both ends inclusive) +# - they are not valid Rust characters +SURROGATE_CODEPOINTS_RANGE = (0xd800, 0xdfff) UnicodeData = namedtuple( - "UnicodeData", ("canon_decomp", "compat_decomp", "gencats", "combines", - "to_upper", "to_lower", "to_title", ) + "UnicodeData", ( + # conversions: + "to_upper", "to_lower", "to_title", + + # decompositions: canonical decompositions, compatibility decomp + "canon_decomp", "compat_decomp", + + # grouped: general categories and combining characters + "general_categories", "combines", + ) ) UnicodeVersion = namedtuple( @@ -91,14 +118,19 @@ UnicodeVersion = namedtuple( def fetch_files(version=None): + # type: (str) -> UnicodeVersion """ - Fetch all the Unicode files from unicode.org + Fetch all the Unicode files from unicode.org. + + This will use cached files (stored in FETCH_DIR) if they exist, + creating them if they don't. In any case, the Unicode version + is always returned. :param version: The desired Unicode version, as string. - (If None, defaults to latest final release available). - :return: The version downloaded (UnicodeVersion object). + (If None, defaults to latest final release available, + querying the unicode.org service). """ - have_version = should_skip_fetch(version) + have_version = check_stored_version(version) if have_version: return have_version @@ -114,22 +146,26 @@ def fetch_files(version=None): print("Fetching: {}".format(readme_url)) readme_content = subprocess.check_output(("curl", readme_url)) - unicode_version = parse_unicode_version( + unicode_version = parse_readme_unicode_version( readme_content.decode("utf8") ) - download_dir = os.path.join(FETCH_DIR, unicode_version.as_str) + download_dir = get_unicode_dir(unicode_version) if not os.path.exists(download_dir): # for 2.7 compat, we don't use exist_ok=True os.makedirs(download_dir) for filename in UnicodeFiles.ALL_FILES: - file_path = os.path.join(download_dir, filename) + file_path = get_unicode_file_path(unicode_version, filename) + + if os.path.exists(file_path): + # assume file on the server didn't change if it's been saved before + continue if filename == UnicodeFiles.README: with open(file_path, "wb") as fd: fd.write(readme_content) - elif not os.path.exists(file_path): + else: url = get_fetch_url(filename) print("Fetching: {}".format(url)) subprocess.check_call(("curl", "-o", file_path, url)) @@ -137,10 +173,15 @@ def fetch_files(version=None): return unicode_version -def should_skip_fetch(version): +def check_stored_version(version): + # type: (Optional[str]) -> Optional[UnicodeVersion] + """ + Given desired Unicode version, return the version + if stored files are all present, and None otherwise. + """ if not version: # should always check latest version - return False + return None fetch_dir = os.path.join(FETCH_DIR, version) @@ -148,13 +189,17 @@ def should_skip_fetch(version): file_path = os.path.join(fetch_dir, filename) if not os.path.exists(file_path): - return False + return None with open(os.path.join(fetch_dir, UnicodeFiles.README)) as fd: - return parse_unicode_version(fd.read()) + return parse_readme_unicode_version(fd.read()) -def parse_unicode_version(readme_content): +def parse_readme_unicode_version(readme_content): + # type: (str) -> UnicodeVersion + """ + Parse the Unicode version contained in their ReadMe.txt file. + """ # "raw string" is necessary for \d not being treated as escape char # (for the sake of compat with future Python versions) # see: https://docs.python.org/3.6/whatsnew/3.6.html#deprecated-python-behavior @@ -164,45 +209,78 @@ def parse_unicode_version(readme_content): return UnicodeVersion(*map(int, groups), as_str=".".join(groups)) +def get_unicode_dir(unicode_version): + # type: (UnicodeVersion) -> str + """ + Indicate where the unicode data files should be stored. + + This returns a full, absolute path. + """ + return os.path.join(FETCH_DIR, unicode_version.as_str) + + def get_unicode_file_path(unicode_version, filename): - return os.path.join(FETCH_DIR, unicode_version.as_str, filename) + # type: (UnicodeVersion, str) -> str + """ + Indicate where the unicode data file should be stored. + """ + return os.path.join(get_unicode_dir(unicode_version), filename) def is_surrogate(n): - return SURROGATE_CODEPOINTS[0] <= n <= SURROGATE_CODEPOINTS[1] + # type: (int) -> bool + """ + Tell if given codepoint is a surrogate (not a valid Rust character). + """ + return SURROGATE_CODEPOINTS_RANGE[0] <= n <= SURROGATE_CODEPOINTS_RANGE[1] def load_unicode_data(file_path): - gencats = {} - to_lower = {} - to_upper = {} - to_title = {} - combines = {} - canon_decomp = {} - compat_decomp = {} + # type: (str) -> UnicodeData + """ + Load main unicode data. + """ + # conversions + to_lower = {} # type: Dict[int, Tuple[int, int, int]] + to_upper = {} # type: Dict[int, Tuple[int, int, int]] + to_title = {} # type: Dict[int, Tuple[int, int, int]] + + # decompositions + compat_decomp = {} # type: Dict[int, List[int]] + canon_decomp = {} # type: Dict[int, List[int]] + + # combining characters + # FIXME: combines are not used + combines = defaultdict(set) # type: Dict[str, Set[int]] + + # categories + general_categories = defaultdict(set) # type: Dict[str, Set[int]] + category_assigned_codepoints = set() # type: Set[int] + + all_codepoints = {} - udict = {} range_start = -1 + for line in fileinput.input(file_path): data = line.split(";") if len(data) != 15: continue - cp = int(data[0], 16) - if is_surrogate(cp): + codepoint = int(data[0], 16) + if is_surrogate(codepoint): continue if range_start >= 0: - for i in range(range_start, cp): - udict[i] = data + for i in range(range_start, codepoint): + all_codepoints[i] = data range_start = -1 if data[1].endswith(", First>"): - range_start = cp + range_start = codepoint continue - udict[cp] = data + all_codepoints[codepoint] = data - for code in udict: + for code, data in all_codepoints.items(): (code_org, name, gencat, combine, bidi, decomp, deci, digit, num, mirror, - old, iso, upcase, lowcase, titlecase) = udict[code] + old, iso, upcase, lowcase, titlecase) = data # generate char to char direct common and simple conversions # uppercase to lowercase @@ -218,46 +296,47 @@ def load_unicode_data(file_path): to_title[code] = (int(titlecase, 16), 0, 0) # store decomposition, if given - if decomp != "": + if decomp: + decompositions = decomp.split()[1:] + decomp_code_points = [int(i, 16) for i in decompositions] + if decomp.startswith("<"): - seq = [] - for i in decomp.split()[1:]: - seq.append(int(i, 16)) - compat_decomp[code] = seq + # compatibility decomposition + compat_decomp[code] = decomp_code_points else: - seq = [] - for i in decomp.split(): - seq.append(int(i, 16)) - canon_decomp[code] = seq + # canonical decomposition + canon_decomp[code] = decomp_code_points # place letter in categories as appropriate - for cat in [gencat, "Assigned"] + EXPANDED_CATEGORIES.get(gencat, []): - if cat not in gencats: - gencats[cat] = [] - gencats[cat].append(code) + for cat in itertools.chain((gencat, ), EXPANDED_CATEGORIES.get(gencat, [])): + general_categories[cat].add(code) + category_assigned_codepoints.add(code) # record combining class, if any if combine != "0": - if combine not in combines: - combines[combine] = [] - combines[combine].append(code) + combines[combine].add(code) # generate Not_Assigned from Assigned - gencats["Cn"] = gen_unassigned(gencats["Assigned"]) - # Assigned is not a real category - del(gencats["Assigned"]) - # Other contains Not_Assigned - gencats["C"].extend(gencats["Cn"]) - gencats = group_cats(gencats) - combines = to_combines(group_cats(combines)) + general_categories["Cn"] = get_unassigned_codepoints(category_assigned_codepoints) + # Other contains Not_Assigned + general_categories["C"].update(general_categories["Cn"]) + + grouped_categories = group_categories(general_categories) + + # FIXME: combines are not used return UnicodeData( - canon_decomp, compat_decomp, gencats, combines, to_upper, - to_lower, to_title, + to_lower=to_lower, to_upper=to_upper, to_title=to_title, + compat_decomp=compat_decomp, canon_decomp=canon_decomp, + general_categories=grouped_categories, combines=combines, ) def load_special_casing(file_path, unicode_data): + # type: (str, UnicodeData) -> None + """ + Load special casing data and enrich given unicode data. + """ for line in fileinput.input(file_path): data = line.split("#")[0].split(";") if len(data) == 5: @@ -277,258 +356,395 @@ def load_special_casing(file_path, unicode_data): (unicode_data.to_upper, upper), (unicode_data.to_title, title)): if values != code: - values = [int(i, 16) for i in values.split()] - for _ in range(len(values), 3): - values.append(0) - assert len(values) == 3 - map_[key] = values + split = values.split() + + codepoints = list(itertools.chain( + (int(i, 16) for i in split), + (0 for _ in range(len(split), 3)) + )) + + assert len(codepoints) == 3 + map_[key] = codepoints -def group_cats(cats): - cats_out = {} - for cat in cats: - cats_out[cat] = group_cat(cats[cat]) - return cats_out +def group_categories(mapping): + # type: (Dict[Any, Iterable[int]]) -> Dict[str, List[Tuple[int, int]]] + """ + Group codepoints mapped in "categories". + """ + return {category: group_codepoints(codepoints) + for category, codepoints in mapping.items()} -def group_cat(cat): - cat_out = [] - letters = sorted(set(cat)) - cur_start = letters.pop(0) - cur_end = cur_start - for letter in letters: - assert letter > cur_end, \ - "cur_end: %s, letter: %s" % (hex(cur_end), hex(letter)) - if letter == cur_end + 1: - cur_end = letter - else: - cat_out.append((cur_start, cur_end)) - cur_start = cur_end = letter - cat_out.append((cur_start, cur_end)) - return cat_out +def group_codepoints(codepoints): + # type: (Iterable[int]) -> List[Tuple[int, int]] + """ + Group integral values into continuous, disjoint value ranges. + + Performs value deduplication. + + :return: sorted list of pairs denoting start and end of codepoint + group values, both ends inclusive. + + >>> group_codepoints([1, 2, 10, 11, 12, 3, 4]) + [(1, 4), (10, 12)] + >>> group_codepoints([1]) + [(1, 1)] + >>> group_codepoints([1, 5, 6]) + [(1, 1), (5, 6)] + >>> group_codepoints([]) + [] + """ + sorted_codes = sorted(set(codepoints)) + result = [] # type: List[Tuple[int, int]] + + if not sorted_codes: + return result + + next_codes = sorted_codes[1:] + start_code = sorted_codes[0] + + for code, next_code in zip_longest(sorted_codes, next_codes, fillvalue=None): + if next_code is None or next_code - code != 1: + result.append((start_code, code)) + start_code = next_code + + return result -def ungroup_cat(cat): - cat_out = [] - for (lo, hi) in cat: - while lo <= hi: - cat_out.append(lo) - lo += 1 - return cat_out +def ungroup_codepoints(codepoint_pairs): + # type: (Iterable[Tuple[int, int]]) -> List[int] + """ + The inverse of group_codepoints -- produce a flat list of values + from value range pairs. + + >>> ungroup_codepoints([(1, 4), (10, 12)]) + [1, 2, 3, 4, 10, 11, 12] + >>> ungroup_codepoints([(1, 1), (5, 6)]) + [1, 5, 6] + >>> ungroup_codepoints(group_codepoints([1, 2, 7, 8])) + [1, 2, 7, 8] + >>> ungroup_codepoints([]) + [] + """ + return list(itertools.chain.from_iterable( + range(lo, hi + 1) for lo, hi in codepoint_pairs + )) -def gen_unassigned(assigned): - assigned = set(assigned) - return ([i for i in range(0, 0xd800) if i not in assigned] + - [i for i in range(0xe000, 0x110000) if i not in assigned]) +def get_unassigned_codepoints(assigned_codepoints): + # type: (Set[int]) -> Set[int] + """ + Given a set of "assigned" codepoints, return a set + of these that are not in assigned and not surrogate. + """ + return {i for i in range(0, 0x110000) + if i not in assigned_codepoints and not is_surrogate(i)} -def to_combines(combs): - combs_out = [] - for comb in combs: - for (lo, hi) in combs[comb]: - combs_out.append((lo, hi, comb)) - combs_out.sort(key=lambda c: c[0]) - return combs_out +def generate_table_lines(items, indent, wrap=98): + # type: (Iterable[str], int, int) -> Iterator[str] + """ + Given table items, generate wrapped lines of text with comma-separated items. + This is a generator function. -def format_table_content(f, content, indent): + :param wrap: soft wrap limit (characters per line), integer. + """ line = " " * indent first = True - for chunk in content.split(","): - if len(line) + len(chunk) < 98: + for item in items: + if len(line) + len(item) < wrap: if first: - line += chunk + line += item else: - line += ", " + chunk + line += ", " + item first = False else: - f.write(line + ",\n") - line = " " * indent + chunk - f.write(line) + yield line + ",\n" + line = " " * indent + item + + yield line -def load_properties(file_path, interestingprops): - props = {} - # "raw string" is necessary for \w not to be treated as escape char +def load_properties(file_path, interesting_props): + # type: (str, Iterable[str]) -> Dict[str, List[Tuple[int, int]]] + """ + Load properties data and return in grouped form. + """ + props = defaultdict(list) # type: Dict[str, List[Tuple[int, int]]] + # "raw string" is necessary for \. and \w not to be treated as escape chars # (for the sake of compat with future Python versions) # see: https://docs.python.org/3.6/whatsnew/3.6.html#deprecated-python-behavior re1 = re.compile(r"^ *([0-9A-F]+) *; *(\w+)") re2 = re.compile(r"^ *([0-9A-F]+)\.\.([0-9A-F]+) *; *(\w+)") for line in fileinput.input(file_path): - prop = None - d_lo = 0 - d_hi = 0 - m = re1.match(line) - if m: - d_lo = m.group(1) - d_hi = m.group(1) - prop = m.group(2) - else: - m = re2.match(line) - if m: - d_lo = m.group(1) - d_hi = m.group(2) - prop = m.group(3) + match = re1.match(line) or re2.match(line) + if match: + groups = match.groups() + + if len(groups) == 2: + # re1 matched + d_lo, prop = groups + d_hi = d_lo else: - continue - if interestingprops and prop not in interestingprops: + d_lo, d_hi, prop = groups + else: continue - d_lo = int(d_lo, 16) - d_hi = int(d_hi, 16) - if prop not in props: - props[prop] = [] - props[prop].append((d_lo, d_hi)) + + if interesting_props and prop not in interesting_props: + continue + + lo_value = int(d_lo, 16) + hi_value = int(d_hi, 16) + + props[prop].append((lo_value, hi_value)) # optimize if possible for prop in props: - props[prop] = group_cat(ungroup_cat(props[prop])) + props[prop] = group_codepoints(ungroup_codepoints(props[prop])) return props def escape_char(c): - return "'\\u{%x}'" % c if c != 0 else "'\\0'" + # type: (int) -> str + r""" + Escape a codepoint for use as Rust char literal. + + Outputs are OK to use as Rust source code as char literals + and they also include necessary quotes. + + >>> escape_char(97) + "'\\u{61}'" + >>> escape_char(0) + "'\\0'" + """ + return r"'\u{%x}'" % c if c != 0 else r"'\0'" -def emit_table(f, name, t_data, t_type="&[(char, char)]", is_pub=True, - pfun=lambda x: "(%s,%s)" % (escape_char(x[0]), escape_char(x[1]))): +def format_char_pair(pair): + # type: (Tuple[int, int]) -> str + """ + Format a pair of two Rust chars. + """ + return "(%s,%s)" % (escape_char(pair[0]), escape_char(pair[1])) + + +def generate_table( + name, # type: str + items, # type: List[Tuple[int, int]] + decl_type="&[(char, char)]", # type: str + is_pub=True, # type: bool + format_item=format_char_pair, # type: Callable[[Tuple[int, int]], str] +): + # type: (...) -> Iterator[str] + """ + Generate a nicely formatted Rust constant "table" array. + + This generates actual Rust code. + """ pub_string = "" if is_pub: pub_string = "pub " - f.write(" %sconst %s: %s = &[\n" % (pub_string, name, t_type)) - data = "" + + yield " %sconst %s: %s = &[\n" % (pub_string, name, decl_type) + + data = [] first = True - for dat in t_data: + for item in items: if not first: - data += "," + data.append(",") first = False - data += pfun(dat) - format_table_content(f, data, 8) - f.write("\n ];\n\n") + data.extend(format_item(item)) + + for table_line in generate_table_lines("".join(data).split(","), 8): + yield table_line + + yield "\n ];\n\n" -def compute_trie(rawdata, chunksize): +def compute_trie(raw_data, chunk_size): + # type: (List[int], int) -> Tuple[List[int], List[int]] + """ + Compute postfix-compressed trie. + + See: bool_trie.rs for more details. + + >>> compute_trie([1, 2, 3, 1, 2, 3, 4, 5, 6], 3) + ([0, 0, 1], [1, 2, 3, 4, 5, 6]) + >>> compute_trie([1, 2, 3, 1, 2, 4, 4, 5, 6], 3) + ([0, 1, 2], [1, 2, 3, 1, 2, 4, 4, 5, 6]) + """ root = [] - childmap = {} + childmap = {} # type: Dict[Tuple[int, ...], int] child_data = [] - for i in range(len(rawdata) // chunksize): - data = rawdata[i * chunksize: (i + 1) * chunksize] - child = "|".join(map(str, data)) + + assert len(raw_data) % chunk_size == 0, "Chunks must be equally sized" + + for i in range(len(raw_data) // chunk_size): + data = raw_data[i * chunk_size : (i + 1) * chunk_size] + + # postfix compression of child nodes (data chunks) + # (identical child nodes are shared) + + # make a tuple out of the list so it's hashable + child = tuple(data) if child not in childmap: childmap[child] = len(childmap) child_data.extend(data) + root.append(childmap[child]) + return root, child_data -def emit_bool_trie(f, name, t_data, is_pub=True): +def generate_bool_trie(name, codepoint_ranges, is_pub=True): + # type: (str, List[Tuple[int, int]], bool) -> Iterator[str] + """ + Generate Rust code for BoolTrie struct. + + This yields string fragments that should be joined to produce + the final string. + + See: bool_trie.rs + """ chunk_size = 64 rawdata = [False] * 0x110000 - for (lo, hi) in t_data: + for (lo, hi) in codepoint_ranges: for cp in range(lo, hi + 1): rawdata[cp] = True - # convert to bitmap chunks of 64 bits each + # convert to bitmap chunks of chunk_size bits each chunks = [] for i in range(0x110000 // chunk_size): chunk = 0 - for j in range(64): - if rawdata[i * 64 + j]: + for j in range(chunk_size): + if rawdata[i * chunk_size + j]: chunk |= 1 << j chunks.append(chunk) pub_string = "" if is_pub: pub_string = "pub " - f.write(" %sconst %s: &super::BoolTrie = &super::BoolTrie {\n" % (pub_string, name)) - f.write(" r1: [\n") - data = ",".join("0x%016x" % chunk for chunk in chunks[0:0x800 // chunk_size]) - format_table_content(f, data, 12) - f.write("\n ],\n") + yield " %sconst %s: &super::BoolTrie = &super::BoolTrie {\n" % (pub_string, name) + yield " r1: [\n" + data = ("0x%016x" % chunk for chunk in chunks[:0x800 // chunk_size]) + for fragment in generate_table_lines(data, 12): + yield fragment + yield "\n ],\n" # 0x800..0x10000 trie (r2, r3) = compute_trie(chunks[0x800 // chunk_size : 0x10000 // chunk_size], 64 // chunk_size) - f.write(" r2: [\n") - data = ",".join(str(node) for node in r2) - format_table_content(f, data, 12) - f.write("\n ],\n") - f.write(" r3: &[\n") - data = ",".join("0x%016x" % chunk for chunk in r3) - format_table_content(f, data, 12) - f.write("\n ],\n") + yield " r2: [\n" + data = map(str, r2) + for fragment in generate_table_lines(data, 12): + yield fragment + yield "\n ],\n" + + yield " r3: &[\n" + data = ("0x%016x" % node for node in r3) + for fragment in generate_table_lines(data, 12): + yield fragment + yield "\n ],\n" # 0x10000..0x110000 trie (mid, r6) = compute_trie(chunks[0x10000 // chunk_size : 0x110000 // chunk_size], 64 // chunk_size) (r4, r5) = compute_trie(mid, 64) - f.write(" r4: [\n") - data = ",".join(str(node) for node in r4) - format_table_content(f, data, 12) - f.write("\n ],\n") - f.write(" r5: &[\n") - data = ",".join(str(node) for node in r5) - format_table_content(f, data, 12) - f.write("\n ],\n") - f.write(" r6: &[\n") - data = ",".join("0x%016x" % chunk for chunk in r6) - format_table_content(f, data, 12) - f.write("\n ],\n") - f.write(" };\n\n") + yield " r4: [\n" + data = map(str, r4) + for fragment in generate_table_lines(data, 12): + yield fragment + yield "\n ],\n" + + yield " r5: &[\n" + data = map(str, r5) + for fragment in generate_table_lines(data, 12): + yield fragment + yield "\n ],\n" + + yield " r6: &[\n" + data = ("0x%016x" % node for node in r6) + for fragment in generate_table_lines(data, 12): + yield fragment + yield "\n ],\n" + + yield " };\n\n" -def emit_small_bool_trie(f, name, t_data, is_pub=True): - last_chunk = max(hi // 64 for (lo, hi) in t_data) +def generate_small_bool_trie(name, codepoint_ranges, is_pub=True): + # type: (str, List[Tuple[int, int]], bool) -> Iterator[str] + """ + Generate Rust code for SmallBoolTrie struct. + + See: bool_trie.rs + """ + last_chunk = max(hi // 64 for (lo, hi) in codepoint_ranges) n_chunks = last_chunk + 1 chunks = [0] * n_chunks - for (lo, hi) in t_data: + for (lo, hi) in codepoint_ranges: for cp in range(lo, hi + 1): - if cp // 64 >= len(chunks): - print(cp, cp // 64, len(chunks), lo, hi) + assert cp // 64 < len(chunks) chunks[cp // 64] |= 1 << (cp & 63) pub_string = "" if is_pub: pub_string = "pub " - f.write(" %sconst %s: &super::SmallBoolTrie = &super::SmallBoolTrie {\n" - % (pub_string, name)) + + yield (" %sconst %s: &super::SmallBoolTrie = &super::SmallBoolTrie {\n" + % (pub_string, name)) (r1, r2) = compute_trie(chunks, 1) - f.write(" r1: &[\n") - data = ",".join(str(node) for node in r1) - format_table_content(f, data, 12) - f.write("\n ],\n") + yield " r1: &[\n" + data = (str(node) for node in r1) + for fragment in generate_table_lines(data, 12): + yield fragment + yield "\n ],\n" - f.write(" r2: &[\n") - data = ",".join("0x%016x" % node for node in r2) - format_table_content(f, data, 12) - f.write("\n ],\n") + yield " r2: &[\n" + data = ("0x%016x" % node for node in r2) + for fragment in generate_table_lines(data, 12): + yield fragment + yield "\n ],\n" - f.write(" };\n\n") + yield " };\n\n" -def emit_property_module(f, mod, tbl, emit): - f.write("pub mod %s {\n" % mod) - for cat in sorted(emit): - if cat in ["Cc", "White_Space", "Pattern_White_Space"]: - emit_small_bool_trie(f, "%s_table" % cat, tbl[cat]) - f.write(" pub fn %s(c: char) -> bool {\n" % cat) - f.write(" %s_table.lookup(c)\n" % cat) - f.write(" }\n\n") +def generate_property_module(mod, grouped_categories, category_subset): + # type: (str, Dict[str, List[Tuple[int, int]]], Iterable[str]) -> Iterator[str] + """ + Generate Rust code for module defining properties. + """ + + yield "pub mod %s {\n" % mod + for cat in sorted(category_subset): + if cat in ("Cc", "White_Space", "Pattern_White_Space"): + generator = generate_small_bool_trie("%s_table" % cat, grouped_categories[cat]) else: - emit_bool_trie(f, "%s_table" % cat, tbl[cat]) - f.write(" pub fn %s(c: char) -> bool {\n" % cat) - f.write(" %s_table.lookup(c)\n" % cat) - f.write(" }\n\n") - f.write("}\n\n") + generator = generate_bool_trie("%s_table" % cat, grouped_categories[cat]) + + for fragment in generator: + yield fragment + + yield " pub fn %s(c: char) -> bool {\n" % cat + yield " %s_table.lookup(c)\n" % cat + yield " }\n\n" + + yield "}\n\n" -def emit_conversions_module(f, unicode_data): - f.write("pub mod conversions {") - f.write(""" +def generate_conversions_module(unicode_data): + # type: (UnicodeData) -> Iterator[str] + """ + Generate Rust code for module defining conversions. + """ + + yield "pub mod conversions {" + yield """ pub fn to_lower(c: char) -> [char; 3] { match bsearch_case_table(c, to_lowercase_table) { None => [c, '\\0', '\\0'], @@ -545,46 +761,39 @@ def emit_conversions_module(f, unicode_data): fn bsearch_case_table(c: char, table: &[(char, [char; 3])]) -> Option { table.binary_search_by(|&(key, _)| key.cmp(&c)).ok() - } + }\n\n""" -""") - t_type = "&[(char, [char; 3])]" - pfun = lambda x: "(%s,[%s,%s,%s])" % ( - escape_char(x[0]), escape_char(x[1][0]), escape_char(x[1][1]), escape_char(x[1][2])) + decl_type = "&[(char, [char; 3])]" + format_conversion = lambda x: "({},[{},{},{}])".format(*( + escape_char(c) for c in (x[0], x[1][0], x[1][1], x[1][2]) + )) - emit_table(f, - name="to_lowercase_table", - t_data=sorted(unicode_data.to_lower.items(), key=operator.itemgetter(0)), - t_type=t_type, - is_pub=False, - pfun=pfun) + for fragment in generate_table( + name="to_lowercase_table", + items=sorted(unicode_data.to_lower.items(), key=lambda x: x[0]), + decl_type=decl_type, + is_pub=False, + format_item=format_conversion + ): + yield fragment - emit_table(f, - name="to_uppercase_table", - t_data=sorted(unicode_data.to_upper.items(), key=operator.itemgetter(0)), - t_type=t_type, - is_pub=False, - pfun=pfun) + for fragment in generate_table( + name="to_uppercase_table", + items=sorted(unicode_data.to_upper.items(), key=lambda x: x[0]), + decl_type=decl_type, + is_pub=False, + format_item=format_conversion + ): + yield fragment - f.write("}\n") - - -def emit_norm_module(f, unicode_data, norm_props): - canon_keys = sorted(unicode_data.canon_decomp.keys()) - - canon_comp = {} - comp_exclusions = norm_props["Full_Composition_Exclusion"] - for char in canon_keys: - if any(lo <= char <= hi for lo, hi in comp_exclusions): - continue - decomp = unicode_data.canon_decomp[char] - if len(decomp) == 2: - if decomp[0] not in canon_comp: - canon_comp[decomp[0]] = [] - canon_comp[decomp[0]].append((decomp[1], char)) + yield "}\n" def parse_args(): + # type: () -> argparse.Namespace + """ + Parse command line arguments. + """ parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("-v", "--version", default=None, type=str, help="Unicode version to use (if not specified," @@ -594,56 +803,63 @@ def parse_args(): def main(): + # type: () -> None + """ + Script entry point. + """ args = parse_args() unicode_version = fetch_files(args.version) print("Using Unicode version: {}".format(unicode_version.as_str)) + # all the writing happens entirely in memory, we only write to file + # once we have generated the file content (it's not very large, <1 MB) + buf = StringIO() + buf.write(PREAMBLE) + + unicode_version_notice = textwrap.dedent(""" + /// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of + /// `char` and `str` methods are based on. + #[unstable(feature = "unicode_version", issue = "49726")] + pub const UNICODE_VERSION: UnicodeVersion = UnicodeVersion {{ + major: {version.major}, + minor: {version.minor}, + micro: {version.micro}, + _priv: (), + }}; + """).format(version=unicode_version) + buf.write(unicode_version_notice) + + get_path = lambda f: get_unicode_file_path(unicode_version, f) + + unicode_data = load_unicode_data(get_path(UnicodeFiles.UNICODE_DATA)) + load_special_casing(get_path(UnicodeFiles.SPECIAL_CASING), unicode_data) + + want_derived = {"XID_Start", "XID_Continue", "Alphabetic", "Lowercase", "Uppercase", + "Cased", "Case_Ignorable", "Grapheme_Extend"} + derived = load_properties(get_path(UnicodeFiles.DERIVED_CORE_PROPERTIES), want_derived) + + props = load_properties(get_path(UnicodeFiles.PROPS), + {"White_Space", "Join_Control", "Noncharacter_Code_Point", + "Pattern_White_Space"}) + + # category tables + for (name, categories, category_subset) in ( + ("general_category", unicode_data.general_categories, ["N", "Cc"]), + ("derived_property", derived, want_derived), + ("property", props, ["White_Space", "Pattern_White_Space"]) + ): + for fragment in generate_property_module(name, categories, category_subset): + buf.write(fragment) + + for fragment in generate_conversions_module(unicode_data): + buf.write(fragment) + tables_rs_path = os.path.join(THIS_DIR, "tables.rs") # will overwrite the file if it exists - with open(tables_rs_path, "w") as rf: - rf.write(PREAMBLE) - - unicode_version_notice = textwrap.dedent(""" - /// The version of [Unicode](http://www.unicode.org/) that the Unicode parts of - /// `char` and `str` methods are based on. - #[unstable(feature = "unicode_version", issue = "49726")] - pub const UNICODE_VERSION: UnicodeVersion = UnicodeVersion {{ - major: {version.major}, - minor: {version.minor}, - micro: {version.micro}, - _priv: (), - }}; - """).format(version=unicode_version) - rf.write(unicode_version_notice) - - get_path = lambda f: get_unicode_file_path(unicode_version, f) - - unicode_data = load_unicode_data(get_path(UnicodeFiles.UNICODE_DATA)) - load_special_casing(get_path(UnicodeFiles.SPECIAL_CASING), unicode_data) - - want_derived = ["XID_Start", "XID_Continue", "Alphabetic", "Lowercase", "Uppercase", - "Cased", "Case_Ignorable", "Grapheme_Extend"] - derived = load_properties(get_path(UnicodeFiles.DERIVED_CORE_PROPERTIES), want_derived) - - # FIXME scripts not used? - scripts = load_properties(get_path(UnicodeFiles.SCRIPTS), []) - props = load_properties(get_path(UnicodeFiles.PROPS), - ["White_Space", "Join_Control", "Noncharacter_Code_Point", - "Pattern_White_Space"]) - norm_props = load_properties(get_path(UnicodeFiles.DERIVED_NORMALIZATION_PROPS), - ["Full_Composition_Exclusion"]) - - # category tables - for (name, cat, pfuns) in (("general_category", unicode_data.gencats, ["N", "Cc"]), - ("derived_property", derived, want_derived), - ("property", props, ["White_Space", "Pattern_White_Space"])): - emit_property_module(rf, name, cat, pfuns) - - # normalizations and conversions module - emit_norm_module(rf, unicode_data, norm_props) - emit_conversions_module(rf, unicode_data) + with open(tables_rs_path, "w") as fd: + fd.write(buf.getvalue()) print("Regenerated tables.rs.") From 02d815f3cec5fe7ccc36c3c985fff4279513135e Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:30:26 -0800 Subject: [PATCH 0024/3207] std::net: site-local ipv6 prefixes are global --- src/libstd/net/ip.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 7f9f3b91a600..14d677b89a0f 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -1104,12 +1104,20 @@ impl Ipv6Addr { /// /// - the loopback address /// - the link-local addresses - /// - the (deprecated) site-local addresses /// - unique local addresses /// - the unspecified address /// - the address range reserved for documentation /// + /// This method returns [`true`] for site-local addresses as per [RFC 4291 section 2.5.7] + /// + /// ```no_rust + /// The special behavior of [the site-local unicast] prefix defined in [RFC3513] must no longer + /// be supported in new implementations (i.e., new implementations must treat this prefix as + /// Global Unicast). + /// ``` + /// /// [`true`]: ../../std/primitive.bool.html + /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7 /// /// # Examples /// @@ -1126,9 +1134,11 @@ impl Ipv6Addr { /// ``` pub fn is_unicast_global(&self) -> bool { !self.is_multicast() - && !self.is_loopback() && !self.is_unicast_link_local() - && !self.is_unicast_site_local() && !self.is_unique_local() - && !self.is_unspecified() && !self.is_documentation() + && !self.is_loopback() + && !self.is_unicast_link_local() + && !self.is_unique_local() + && !self.is_unspecified() + && !self.is_documentation() } /// Returns the address's multicast scope if the address is multicast. From 5aea18411ed6baf471af0799f8926f105009dfcc Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:32:03 -0800 Subject: [PATCH 0025/3207] std::net: improve Ipv6Addr::is_unicast_site_local() doc - quote the RFC - add a link to the RFC - fix markdown --- src/libstd/net/ip.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 14d677b89a0f..f70e07049f27 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -1051,10 +1051,19 @@ impl Ipv6Addr { (self.segments()[0] & 0xffc0) == 0xfe80 } - /// Returns [`true`] if this is a deprecated unicast site-local address - /// (fec0::/10). + /// Returns [`true`] if this is a deprecated unicast site-local address (fec0::/10). The + /// unicast site-local address format is defined in [RFC 4291 section 2.5.7] as: + /// + /// ```no_rust + /// | 10 | + /// | bits | 54 bits | 64 bits | + /// +----------+-------------------------+----------------------------+ + /// |1111111011| subnet ID | interface ID | + /// +----------+-------------------------+----------------------------+ + /// ``` /// /// [`true`]: ../../std/primitive.bool.html + /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7 /// /// # Examples /// From 1f0aa4043b6051602f016b61a393ef5981b5b831 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:33:02 -0800 Subject: [PATCH 0026/3207] std::net: add Ipv6Addr::is_unicast_link_local_strict() RFC 4291 is a little unclear about what is a unicast link local address. According to section 2.4, the entire fe80::/10 range is reserved for these addresses, but section 2.5.3 defines a stricter format for such addresses. After a discussion[0] is has been decided to add a different method for each definition, so this commit: - renames is_unicast_link_local() into is_unicast_link_local_strict() - relaxed the check in is_unicast_link_local() [0]: https://github.com/rust-lang/rust/issues/27709#issuecomment-400370706 --- src/libstd/net/ip.rs | 104 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 97 insertions(+), 7 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index f70e07049f27..4dd5e2cafbf2 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -1027,12 +1027,22 @@ impl Ipv6Addr { (self.segments()[0] & 0xfe00) == 0xfc00 } - /// Returns [`true`] if the address is unicast and link-local (fe80::/10). + /// Returns [`true`] if the address is a unicast link-local address (`fe80::/64`). /// - /// This property is defined in [IETF RFC 4291]. + /// A common mis-conception is to think that "unicast link-local addresses start with + /// `fe80::`", but the [IETF RFC 4291] actually defines a stricter format for these addresses: /// - /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 - /// [`true`]: ../../std/primitive.bool.html + /// ```no_rust + /// | 10 | + /// | bits | 54 bits | 64 bits | + /// +----------+-------------------------+----------------------------+ + /// |1111111010| 0 | interface ID | + /// +----------+-------------------------+----------------------------+ + /// ``` + /// + /// This method validates the format defined in the RFC and won't recognize the following + /// addresses such as `fe80:0:0:1::` or `fe81::` as unicast link-local addresses for example. + /// If you need a less strict validation use [`is_unicast_link_local()`] instead. /// /// # Examples /// @@ -1042,11 +1052,91 @@ impl Ipv6Addr { /// use std::net::Ipv6Addr; /// /// fn main() { - /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_link_local(), - /// false); - /// assert_eq!(Ipv6Addr::new(0xfe8a, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true); + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0); + /// assert!(ip.is_unicast_link_local_strict()); + /// + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff); + /// assert!(ip.is_unicast_link_local_strict()); + /// + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0); + /// assert!(!ip.is_unicast_link_local_strict()); + /// assert!(ip.is_unicast_link_local()); + /// + /// let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0); + /// assert!(!ip.is_unicast_link_local_strict()); + /// assert!(ip.is_unicast_link_local()); /// } /// ``` + /// + /// # See also + /// + /// - [IETF RFC 4291 section 2.5.6] + /// - [RFC 4291 errata 4406] + /// + /// [IETF RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6 + /// [`true`]: ../../std/primitive.bool.html + /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406 + /// [`is_unicast_link_local()`](#method.is_unicast_link_local) + /// + pub fn is_unicast_link_local_strict(&self) -> bool { + (self.segments()[0] & 0xffff) == 0xfe80 + && (self.segments()[1] & 0xffff) == 0 + && (self.segments()[2] & 0xffff) == 0 + && (self.segments()[3] & 0xffff) == 0 + } + + /// Returns [`true`] if the address is a unicast link-local address (`fe80::/10`). + /// + /// This method returns [`true`] for addresses in the range reserved by [RFC 4291 section 2.4], + /// i.e. addresses with the following format: + /// + /// ```no_rust + /// | 10 | + /// | bits | 54 bits | 64 bits | + /// +----------+-------------------------+----------------------------+ + /// |1111111010| arbitratry value | interface ID | + /// +----------+-------------------------+----------------------------+ + /// ``` + /// + /// As a result, this method consider addresses such as `fe80:0:0:1::` or `fe81::` to be + /// unicast link-local addresses, whereas [`is_unicast_link_local_strict()`] does not. If you + /// need a strict validation fully compliant with the RFC, use + /// [`is_unicast_link_local_strict()`]. + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// + /// use std::net::Ipv6Addr; + /// + /// fn main() { + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0); + /// assert!(ip.is_unicast_link_local()); + /// + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff); + /// assert!(ip.is_unicast_link_local()); + /// + /// let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0); + /// assert!(ip.is_unicast_link_local()); + /// assert!(!ip.is_unicast_link_local_strict()); + /// + /// let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0); + /// assert!(ip.is_unicast_link_local()); + /// assert!(!ip.is_unicast_link_local_strict()); + /// } + /// ``` + /// + /// # See also + /// + /// - [IETF RFC 4291 section 2.4] + /// - [RFC 4291 errata 4406] + /// + /// [IETF RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4 + /// [`true`]: ../../std/primitive.bool.html + /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406 + /// [`is_unicast_link_local_strict()`](#method.is_unicast_link_local_strict) + /// pub fn is_unicast_link_local(&self) -> bool { (self.segments()[0] & 0xffc0) == 0xfe80 } From aea687c3148c7ae48833a0faef7e6ada24fce05c Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:34:04 -0800 Subject: [PATCH 0027/3207] std::net: fix doc markdown in Ipv6Addr::is_unique_local() --- src/libstd/net/ip.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 4dd5e2cafbf2..0fea70c6ed78 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -1003,7 +1003,7 @@ impl Ipv6Addr { } } - /// Returns [`true`] if this is a unique local address (fc00::/7). + /// Returns [`true`] if this is a unique local address (`fc00::/7`). /// /// This property is defined in [IETF RFC 4193]. /// From 8f679977e00dba29819aedbcfaf14927a4136430 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:36:23 -0800 Subject: [PATCH 0028/3207] std::net: add Ipv4Addr::is_reserved() --- src/libstd/net/ip.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 0fea70c6ed78..f94923d28d29 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -532,6 +532,34 @@ impl Ipv4Addr { !self.is_broadcast() && !self.is_documentation() && !self.is_unspecified() } + /// Returns [`true`] if this address is reserved by IANA for future use. [IETF RFC 1112] + /// defines the block of reserved addresses as `240.0.0.0/4`. This range normally includes the + /// broadcast address `255.255.255.255`, but this implementation explicitely excludes it, since + /// it is obviously not reserved for future use. + /// + /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112 + /// [`true`]: ../../std/primitive.bool.html + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// use std::net::Ipv4Addr; + /// + /// fn main() { + /// assert_eq!(Ipv4Addr::new(240, 0, 0, 0).is_reserved(), true); + /// assert_eq!(Ipv4Addr::new(255, 255, 255, 254).is_reserved(), true); + /// + /// assert_eq!(Ipv4Addr::new(239, 255, 255, 255).is_reserved(), false); + /// // The broadcast address is not considered as reserved for future use by this + /// // implementation + /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false); + /// } + /// ``` + pub fn is_reserved(&self) -> bool { + self.octets()[0] & 240 == 240 && !self.is_broadcast() + } + /// Returns [`true`] if this is a multicast address (224.0.0.0/4). /// /// Multicast addresses have a most significant octet between 224 and 239, From de3cf0d5eb30be7b2a297151af1528314664bd69 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:37:21 -0800 Subject: [PATCH 0029/3207] std::net: add Ipv4Addr::is_benchmarking() --- src/libstd/net/ip.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index f94923d28d29..6e9c6588a1df 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -532,6 +532,31 @@ impl Ipv4Addr { !self.is_broadcast() && !self.is_documentation() && !self.is_unspecified() } + /// Returns [`true`] if this address part of the `198.18.0.0/15` range, which is reserved for + /// network devices benchmarking. This range is defined in [IETF RFC 2544] as `192.18.0.0` + /// through `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`. + /// + /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112 + /// [errate 423]: https://www.rfc-editor.org/errata/eid423 + /// [`true`]: ../../std/primitive.bool.html + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// use std::net::Ipv4Addr; + /// + /// fn main() { + /// assert_eq!(Ipv4Addr::new(198, 17, 255, 255).is_benchmarking(), false); + /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_benchmarking(), true); + /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true); + /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false); + /// } + /// ``` + pub fn is_benchmarking(&self) -> bool { + self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18 + } + /// Returns [`true`] if this address is reserved by IANA for future use. [IETF RFC 1112] /// defines the block of reserved addresses as `240.0.0.0/4`. This range normally includes the /// broadcast address `255.255.255.255`, but this implementation explicitely excludes it, since From f87b96773b0fbbfa24781c58af7a73b816c7d658 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:37:58 -0800 Subject: [PATCH 0030/3207] std::net: add Ipv4Addr::is_ietf_protocol_assignment() --- src/libstd/net/ip.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 6e9c6588a1df..998642f8346e 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -532,6 +532,40 @@ impl Ipv4Addr { !self.is_broadcast() && !self.is_documentation() && !self.is_unspecified() } + /// Returns [`true`] if this address is part of `192.0.0.0/24`, which is reserved to + /// IANA for IETF protocol assignments, as documented in [IETF RFC 6890]. + /// + /// Note that parts of this block are in use: + /// + /// - `192.0.0.8/32` is the "IPv4 dummy address" (see [IETF RFC 7600]) + /// - `192.0.0.9/32` is the "Port Control Protocol Anycast" (see [IETF RFC 7723]) + /// - `192.0.0.10/32` is used for NAT traversal (see [IETF RFC 8155]) + /// + /// [IETF RFC 6890]: https://tools.ietf.org/html/rfc6890 + /// [IETF RFC 7600]: https://tools.ietf.org/html/rfc7600 + /// [IETF RFC 7723]: https://tools.ietf.org/html/rfc7723 + /// [IETF RFC 8155]: https://tools.ietf.org/html/rfc8155 + /// [`true`]: ../../std/primitive.bool.html + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// use std::net::Ipv4Addr; + /// + /// fn main() { + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_ietf_protocol_assignment(), true); + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 8).is_ietf_protocol_assignment(), true); + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 9).is_ietf_protocol_assignment(), true); + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_ietf_protocol_assignment(), true); + /// assert_eq!(Ipv4Addr::new(192, 0, 1, 0).is_ietf_protocol_assignment(), false); + /// assert_eq!(Ipv4Addr::new(191, 255, 255, 255).is_ietf_protocol_assignment(), false); + /// } + /// ``` + pub fn is_ietf_protocol_assignment(&self) -> bool { + self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0 + } + /// Returns [`true`] if this address part of the `198.18.0.0/15` range, which is reserved for /// network devices benchmarking. This range is defined in [IETF RFC 2544] as `192.18.0.0` /// through `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`. From 67291cc9711eb4ceb717dc0860aba499bcdf55f7 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:39:05 -0800 Subject: [PATCH 0031/3207] std::net: add Ipv4Addr::is_shared() --- src/libstd/net/ip.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 998642f8346e..fd6b00619909 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -532,6 +532,28 @@ impl Ipv4Addr { !self.is_broadcast() && !self.is_documentation() && !self.is_unspecified() } + /// Returns [`true`] if this address is part of the Shared Address Space defined in + /// [IETF RFC 6598] (`100.64.0.0/10`). + /// + /// [IETF RFC 6598]: https://tools.ietf.org/html/rfc6598 + /// [`true`]: ../../std/primitive.bool.html + /// + /// # Examples + /// + /// ``` + /// #![feature(ip)] + /// use std::net::Ipv4Addr; + /// + /// fn main() { + /// assert_eq!(Ipv4Addr::new(100, 64, 0, 0).is_shared(), true); + /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true); + /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false); + /// } + /// ``` + pub fn is_shared(&self) -> bool { + self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000) + } + /// Returns [`true`] if this address is part of `192.0.0.0/24`, which is reserved to /// IANA for IETF protocol assignments, as documented in [IETF RFC 6890]. /// From 9f6a747b32d55d0219a909eb29c136efbb98c473 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 09:40:21 -0800 Subject: [PATCH 0032/3207] std::net: fix Ipv4Addr::is_global() As per @therealbstern's comment[0]: The implementation of Ipv4::is_global is not complete, according to the IANA IPv4 Special-Purpose Address Registry. - It compares the address to 0.0.0.0, but anything in 0.0.0.0/8 should not be considered global. - 0/8 is not global and is currently forbidden because some systems used to treat it as the local network. - The implementation of Ipv4::is_unspecified is correct. 0.0.0.0 is the unspecified address. - It does not examine 100.64.0.0/10, which is "Shared Address Space" and not global. - Ditto 192.0.0.0/24 (IETF Protocol Assignments), except for 192.0.0.9/32 and 192.0.0.10/32, which are carved out as globally reachable. - 198.18.0.0/15 is for "Benchmarking" and should not be globally reachable. - 240.0.0.0/4 is reserved and not currently reachable --- src/libstd/net/ip.rs | 72 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 8 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index fd6b00619909..8d00bee0e366 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -502,12 +502,19 @@ impl Ipv4Addr { /// /// The following return false: /// - /// - private address (10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16) - /// - the loopback address (127.0.0.0/8) - /// - the link-local address (169.254.0.0/16) - /// - the broadcast address (255.255.255.255/32) - /// - test addresses used for documentation (192.0.2.0/24, 198.51.100.0/24 and 203.0.113.0/24) - /// - the unspecified address (0.0.0.0) + /// - private addresses (see [`is_private()`](#method.is_private)) + /// - the loopback address (see [`is_loopback()`](#method.is_loopback)) + /// - the link-local address (see [`is_link_local()`](#method.is_link_local)) + /// - the broadcast address (see [`is_broadcast()`](#method.is_broadcast)) + /// - addresses used for documentation (see [`is_documentation()`](#method.is_documentation)) + /// - the unspecified address (see [`is_unspecified()`](#method.is_unspecified)), and the whole + /// 0.0.0.0/8 block + /// - addresses reserved for future protocols (see + /// [`is_ietf_protocol_assignment()`](#method.is_ietf_protocol_assignment), except + /// `192.0.0.9/32` and `192.0.0.10/32` which are globally routable + /// - addresses reserved for future use (see [`is_reserved()`](#method.is_reserved()) + /// - addresses reserved for networking devices benchmarking (see + /// [`is_benchmarking`](#method.is_benchmarking)) /// /// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml /// [`true`]: ../../std/primitive.bool.html @@ -520,16 +527,65 @@ impl Ipv4Addr { /// use std::net::Ipv4Addr; /// /// fn main() { + /// // private addresses are not global /// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false); /// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false); /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false); + /// + /// // the 0.0.0.0/8 block is not global + /// assert_eq!(Ipv4Addr::new(0, 1, 2, 3).is_global(), false); + /// // in particular, the unspecified address is not global /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_global(), false); + /// + /// // the loopback address is not global + /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_global(), false); + /// + /// // link local addresses are not global + /// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false); + /// + /// // the broadcast address is not global + /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_global(), false); + /// + /// // the broadcast address is not global + /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false); + /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false); + /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false); + /// + /// // shared addresses are not global + /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false); + /// + /// // addresses reserved for protocol assignment are not global + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_global(), false); + /// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_global(), false); + /// + /// // addresses reserved for future use are not global + /// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false); + /// + /// // addresses reserved for network devices benchmarking are not global + /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false); + /// + /// // All the other addresses are global + /// assert_eq!(Ipv4Addr::new(1, 1, 1, 1).is_global(), true); /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true); /// } /// ``` pub fn is_global(&self) -> bool { - !self.is_private() && !self.is_loopback() && !self.is_link_local() && - !self.is_broadcast() && !self.is_documentation() && !self.is_unspecified() + // check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two + // globally routable addresses in the 192.0.0.0/24 range. + if u32::from(*self) == 0xc0000009 || u32::from(*self) == 0xc000000a { + return true; + } + !self.is_private() + && !self.is_loopback() + && !self.is_link_local() + && !self.is_broadcast() + && !self.is_documentation() + && !self.is_shared() + && !self.is_ietf_protocol_assignment() + && !self.is_reserved() + && !self.is_benchmarking() + // Make sure the address is not in 0.0.0.0/8 + && self.octets()[0] != 0 } /// Returns [`true`] if this address is part of the Shared Address Space defined in From 810632000972343fefd0ec37b12f05a665fd12c6 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 16:31:14 -0800 Subject: [PATCH 0033/3207] std::net: fix documentation markdown --- src/libstd/net/ip.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 8d00bee0e366..d8c5f27a9981 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -512,7 +512,7 @@ impl Ipv4Addr { /// - addresses reserved for future protocols (see /// [`is_ietf_protocol_assignment()`](#method.is_ietf_protocol_assignment), except /// `192.0.0.9/32` and `192.0.0.10/32` which are globally routable - /// - addresses reserved for future use (see [`is_reserved()`](#method.is_reserved()) + /// - addresses reserved for future use (see [`is_reserved()`](#method.is_reserved) /// - addresses reserved for networking devices benchmarking (see /// [`is_benchmarking`](#method.is_benchmarking)) /// @@ -1237,11 +1237,13 @@ impl Ipv6Addr { /// /// - [IETF RFC 4291 section 2.5.6] /// - [RFC 4291 errata 4406] + /// - [`is_unicast_link_local()`] /// + /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291 /// [IETF RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6 /// [`true`]: ../../std/primitive.bool.html /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406 - /// [`is_unicast_link_local()`](#method.is_unicast_link_local) + /// [`is_unicast_link_local()`]: ../../std/net/struct.Ipv6Addr.html#method.is_unicast_link_local /// pub fn is_unicast_link_local_strict(&self) -> bool { (self.segments()[0] & 0xffff) == 0xfe80 @@ -1300,7 +1302,7 @@ impl Ipv6Addr { /// [IETF RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4 /// [`true`]: ../../std/primitive.bool.html /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406 - /// [`is_unicast_link_local_strict()`](#method.is_unicast_link_local_strict) + /// [`is_unicast_link_local_strict()`]: ../../std/net/struct.Ipv6Addr.html#method.is_unicast_link_local_strict /// pub fn is_unicast_link_local(&self) -> bool { (self.segments()[0] & 0xffc0) == 0xfe80 From c34bcc658b46fa0368c2faa75c0fa8767afab920 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 19 Nov 2018 16:31:14 -0800 Subject: [PATCH 0034/3207] std::net: use macros to test ip properties --- src/libstd/net/ip.rs | 522 +++++++++++++++++++++++++++++++------------ 1 file changed, 380 insertions(+), 142 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index d8c5f27a9981..17200d7b94a4 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -1786,8 +1786,8 @@ impl From<[u16; 8]> for IpAddr { #[cfg(all(test, not(target_os = "emscripten")))] mod tests { use crate::net::*; - use crate::net::Ipv6MulticastScope::*; use crate::net::test::{tsa, sa6, sa4}; + use crate::str::FromStr; #[test] fn test_from_str_ipv4() { @@ -1951,164 +1951,402 @@ mod tests { #[test] fn ip_properties() { - fn check4(octets: &[u8; 4], unspec: bool, loopback: bool, - global: bool, multicast: bool, documentation: bool) { - let ip = IpAddr::V4(Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3])); - assert_eq!(ip.is_unspecified(), unspec); - assert_eq!(ip.is_loopback(), loopback); - assert_eq!(ip.is_global(), global); - assert_eq!(ip.is_multicast(), multicast); - assert_eq!(ip.is_documentation(), documentation); + macro_rules! ip { + ($s:expr) => { + IpAddr::from_str($s).unwrap() + } } - fn check6(str_addr: &str, unspec: bool, loopback: bool, - global: bool, u_doc: bool, mcast: bool) { - let ip = IpAddr::V6(str_addr.parse().unwrap()); - assert_eq!(ip.is_unspecified(), unspec); - assert_eq!(ip.is_loopback(), loopback); - assert_eq!(ip.is_global(), global); - assert_eq!(ip.is_documentation(), u_doc); - assert_eq!(ip.is_multicast(), mcast); + macro_rules! check { + ($s:expr) => { + check!($s, 0); + }; + + ($s:expr, $mask:expr) => {{ + let unspec: u8 = 1 << 0; + let loopback: u8 = 1 << 1; + let global: u8 = 1 << 2; + let multicast: u8 = 1 << 3; + let doc: u8 = 1 << 4; + + if ($mask & unspec) == unspec { + assert!(ip!($s).is_unspecified()); + } else { + assert!(!ip!($s).is_unspecified()); + } + + if ($mask & loopback) == loopback { + assert!(ip!($s).is_loopback()); + } else { + assert!(!ip!($s).is_loopback()); + } + + if ($mask & global) == global { + assert!(ip!($s).is_global()); + } else { + assert!(!ip!($s).is_global()); + } + + if ($mask & multicast) == multicast { + assert!(ip!($s).is_multicast()); + } else { + assert!(!ip!($s).is_multicast()); + } + + if ($mask & doc) == doc { + assert!(ip!($s).is_documentation()); + } else { + assert!(!ip!($s).is_documentation()); + } + }} } - // address unspec loopbk global multicast doc - check4(&[0, 0, 0, 0], true, false, false, false, false); - check4(&[0, 0, 0, 1], false, false, true, false, false); - check4(&[0, 1, 0, 0], false, false, true, false, false); - check4(&[10, 9, 8, 7], false, false, false, false, false); - check4(&[127, 1, 2, 3], false, true, false, false, false); - check4(&[172, 31, 254, 253], false, false, false, false, false); - check4(&[169, 254, 253, 242], false, false, false, false, false); - check4(&[192, 0, 2, 183], false, false, false, false, true); - check4(&[192, 1, 2, 183], false, false, true, false, false); - check4(&[192, 168, 254, 253], false, false, false, false, false); - check4(&[198, 51, 100, 0], false, false, false, false, true); - check4(&[203, 0, 113, 0], false, false, false, false, true); - check4(&[203, 2, 113, 0], false, false, true, false, false); - check4(&[224, 0, 0, 0], false, false, true, true, false); - check4(&[239, 255, 255, 255], false, false, true, true, false); - check4(&[255, 255, 255, 255], false, false, false, false, false); + let unspec: u8 = 1 << 0; + let loopback: u8 = 1 << 1; + let global: u8 = 1 << 2; + let multicast: u8 = 1 << 3; + let doc: u8 = 1 << 4; - // address unspec loopbk global doc mcast - check6("::", true, false, false, false, false); - check6("::1", false, true, false, false, false); - check6("::0.0.0.2", false, false, true, false, false); - check6("1::", false, false, true, false, false); - check6("fc00::", false, false, false, false, false); - check6("fdff:ffff::", false, false, false, false, false); - check6("fe80:ffff::", false, false, false, false, false); - check6("febf:ffff::", false, false, false, false, false); - check6("fec0::", false, false, false, false, false); - check6("ff01::", false, false, false, false, true); - check6("ff02::", false, false, false, false, true); - check6("ff03::", false, false, false, false, true); - check6("ff04::", false, false, false, false, true); - check6("ff05::", false, false, false, false, true); - check6("ff08::", false, false, false, false, true); - check6("ff0e::", false, false, true, false, true); - check6("2001:db8:85a3::8a2e:370:7334", false, false, false, true, false); - check6("102:304:506:708:90a:b0c:d0e:f10", false, false, true, false, false); + check!("0.0.0.0", unspec); + check!("0.0.0.1", global); + check!("0.1.0.0", global); + check!("10.9.8.7"); + check!("127.1.2.3", loopback); + check!("172.31.254.253"); + check!("169.254.253.242"); + check!("192.0.2.183", doc); + check!("192.1.2.183", global); + check!("192.168.254.253"); + check!("198.51.100.0", doc); + check!("203.0.113.0", doc); + check!("203.2.113.0", global); + check!("224.0.0.0", global|multicast); + check!("239.255.255.255", global|multicast); + check!("255.255.255.255"); + + check!("::", unspec); + check!("::1", loopback); + check!("::0.0.0.2", global); + check!("1::", global); + check!("fc00::"); + check!("fdff:ffff::"); + check!("fe80:ffff::"); + check!("febf:ffff::"); + check!("fec0::"); + check!("ff01::", multicast); + check!("ff02::", multicast); + check!("ff03::", multicast); + check!("ff04::", multicast); + check!("ff05::", multicast); + check!("ff08::", multicast); + check!("ff0e::", global|multicast); + check!("2001:db8:85a3::8a2e:370:7334", doc); + check!("102:304:506:708:90a:b0c:d0e:f10", global); } #[test] fn ipv4_properties() { - fn check(octets: &[u8; 4], unspec: bool, loopback: bool, - private: bool, link_local: bool, global: bool, - multicast: bool, broadcast: bool, documentation: bool) { - let ip = Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3]); - assert_eq!(octets, &ip.octets()); - - assert_eq!(ip.is_unspecified(), unspec); - assert_eq!(ip.is_loopback(), loopback); - assert_eq!(ip.is_private(), private); - assert_eq!(ip.is_link_local(), link_local); - assert_eq!(ip.is_global(), global); - assert_eq!(ip.is_multicast(), multicast); - assert_eq!(ip.is_broadcast(), broadcast); - assert_eq!(ip.is_documentation(), documentation); + macro_rules! ip { + ($s:expr) => { + Ipv4Addr::from_str($s).unwrap() + } } - // address unspec loopbk privt linloc global multicast brdcast doc - check(&[0, 0, 0, 0], true, false, false, false, false, false, false, false); - check(&[0, 0, 0, 1], false, false, false, false, true, false, false, false); - check(&[0, 1, 0, 0], false, false, false, false, true, false, false, false); - check(&[10, 9, 8, 7], false, false, true, false, false, false, false, false); - check(&[127, 1, 2, 3], false, true, false, false, false, false, false, false); - check(&[172, 31, 254, 253], false, false, true, false, false, false, false, false); - check(&[169, 254, 253, 242], false, false, false, true, false, false, false, false); - check(&[192, 0, 2, 183], false, false, false, false, false, false, false, true); - check(&[192, 1, 2, 183], false, false, false, false, true, false, false, false); - check(&[192, 168, 254, 253], false, false, true, false, false, false, false, false); - check(&[198, 51, 100, 0], false, false, false, false, false, false, false, true); - check(&[203, 0, 113, 0], false, false, false, false, false, false, false, true); - check(&[203, 2, 113, 0], false, false, false, false, true, false, false, false); - check(&[224, 0, 0, 0], false, false, false, false, true, true, false, false); - check(&[239, 255, 255, 255], false, false, false, false, true, true, false, false); - check(&[255, 255, 255, 255], false, false, false, false, false, false, true, false); + macro_rules! check { + ($s:expr) => { + check!($s, 0); + }; + + ($s:expr, $mask:expr) => {{ + let unspec: u8 = 1 << 0; + let loopback: u8 = 1 << 1; + let private: u8 = 1 << 2; + let link_local: u8 = 1 << 3; + let global: u8 = 1 << 4; + let multicast: u8 = 1 << 5; + let broadcast: u8 = 1 << 6; + let documentation: u8 = 1 << 7; + + if ($mask & unspec) == unspec { + assert!(ip!($s).is_unspecified()); + } else { + assert!(!ip!($s).is_unspecified()); + } + + if ($mask & loopback) == loopback { + assert!(ip!($s).is_loopback()); + } else { + assert!(!ip!($s).is_loopback()); + } + + if ($mask & private) == private { + assert!(ip!($s).is_private()); + } else { + assert!(!ip!($s).is_private()); + } + + if ($mask & link_local) == link_local { + assert!(ip!($s).is_link_local()); + } else { + assert!(!ip!($s).is_link_local()); + } + + if ($mask & global) == global { + assert!(ip!($s).is_global()); + } else { + assert!(!ip!($s).is_global()); + } + + if ($mask & multicast) == multicast { + assert!(ip!($s).is_multicast()); + } else { + assert!(!ip!($s).is_multicast()); + } + + if ($mask & broadcast) == broadcast { + assert!(ip!($s).is_broadcast()); + } else { + assert!(!ip!($s).is_broadcast()); + } + + if ($mask & documentation) == documentation { + assert!(ip!($s).is_documentation()); + } else { + assert!(!ip!($s).is_documentation()); + } + }} + } + + let unspec: u8 = 1 << 0; + let loopback: u8 = 1 << 1; + let private: u8 = 1 << 2; + let link_local: u8 = 1 << 3; + let global: u8 = 1 << 4; + let multicast: u8 = 1 << 5; + let broadcast: u8 = 1 << 6; + let documentation: u8 = 1 << 7; + + check!("0.0.0.0", unspec); + check!("0.0.0.1", global); + check!("0.1.0.0", global); + check!("10.9.8.7", private); + check!("127.1.2.3", loopback); + check!("172.31.254.253", private); + check!("169.254.253.242", link_local); + check!("192.0.2.183", documentation); + check!("192.1.2.183", global); + check!("192.168.254.253", private); + check!("198.51.100.0", documentation); + check!("203.0.113.0", documentation); + check!("203.2.113.0", global); + check!("224.0.0.0", global|multicast); + check!("239.255.255.255", global|multicast); + check!("255.255.255.255", broadcast); } #[test] fn ipv6_properties() { - fn check(str_addr: &str, octets: &[u8; 16], unspec: bool, loopback: bool, - unique_local: bool, global: bool, - u_link_local: bool, u_site_local: bool, u_global: bool, u_doc: bool, - m_scope: Option) { - let ip: Ipv6Addr = str_addr.parse().unwrap(); - assert_eq!(str_addr, ip.to_string()); - assert_eq!(&ip.octets(), octets); - assert_eq!(Ipv6Addr::from(*octets), ip); - - assert_eq!(ip.is_unspecified(), unspec); - assert_eq!(ip.is_loopback(), loopback); - assert_eq!(ip.is_unique_local(), unique_local); - assert_eq!(ip.is_global(), global); - assert_eq!(ip.is_unicast_link_local(), u_link_local); - assert_eq!(ip.is_unicast_site_local(), u_site_local); - assert_eq!(ip.is_unicast_global(), u_global); - assert_eq!(ip.is_documentation(), u_doc); - assert_eq!(ip.multicast_scope(), m_scope); - assert_eq!(ip.is_multicast(), m_scope.is_some()); + macro_rules! ip { + ($s:expr) => { + Ipv6Addr::from_str($s).unwrap() + } } - // unspec loopbk uniqlo global unill unisl uniglo doc mscope - check("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - true, false, false, false, false, false, false, false, None); - check("::1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], - false, true, false, false, false, false, false, false, None); - check("::0.0.0.2", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], - false, false, false, true, false, false, true, false, None); - check("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, false, true, false, false, true, false, None); - check("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, true, false, false, false, false, false, None); - check("fdff:ffff::", &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, true, false, false, false, false, false, None); - check("fe80:ffff::", &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, false, false, true, false, false, false, None); - check("febf:ffff::", &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, false, false, true, false, false, false, None); - check("fec0::", &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, false, false, false, true, false, false, None); - check("ff01::", &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, false, false, false, false, false, false, Some(InterfaceLocal)); - check("ff02::", &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, false, false, false, false, false, false, Some(LinkLocal)); - check("ff03::", &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, false, false, false, false, false, false, Some(RealmLocal)); - check("ff04::", &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, false, false, false, false, false, false, Some(AdminLocal)); - check("ff05::", &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, false, false, false, false, false, false, Some(SiteLocal)); - check("ff08::", &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, false, false, false, false, false, false, Some(OrganizationLocal)); - check("ff0e::", &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - false, false, false, true, false, false, false, false, Some(Global)); - check("2001:db8:85a3::8a2e:370:7334", - &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34], - false, false, false, false, false, false, false, true, None); - check("102:304:506:708:90a:b0c:d0e:f10", - &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], - false, false, false, true, false, false, true, false, None); + macro_rules! check { + ($s:expr, &[$($octet:expr),*], $mask:expr) => { + assert_eq!($s, ip!($s).to_string()); + let octets = &[$($octet),*]; + assert_eq!(&ip!($s).octets(), octets); + assert_eq!(Ipv6Addr::from(*octets), ip!($s)); + + let unspecified: u16 = 1 << 0; + let loopback: u16 = 1 << 1; + let unique_local: u16 = 1 << 2; + let global: u16 = 1 << 3; + let unicast_link_local: u16 = 1 << 4; + let unicast_site_local: u16 = 1 << 5; + let unicast_global: u16 = 1 << 6; + let documentation: u16 = 1 << 7; + let multicast_interface_local: u16 = 1 << 8; + let multicast_link_local: u16 = 1 << 9; + let multicast_realm_local: u16 = 1 << 10; + let multicast_admin_local: u16 = 1 << 11; + let multicast_site_local: u16 = 1 << 12; + let multicast_organization_local: u16 = 1 << 13; + let multicast_global: u16 = 1 << 14; + let multicast: u16 = multicast_interface_local + | multicast_admin_local + | multicast_global + | multicast_link_local + | multicast_realm_local + | multicast_site_local + | multicast_organization_local; + + if ($mask & unspecified) == unspecified { + assert!(ip!($s).is_unspecified()); + } else { + assert!(!ip!($s).is_unspecified()); + } + if ($mask & loopback) == loopback { + assert!(ip!($s).is_loopback()); + } else { + assert!(!ip!($s).is_loopback()); + } + if ($mask & unique_local) == unique_local { + assert!(ip!($s).is_unique_local()); + } else { + assert!(!ip!($s).is_unique_local()); + } + if ($mask & global) == global { + assert!(ip!($s).is_global()); + } else { + assert!(!ip!($s).is_global()); + } + if ($mask & unicast_link_local) == unicast_link_local { + assert!(ip!($s).is_unicast_link_local()); + } else { + assert!(!ip!($s).is_unicast_link_local()); + } + if ($mask & unicast_site_local) == unicast_site_local { + assert!(ip!($s).is_unicast_site_local()); + } else { + assert!(!ip!($s).is_unicast_site_local()); + } + if ($mask & unicast_global) == unicast_global { + assert!(ip!($s).is_unicast_global()); + } else { + assert!(!ip!($s).is_unicast_global()); + } + if ($mask & documentation) == documentation { + assert!(ip!($s).is_documentation()); + } else { + assert!(!ip!($s).is_documentation()); + } + if ($mask & multicast) != 0 { + assert!(ip!($s).multicast_scope().is_some()); + assert!(ip!($s).is_multicast()); + } else { + assert!(ip!($s).multicast_scope().is_none()); + assert!(!ip!($s).is_multicast()); + } + if ($mask & multicast_interface_local) == multicast_interface_local { + assert_eq!(ip!($s).multicast_scope().unwrap(), + Ipv6MulticastScope::InterfaceLocal); + } + if ($mask & multicast_link_local) == multicast_link_local { + assert_eq!(ip!($s).multicast_scope().unwrap(), + Ipv6MulticastScope::LinkLocal); + } + if ($mask & multicast_realm_local) == multicast_realm_local { + assert_eq!(ip!($s).multicast_scope().unwrap(), + Ipv6MulticastScope::RealmLocal); + } + if ($mask & multicast_admin_local) == multicast_admin_local { + assert_eq!(ip!($s).multicast_scope().unwrap(), + Ipv6MulticastScope::AdminLocal); + } + if ($mask & multicast_site_local) == multicast_site_local { + assert_eq!(ip!($s).multicast_scope().unwrap(), + Ipv6MulticastScope::SiteLocal); + } + if ($mask & multicast_organization_local) == multicast_organization_local { + assert_eq!(ip!($s).multicast_scope().unwrap(), + Ipv6MulticastScope::OrganizationLocal); + } + if ($mask & multicast_global) == multicast_global { + assert_eq!(ip!($s).multicast_scope().unwrap(), + Ipv6MulticastScope::Global); + } + } + } + + let unspecified: u16 = 1 << 0; + let loopback: u16 = 1 << 1; + let unique_local: u16 = 1 << 2; + let global: u16 = 1 << 3; + let unicast_link_local: u16 = 1 << 4; + let unicast_site_local: u16 = 1 << 5; + let unicast_global: u16 = 1 << 6; + let documentation: u16 = 1 << 7; + let multicast_interface_local: u16 = 1 << 8; + let multicast_link_local: u16 = 1 << 9; + let multicast_realm_local: u16 = 1 << 10; + let multicast_admin_local: u16 = 1 << 11; + let multicast_site_local: u16 = 1 << 12; + let multicast_organization_local: u16 = 1 << 13; + let multicast_global: u16 = 1 << 14; + + check!("::", + &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + unspecified); + + check!("::1", + &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], + loopback); + + check!("::0.0.0.2", + &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], + global | unicast_global); + + check!("1::", + &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + global | unicast_global); + + check!("fc00::", + &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + unique_local); + + check!("fdff:ffff::", + &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + unique_local); + + check!("fe80:ffff::", + &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + unicast_link_local); + + check!("febf:ffff::", + &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + unicast_link_local); + + check!("fec0::", + &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + unicast_site_local); + + check!("ff01::", + &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_interface_local); + + check!("ff02::", + &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_link_local); + + check!("ff03::", + &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_realm_local); + + check!("ff04::", + &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_admin_local); + + check!("ff05::", + &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_site_local); + + check!("ff08::", + &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_organization_local); + + check!("ff0e::", + &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + multicast_global | global); + + check!("2001:db8:85a3::8a2e:370:7334", + &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34], + documentation); + + check!("102:304:506:708:90a:b0c:d0e:f10", + &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], + global| unicast_global); } #[test] From c302d2c78f94839473a7e9be3eb4756d0f1e2508 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sat, 20 Apr 2019 22:33:05 +0200 Subject: [PATCH 0035/3207] std::net: fix Ipv4addr::is_global() tests Ipv4addr::is_global() previously considered 0/8 was global, but has now been fixed, so these tests needed to be fixed as well. --- src/libstd/net/ip.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 17200d7b94a4..cd78eb05c11a 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -2008,8 +2008,8 @@ mod tests { let doc: u8 = 1 << 4; check!("0.0.0.0", unspec); - check!("0.0.0.1", global); - check!("0.1.0.0", global); + check!("0.0.0.1"); + check!("0.1.0.0"); check!("10.9.8.7"); check!("127.1.2.3", loopback); check!("172.31.254.253"); @@ -2127,8 +2127,8 @@ mod tests { let documentation: u8 = 1 << 7; check!("0.0.0.0", unspec); - check!("0.0.0.1", global); - check!("0.1.0.0", global); + check!("0.0.0.1"); + check!("0.1.0.0"); check!("10.9.8.7", private); check!("127.1.2.3", loopback); check!("172.31.254.253", private); From 99d9bb640f0ea95ae6a7346c82a61008b2363c16 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Sun, 21 Apr 2019 19:47:54 +0200 Subject: [PATCH 0036/3207] std::net: fix tests for site-local ipv6 addresses Ipv6Addr::is_unicast_global() now returns `true` for unicast site local addresses, since they are deprecated. --- src/libstd/net/ip.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index cd78eb05c11a..6f39575da2c4 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -2032,7 +2032,7 @@ mod tests { check!("fdff:ffff::"); check!("fe80:ffff::"); check!("febf:ffff::"); - check!("fec0::"); + check!("fec0::", global); check!("ff01::", multicast); check!("ff02::", multicast); check!("ff03::", multicast); @@ -2310,7 +2310,7 @@ mod tests { check!("fec0::", &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - unicast_site_local); + unicast_site_local|unicast_global|global); check!("ff01::", &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], From 40d0127a091dbf3eb55ef57de5facc4983ee472d Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 22 Apr 2019 15:27:14 +0200 Subject: [PATCH 0037/3207] std::net: tests for Ipv6addr::is_unicast_link_local{_strict}() --- src/libstd/net/ip.rs | 69 +++++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 6f39575da2c4..7ce8974e09fd 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -2164,16 +2164,17 @@ mod tests { let unique_local: u16 = 1 << 2; let global: u16 = 1 << 3; let unicast_link_local: u16 = 1 << 4; - let unicast_site_local: u16 = 1 << 5; - let unicast_global: u16 = 1 << 6; - let documentation: u16 = 1 << 7; - let multicast_interface_local: u16 = 1 << 8; - let multicast_link_local: u16 = 1 << 9; - let multicast_realm_local: u16 = 1 << 10; - let multicast_admin_local: u16 = 1 << 11; - let multicast_site_local: u16 = 1 << 12; - let multicast_organization_local: u16 = 1 << 13; - let multicast_global: u16 = 1 << 14; + let unicast_link_local_strict: u16 = 1 << 5; + let unicast_site_local: u16 = 1 << 6; + let unicast_global: u16 = 1 << 7; + let documentation: u16 = 1 << 8; + let multicast_interface_local: u16 = 1 << 9; + let multicast_link_local: u16 = 1 << 10; + let multicast_realm_local: u16 = 1 << 11; + let multicast_admin_local: u16 = 1 << 12; + let multicast_site_local: u16 = 1 << 13; + let multicast_organization_local: u16 = 1 << 14; + let multicast_global: u16 = 1 << 15; let multicast: u16 = multicast_interface_local | multicast_admin_local | multicast_global @@ -2207,6 +2208,11 @@ mod tests { } else { assert!(!ip!($s).is_unicast_link_local()); } + if ($mask & unicast_link_local_strict) == unicast_link_local_strict { + assert!(ip!($s).is_unicast_link_local_strict()); + } else { + assert!(!ip!($s).is_unicast_link_local_strict()); + } if ($mask & unicast_site_local) == unicast_site_local { assert!(ip!($s).is_unicast_site_local()); } else { @@ -2265,16 +2271,17 @@ mod tests { let unique_local: u16 = 1 << 2; let global: u16 = 1 << 3; let unicast_link_local: u16 = 1 << 4; - let unicast_site_local: u16 = 1 << 5; - let unicast_global: u16 = 1 << 6; - let documentation: u16 = 1 << 7; - let multicast_interface_local: u16 = 1 << 8; - let multicast_link_local: u16 = 1 << 9; - let multicast_realm_local: u16 = 1 << 10; - let multicast_admin_local: u16 = 1 << 11; - let multicast_site_local: u16 = 1 << 12; - let multicast_organization_local: u16 = 1 << 13; - let multicast_global: u16 = 1 << 14; + let unicast_link_local_strict: u16 = 1 << 5; + let unicast_site_local: u16 = 1 << 6; + let unicast_global: u16 = 1 << 7; + let documentation: u16 = 1 << 8; + let multicast_interface_local: u16 = 1 << 9; + let multicast_link_local: u16 = 1 << 10; + let multicast_realm_local: u16 = 1 << 11; + let multicast_admin_local: u16 = 1 << 12; + let multicast_site_local: u16 = 1 << 13; + let multicast_organization_local: u16 = 1 << 14; + let multicast_global: u16 = 1 << 15; check!("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], @@ -2304,10 +2311,32 @@ mod tests { &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_link_local); + check!("fe80::", + &[0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + unicast_link_local|unicast_link_local_strict); + check!("febf:ffff::", &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_link_local); + check!("febf::", + &[0xfe, 0xbf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + unicast_link_local); + + check!("febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff", + &[0xfe, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], + unicast_link_local); + + check!("fe80::ffff:ffff:ffff:ffff", + &[0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], + unicast_link_local|unicast_link_local_strict); + + check!("fe80:0:0:1::", + &[0xfe, 0x80, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], + unicast_link_local); + check!("fec0::", &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_site_local|unicast_global|global); From 9dcfd9f58ca808d586c186f983f5572667e56471 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 22 Apr 2019 15:47:41 +0200 Subject: [PATCH 0038/3207] std::net: tests for Ipv4addr::is_benchmarking() also add test to Ipaddr, making sure that these addresses are not global. --- src/libstd/net/ip.rs | 46 +++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 7ce8974e09fd..5e93a6c1e867 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -2023,6 +2023,9 @@ mod tests { check!("224.0.0.0", global|multicast); check!("239.255.255.255", global|multicast); check!("255.255.255.255"); + check!("198.18.0.0"); + check!("198.18.54.2"); + check!("198.19.255.255"); check!("::", unspec); check!("::1", loopback); @@ -2058,14 +2061,15 @@ mod tests { }; ($s:expr, $mask:expr) => {{ - let unspec: u8 = 1 << 0; - let loopback: u8 = 1 << 1; - let private: u8 = 1 << 2; - let link_local: u8 = 1 << 3; - let global: u8 = 1 << 4; - let multicast: u8 = 1 << 5; - let broadcast: u8 = 1 << 6; - let documentation: u8 = 1 << 7; + let unspec: u16 = 1 << 0; + let loopback: u16 = 1 << 1; + let private: u16 = 1 << 2; + let link_local: u16 = 1 << 3; + let global: u16 = 1 << 4; + let multicast: u16 = 1 << 5; + let broadcast: u16 = 1 << 6; + let documentation: u16 = 1 << 7; + let benchmarking: u16 = 1 << 8; if ($mask & unspec) == unspec { assert!(ip!($s).is_unspecified()); @@ -2114,17 +2118,24 @@ mod tests { } else { assert!(!ip!($s).is_documentation()); } + + if ($mask & benchmarking) == benchmarking { + assert!(ip!($s).is_benchmarking()); + } else { + assert!(!ip!($s).is_benchmarking()); + } }} } - let unspec: u8 = 1 << 0; - let loopback: u8 = 1 << 1; - let private: u8 = 1 << 2; - let link_local: u8 = 1 << 3; - let global: u8 = 1 << 4; - let multicast: u8 = 1 << 5; - let broadcast: u8 = 1 << 6; - let documentation: u8 = 1 << 7; + let unspec: u16 = 1 << 0; + let loopback: u16 = 1 << 1; + let private: u16 = 1 << 2; + let link_local: u16 = 1 << 3; + let global: u16 = 1 << 4; + let multicast: u16 = 1 << 5; + let broadcast: u16 = 1 << 6; + let documentation: u16 = 1 << 7; + let benchmarking: u16 = 1 << 8; check!("0.0.0.0", unspec); check!("0.0.0.1"); @@ -2142,6 +2153,9 @@ mod tests { check!("224.0.0.0", global|multicast); check!("239.255.255.255", global|multicast); check!("255.255.255.255", broadcast); + check!("198.18.0.0", benchmarking); + check!("198.18.54.2", benchmarking); + check!("198.19.255.255", benchmarking); } #[test] From a2bead8761306a46079edc8cc7cff84b85d8f891 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 22 Apr 2019 16:00:58 +0200 Subject: [PATCH 0039/3207] std::net: tests for Ipv4addr::is_ietf_protocol_assignment() Also add tests to IpAddr to make sure these addresses are not global. --- src/libstd/net/ip.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 5e93a6c1e867..4ff47257c3fc 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -2023,9 +2023,14 @@ mod tests { check!("224.0.0.0", global|multicast); check!("239.255.255.255", global|multicast); check!("255.255.255.255"); + // make sure benchmarking addresses are not global check!("198.18.0.0"); check!("198.18.54.2"); check!("198.19.255.255"); + // make sure addresses reserved for protocol assignment are not global + check!("192.0.0.0"); + check!("192.0.0.255"); + check!("192.0.0.100"); check!("::", unspec); check!("::1", loopback); @@ -2070,6 +2075,7 @@ mod tests { let broadcast: u16 = 1 << 6; let documentation: u16 = 1 << 7; let benchmarking: u16 = 1 << 8; + let ietf_protocol_assignment: u16 = 1 << 9; if ($mask & unspec) == unspec { assert!(ip!($s).is_unspecified()); @@ -2124,6 +2130,12 @@ mod tests { } else { assert!(!ip!($s).is_benchmarking()); } + + if ($mask & ietf_protocol_assignment) == ietf_protocol_assignment { + assert!(ip!($s).is_ietf_protocol_assignment()); + } else { + assert!(!ip!($s).is_ietf_protocol_assignment()); + } }} } @@ -2136,6 +2148,7 @@ mod tests { let broadcast: u16 = 1 << 6; let documentation: u16 = 1 << 7; let benchmarking: u16 = 1 << 8; + let ietf_protocol_assignment: u16 = 1 << 9; check!("0.0.0.0", unspec); check!("0.0.0.1"); @@ -2156,6 +2169,9 @@ mod tests { check!("198.18.0.0", benchmarking); check!("198.18.54.2", benchmarking); check!("198.19.255.255", benchmarking); + check!("192.0.0.0", ietf_protocol_assignment); + check!("192.0.0.255", ietf_protocol_assignment); + check!("192.0.0.100", ietf_protocol_assignment); } #[test] From 66627777b54843dc6c5630e27dd995258b05ac6d Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Mon, 22 Apr 2019 16:14:28 +0200 Subject: [PATCH 0040/3207] std::net: tests for Ipv4addr::is_reserved() Also add tests to IpAddr for make sure these addresses are not global or multicast. --- src/libstd/net/ip.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 4ff47257c3fc..1322733bb15b 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -2031,6 +2031,10 @@ mod tests { check!("192.0.0.0"); check!("192.0.0.255"); check!("192.0.0.100"); + // make sure reserved addresses are not global + check!("240.0.0.0"); + check!("251.54.1.76"); + check!("254.255.255.255"); check!("::", unspec); check!("::1", loopback); @@ -2076,6 +2080,7 @@ mod tests { let documentation: u16 = 1 << 7; let benchmarking: u16 = 1 << 8; let ietf_protocol_assignment: u16 = 1 << 9; + let reserved: u16 = 1 << 10; if ($mask & unspec) == unspec { assert!(ip!($s).is_unspecified()); @@ -2136,6 +2141,12 @@ mod tests { } else { assert!(!ip!($s).is_ietf_protocol_assignment()); } + + if ($mask & reserved) == reserved { + assert!(ip!($s).is_reserved()); + } else { + assert!(!ip!($s).is_reserved()); + } }} } @@ -2149,6 +2160,7 @@ mod tests { let documentation: u16 = 1 << 7; let benchmarking: u16 = 1 << 8; let ietf_protocol_assignment: u16 = 1 << 9; + let reserved: u16 = 1 << 10; check!("0.0.0.0", unspec); check!("0.0.0.1"); @@ -2172,6 +2184,9 @@ mod tests { check!("192.0.0.0", ietf_protocol_assignment); check!("192.0.0.255", ietf_protocol_assignment); check!("192.0.0.100", ietf_protocol_assignment); + check!("240.0.0.0", reserved); + check!("251.54.1.76", reserved); + check!("254.255.255.255", reserved); } #[test] From fc7ffa670c1eeea4999aa84d131c4fd5358da43b Mon Sep 17 00:00:00 2001 From: LooMaclin Date: Tue, 23 Apr 2019 03:15:27 +0300 Subject: [PATCH 0041/3207] Improve miri's error reporting in check_in_alloc --- src/librustc/mir/interpret/allocation.rs | 4 +++- src/librustc/mir/interpret/error.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 84733f9af6d5..bc2dbfcbf388 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -32,8 +32,10 @@ pub enum CheckInAllocMsg { } impl Display for CheckInAllocMsg { + /// When this printed as an error the context looks like this + /// "{test name} test failed: pointer must be in-bounds at offset..." fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", match *self { + write!(f, "{} test", match *self { CheckInAllocMsg::MemoryAccessTest => "Memory access", CheckInAllocMsg::NullPointerTest => "Null pointer", CheckInAllocMsg::PointerArithmeticTest => "Pointer arithmetic", diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index cf2d12b59359..ce281cf0d340 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -461,7 +461,7 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for InterpError<'tcx, O> { use self::InterpError::*; match *self { PointerOutOfBounds { ptr, msg, allocation_size } => { - write!(f, "{} test failed: pointer must be in-bounds at offset {}, \ + write!(f, "{} failed: pointer must be in-bounds at offset {}, \ but is outside bounds of allocation {} which has size {}", msg, ptr.offset.bytes(), ptr.alloc_id, allocation_size.bytes()) }, From 634dcd00b4f4a57cea0baae85d364d433897bf59 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Tue, 23 Apr 2019 10:38:26 +0200 Subject: [PATCH 0042/3207] std::net: add warning in Ipv6Addr::is_unicast_site_local() doc site-local addresses are deprecated, so we should warn users about it. --- src/libstd/net/ip.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 1322733bb15b..e3e257f5ac17 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -1335,6 +1335,14 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0xfec2, 0, 0, 0, 0, 0, 0, 0).is_unicast_site_local(), true); /// } /// ``` + /// + /// # Warning + /// + /// As per [RFC 3879], the whole `FEC0::/10` prefix is + /// deprecated. New software must not support site-local + /// addresses. + /// + /// [RFC 3879]: https://tools.ietf.org/html/rfc3879 pub fn is_unicast_site_local(&self) -> bool { (self.segments()[0] & 0xffc0) == 0xfec0 } From fe718ef07f56457740b59b196eed0f1226137895 Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Tue, 23 Apr 2019 10:40:15 +0200 Subject: [PATCH 0043/3207] std::net: add warning in Ipv4addr::is_reserved() documentation See @the8472 comment's on Github: https://github.com/rust-lang/rust/pull/60145#issuecomment-485424229 > I don't think is_reserved including ranges marked for future use is > a good idea since those future uses may be realized at at some point > and then old software with is_reserved filters may have false > positives. This is not a hypothetical concern, such issues have been > encountered before when IANA assigned previously reserved /8 address > blocks. --- src/libstd/net/ip.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index e3e257f5ac17..6ea49de49af6 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -677,6 +677,13 @@ impl Ipv4Addr { /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112 /// [`true`]: ../../std/primitive.bool.html /// + /// # Warning + /// + /// As IANA assigns new addresses, this method will be + /// updated. This may result in non-reserved addresses being + /// treated as reserved in code that relies on an outdated version + /// of this method. + /// /// # Examples /// /// ``` From b1c829b6379568b4355e9759981b6ad96d08c9c7 Mon Sep 17 00:00:00 2001 From: Loo Maclin Date: Tue, 23 Apr 2019 12:12:16 +0300 Subject: [PATCH 0044/3207] Improve miri's error reporting in check_in_alloc --- src/librustc/mir/interpret/allocation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index bc2dbfcbf388..2910deadb9e4 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -32,7 +32,7 @@ pub enum CheckInAllocMsg { } impl Display for CheckInAllocMsg { - /// When this printed as an error the context looks like this + /// When this is printed as an error the context looks like this /// "{test name} test failed: pointer must be in-bounds at offset..." fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{} test", match *self { From cddb838043fb0201c09bf0a8692001b04b3bec1a Mon Sep 17 00:00:00 2001 From: Corentin Henry Date: Tue, 23 Apr 2019 12:00:23 +0200 Subject: [PATCH 0045/3207] std::net: tests for Ipv4addr::is_shared() --- src/libstd/net/ip.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 6ea49de49af6..6b504056e5f8 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -2050,6 +2050,10 @@ mod tests { check!("240.0.0.0"); check!("251.54.1.76"); check!("254.255.255.255"); + // make sure shared addresses are not global + check!("100.64.0.0"); + check!("100.127.255.255"); + check!("100.100.100.0"); check!("::", unspec); check!("::1", loopback); @@ -2096,6 +2100,7 @@ mod tests { let benchmarking: u16 = 1 << 8; let ietf_protocol_assignment: u16 = 1 << 9; let reserved: u16 = 1 << 10; + let shared: u16 = 1 << 11; if ($mask & unspec) == unspec { assert!(ip!($s).is_unspecified()); @@ -2162,6 +2167,12 @@ mod tests { } else { assert!(!ip!($s).is_reserved()); } + + if ($mask & shared) == shared { + assert!(ip!($s).is_shared()); + } else { + assert!(!ip!($s).is_shared()); + } }} } @@ -2176,6 +2187,7 @@ mod tests { let benchmarking: u16 = 1 << 8; let ietf_protocol_assignment: u16 = 1 << 9; let reserved: u16 = 1 << 10; + let shared: u16 = 1 << 11; check!("0.0.0.0", unspec); check!("0.0.0.1"); @@ -2202,6 +2214,9 @@ mod tests { check!("240.0.0.0", reserved); check!("251.54.1.76", reserved); check!("254.255.255.255", reserved); + check!("100.64.0.0", shared); + check!("100.127.255.255", shared); + check!("100.100.100.0", shared); } #[test] From 0967d28be787b281c0364aca8fb9c25124029b30 Mon Sep 17 00:00:00 2001 From: Matthias Geier Date: Sat, 27 Apr 2019 21:28:40 +0200 Subject: [PATCH 0046/3207] Rename .cap() methods to .capacity() ... but leave the old names in there for backwards compatibility. --- src/liballoc/collections/vec_deque.rs | 34 +++---- src/liballoc/raw_vec.rs | 125 ++++++++++++++------------ src/liballoc/vec.rs | 8 +- src/libarena/lib.rs | 6 +- src/libcore/slice/rotate.rs | 4 +- src/libstd/sync/mpsc/sync.rs | 14 +-- 6 files changed, 99 insertions(+), 92 deletions(-) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index d65c24f7350a..793da97a083f 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -98,7 +98,7 @@ impl VecDeque { // For zero sized types, we are always at maximum capacity MAXIMUM_ZST_CAPACITY } else { - self.buf.cap() + self.buf.capacity() } } @@ -314,10 +314,10 @@ impl VecDeque { } /// Frobs the head and tail sections around to handle the fact that we - /// just reallocated. Unsafe because it trusts old_cap. + /// just reallocated. Unsafe because it trusts old_capacity. #[inline] - unsafe fn handle_cap_increase(&mut self, old_cap: usize) { - let new_cap = self.cap(); + unsafe fn handle_capacity_increase(&mut self, old_capacity: usize) { + let new_capacity = self.cap(); // Move the shortest contiguous section of the ring buffer // T H @@ -336,15 +336,15 @@ impl VecDeque { if self.tail <= self.head { // A // Nop - } else if self.head < old_cap - self.tail { + } else if self.head < old_capacity - self.tail { // B - self.copy_nonoverlapping(old_cap, 0, self.head); - self.head += old_cap; + self.copy_nonoverlapping(old_capacity, 0, self.head); + self.head += old_capacity; debug_assert!(self.head > self.tail); } else { // C - let new_tail = new_cap - (old_cap - self.tail); - self.copy_nonoverlapping(new_tail, self.tail, old_cap - self.tail); + let new_tail = new_capacity - (old_capacity - self.tail); + self.copy_nonoverlapping(new_tail, self.tail, old_capacity - self.tail); self.tail = new_tail; debug_assert!(self.head < self.tail); } @@ -551,7 +551,7 @@ impl VecDeque { if new_cap > old_cap { self.buf.reserve_exact(used_cap, new_cap - used_cap); unsafe { - self.handle_cap_increase(old_cap); + self.handle_capacity_increase(old_cap); } } } @@ -641,7 +641,7 @@ impl VecDeque { if new_cap > old_cap { self.buf.try_reserve_exact(used_cap, new_cap - used_cap)?; unsafe { - self.handle_cap_increase(old_cap); + self.handle_capacity_increase(old_cap); } } Ok(()) @@ -1873,7 +1873,7 @@ impl VecDeque { let old_cap = self.cap(); self.buf.double(); unsafe { - self.handle_cap_increase(old_cap); + self.handle_capacity_increase(old_cap); } debug_assert!(!self.is_full()); } @@ -2708,9 +2708,9 @@ impl From> for VecDeque { // We need to extend the buf if it's not a power of two, too small // or doesn't have at least one free space - if !buf.cap().is_power_of_two() || (buf.cap() < (MINIMUM_CAPACITY + 1)) || - (buf.cap() == len) { - let cap = cmp::max(buf.cap() + 1, MINIMUM_CAPACITY + 1).next_power_of_two(); + if !buf.capacity().is_power_of_two() || (buf.capacity() < (MINIMUM_CAPACITY + 1)) || + (buf.capacity() == len) { + let cap = cmp::max(buf.capacity() + 1, MINIMUM_CAPACITY + 1).next_power_of_two(); buf.reserve_exact(len, cap - len); } @@ -3096,8 +3096,8 @@ mod tests { fn test_vec_from_vecdeque() { use crate::vec::Vec; - fn create_vec_and_test_convert(cap: usize, offset: usize, len: usize) { - let mut vd = VecDeque::with_capacity(cap); + fn create_vec_and_test_convert(capacity: usize, offset: usize, len: usize) { + let mut vd = VecDeque::with_capacity(capacity); for _ in 0..offset { vd.push_back(0); vd.pop_front(); diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index d1fc5ac3b30d..e5a8a522fbc1 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -34,7 +34,7 @@ use crate::boxed::Box; /// that might occur with zero-sized types. /// /// However this means that you need to be careful when round-tripping this type -/// with a `Box<[T]>`: `cap()` won't yield the len. However `with_capacity`, +/// with a `Box<[T]>`: `capacity()` won't yield the len. However `with_capacity`, /// `shrink_to_fit`, and `from_box` will actually set RawVec's private capacity /// field. This allows zero-sized types to not be special-cased by consumers of /// this type. @@ -65,25 +65,25 @@ impl RawVec { /// Like `with_capacity` but parameterized over the choice of /// allocator for the returned RawVec. #[inline] - pub fn with_capacity_in(cap: usize, a: A) -> Self { - RawVec::allocate_in(cap, false, a) + pub fn with_capacity_in(capacity: usize, a: A) -> Self { + RawVec::allocate_in(capacity, false, a) } /// Like `with_capacity_zeroed` but parameterized over the choice /// of allocator for the returned RawVec. #[inline] - pub fn with_capacity_zeroed_in(cap: usize, a: A) -> Self { - RawVec::allocate_in(cap, true, a) + pub fn with_capacity_zeroed_in(capacity: usize, a: A) -> Self { + RawVec::allocate_in(capacity, true, a) } - fn allocate_in(cap: usize, zeroed: bool, mut a: A) -> Self { + fn allocate_in(capacity: usize, zeroed: bool, mut a: A) -> Self { unsafe { let elem_size = mem::size_of::(); - let alloc_size = cap.checked_mul(elem_size).unwrap_or_else(|| capacity_overflow()); + let alloc_size = capacity.checked_mul(elem_size).unwrap_or_else(|| capacity_overflow()); alloc_guard(alloc_size).unwrap_or_else(|_| capacity_overflow()); - // handles ZSTs and `cap = 0` alike + // handles ZSTs and `capacity = 0` alike let ptr = if alloc_size == 0 { NonNull::::dangling() } else { @@ -102,7 +102,7 @@ impl RawVec { RawVec { ptr: ptr.into(), - cap, + cap: capacity, a, } } @@ -120,8 +120,8 @@ impl RawVec { } /// Creates a RawVec (on the system heap) with exactly the - /// capacity and alignment requirements for a `[T; cap]`. This is - /// equivalent to calling RawVec::new when `cap` is 0 or T is + /// capacity and alignment requirements for a `[T; capacity]`. This is + /// equivalent to calling RawVec::new when `capacity` is 0 or T is /// zero-sized. Note that if `T` is zero-sized this means you will /// *not* get a RawVec with the requested capacity! /// @@ -135,14 +135,14 @@ impl RawVec { /// /// Aborts on OOM #[inline] - pub fn with_capacity(cap: usize) -> Self { - RawVec::allocate_in(cap, false, Global) + pub fn with_capacity(capacity: usize) -> Self { + RawVec::allocate_in(capacity, false, Global) } /// Like `with_capacity` but guarantees the buffer is zeroed. #[inline] - pub fn with_capacity_zeroed(cap: usize) -> Self { - RawVec::allocate_in(cap, true, Global) + pub fn with_capacity_zeroed(capacity: usize) -> Self { + RawVec::allocate_in(capacity, true, Global) } } @@ -154,10 +154,10 @@ impl RawVec { /// The ptr must be allocated (via the given allocator `a`), and with the given capacity. The /// capacity cannot exceed `isize::MAX` (only a concern on 32-bit systems). /// If the ptr and capacity come from a RawVec created via `a`, then this is guaranteed. - pub unsafe fn from_raw_parts_in(ptr: *mut T, cap: usize, a: A) -> Self { + pub unsafe fn from_raw_parts_in(ptr: *mut T, capacity: usize, a: A) -> Self { RawVec { ptr: Unique::new_unchecked(ptr), - cap, + cap: capacity, a, } } @@ -171,10 +171,10 @@ impl RawVec { /// The ptr must be allocated (on the system heap), and with the given capacity. The /// capacity cannot exceed `isize::MAX` (only a concern on 32-bit systems). /// If the ptr and capacity come from a RawVec, then this is guaranteed. - pub unsafe fn from_raw_parts(ptr: *mut T, cap: usize) -> Self { + pub unsafe fn from_raw_parts(ptr: *mut T, capacity: usize) -> Self { RawVec { ptr: Unique::new_unchecked(ptr), - cap, + cap: capacity, a: Global, } } @@ -191,7 +191,7 @@ impl RawVec { impl RawVec { /// Gets a raw pointer to the start of the allocation. Note that this is - /// Unique::empty() if `cap = 0` or T is zero-sized. In the former case, you must + /// Unique::empty() if `capacity = 0` or T is zero-sized. In the former case, you must /// be careful. pub fn ptr(&self) -> *mut T { self.ptr.as_ptr() @@ -201,7 +201,7 @@ impl RawVec { /// /// This will always be `usize::MAX` if `T` is zero-sized. #[inline(always)] - pub fn cap(&self) -> usize { + pub fn capacity(&self) -> usize { if mem::size_of::() == 0 { !0 } else { @@ -209,6 +209,12 @@ impl RawVec { } } + // For backwards compatibility + #[inline(always)] + pub fn cap(&self) -> usize { + self.capacity() + } + /// Returns a shared reference to the allocator backing this RawVec. pub fn alloc(&self) -> &A { &self.a @@ -240,7 +246,7 @@ impl RawVec { /// This function is ideal for when pushing elements one-at-a-time because /// you don't need to incur the costs of the more general computations /// reserve needs to do to guard against overflow. You do however need to - /// manually check if your `len == cap`. + /// manually check if your `len == capacity`. /// /// # Panics /// @@ -267,7 +273,7 @@ impl RawVec { /// /// impl MyVec { /// pub fn push(&mut self, elem: T) { - /// if self.len == self.buf.cap() { self.buf.double(); } + /// if self.len == self.buf.capacity() { self.buf.double(); } /// // double would have aborted or panicked if the len exceeded /// // `isize::MAX` so this is safe to do unchecked now. /// unsafe { @@ -381,20 +387,20 @@ impl RawVec { } /// The same as `reserve_exact`, but returns on errors instead of panicking or aborting. - pub fn try_reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize) + pub fn try_reserve_exact(&mut self, used_capacity: usize, needed_extra_capacity: usize) -> Result<(), CollectionAllocErr> { - self.reserve_internal(used_cap, needed_extra_cap, Fallible, Exact) + self.reserve_internal(used_capacity, needed_extra_capacity, Fallible, Exact) } /// Ensures that the buffer contains at least enough space to hold - /// `used_cap + needed_extra_cap` elements. If it doesn't already, + /// `used_capacity + needed_extra_capacity` elements. If it doesn't already, /// will reallocate the minimum possible amount of memory necessary. /// Generally this will be exactly the amount of memory necessary, /// but in principle the allocator is free to give back more than /// we asked for. /// - /// If `used_cap` exceeds `self.cap()`, this may fail to actually allocate + /// If `used_capacity` exceeds `self.capacity()`, this may fail to actually allocate /// the requested space. This is not really unsafe, but the unsafe /// code *you* write that relies on the behavior of this function may break. /// @@ -407,22 +413,23 @@ impl RawVec { /// # Aborts /// /// Aborts on OOM - pub fn reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize) { - match self.reserve_internal(used_cap, needed_extra_cap, Infallible, Exact) { + pub fn reserve_exact(&mut self, used_capacity: usize, needed_extra_capacity: usize) { + match self.reserve_internal(used_capacity, needed_extra_capacity, Infallible, Exact) { Err(CapacityOverflow) => capacity_overflow(), Err(AllocErr) => unreachable!(), Ok(()) => { /* yay */ } } } - /// Calculates the buffer's new size given that it'll hold `used_cap + - /// needed_extra_cap` elements. This logic is used in amortized reserve methods. + /// Calculates the buffer's new size given that it'll hold `used_capacity + + /// needed_extra_capacity` elements. This logic is used in amortized reserve methods. /// Returns `(new_capacity, new_alloc_size)`. - fn amortized_new_size(&self, used_cap: usize, needed_extra_cap: usize) + fn amortized_new_size(&self, used_capacity: usize, needed_extra_capacity: usize) -> Result { // Nothing we can really do about these checks :( - let required_cap = used_cap.checked_add(needed_extra_cap).ok_or(CapacityOverflow)?; + let required_cap = used_capacity.checked_add(needed_extra_capacity) + .ok_or(CapacityOverflow)?; // Cannot overflow, because `cap <= isize::MAX`, and type of `cap` is `usize`. let double_cap = self.cap * 2; // `double_cap` guarantees exponential growth. @@ -430,18 +437,18 @@ impl RawVec { } /// The same as `reserve`, but returns on errors instead of panicking or aborting. - pub fn try_reserve(&mut self, used_cap: usize, needed_extra_cap: usize) + pub fn try_reserve(&mut self, used_capacity: usize, needed_extra_capacity: usize) -> Result<(), CollectionAllocErr> { - self.reserve_internal(used_cap, needed_extra_cap, Fallible, Amortized) + self.reserve_internal(used_capacity, needed_extra_capacity, Fallible, Amortized) } /// Ensures that the buffer contains at least enough space to hold - /// `used_cap + needed_extra_cap` elements. If it doesn't already have + /// `used_capacity + needed_extra_capacity` elements. If it doesn't already have /// enough capacity, will reallocate enough space plus comfortable slack /// space to get amortized `O(1)` behavior. Will limit this behavior /// if it would needlessly cause itself to panic. /// - /// If `used_cap` exceeds `self.cap()`, this may fail to actually allocate + /// If `used_capacity` exceeds `self.capacity()`, this may fail to actually allocate /// the requested space. This is not really unsafe, but the unsafe /// code *you* write that relies on the behavior of this function may break. /// @@ -487,20 +494,20 @@ impl RawVec { /// # vector.push_all(&[1, 3, 5, 7, 9]); /// # } /// ``` - pub fn reserve(&mut self, used_cap: usize, needed_extra_cap: usize) { - match self.reserve_internal(used_cap, needed_extra_cap, Infallible, Amortized) { + pub fn reserve(&mut self, used_capacity: usize, needed_extra_capacity: usize) { + match self.reserve_internal(used_capacity, needed_extra_capacity, Infallible, Amortized) { Err(CapacityOverflow) => capacity_overflow(), Err(AllocErr) => unreachable!(), Ok(()) => { /* yay */ } } } /// Attempts to ensure that the buffer contains at least enough space to hold - /// `used_cap + needed_extra_cap` elements. If it doesn't already have + /// `used_capacity + needed_extra_capacity` elements. If it doesn't already have /// enough capacity, will reallocate in place enough space plus comfortable slack /// space to get amortized `O(1)` behavior. Will limit this behaviour /// if it would needlessly cause itself to panic. /// - /// If `used_cap` exceeds `self.cap()`, this may fail to actually allocate + /// If `used_capacity` exceeds `self.capacity()`, this may fail to actually allocate /// the requested space. This is not really unsafe, but the unsafe /// code *you* write that relies on the behavior of this function may break. /// @@ -511,7 +518,7 @@ impl RawVec { /// * Panics if the requested capacity exceeds `usize::MAX` bytes. /// * Panics on 32-bit platforms if the requested capacity exceeds /// `isize::MAX` bytes. - pub fn reserve_in_place(&mut self, used_cap: usize, needed_extra_cap: usize) -> bool { + pub fn reserve_in_place(&mut self, used_capacity: usize, needed_extra_capacity: usize) -> bool { unsafe { // NOTE: we don't early branch on ZSTs here because we want this // to actually catch "asking for more than usize::MAX" in that case. @@ -520,20 +527,20 @@ impl RawVec { // Don't actually need any more capacity. If the current `cap` is 0, we can't // reallocate in place. - // Wrapping in case they give a bad `used_cap` + // Wrapping in case they give a bad `used_capacity` let old_layout = match self.current_layout() { Some(layout) => layout, None => return false, }; - if self.cap().wrapping_sub(used_cap) >= needed_extra_cap { + if self.capacity().wrapping_sub(used_capacity) >= needed_extra_capacity { return false; } - let new_cap = self.amortized_new_size(used_cap, needed_extra_cap) + let new_cap = self.amortized_new_size(used_capacity, needed_extra_capacity) .unwrap_or_else(|_| capacity_overflow()); - // Here, `cap < used_cap + needed_extra_cap <= new_cap` - // (regardless of whether `self.cap - used_cap` wrapped). + // Here, `cap < used_capacity + needed_extra_capacity <= new_cap` + // (regardless of whether `self.cap - used_capacity` wrapped). // Therefore we can safely call grow_in_place. let new_layout = Layout::new::().repeat(new_cap).unwrap().0; @@ -632,8 +639,8 @@ use ReserveStrategy::*; impl RawVec { fn reserve_internal( &mut self, - used_cap: usize, - needed_extra_cap: usize, + used_capacity: usize, + needed_extra_capacity: usize, fallibility: Fallibility, strategy: ReserveStrategy, ) -> Result<(), CollectionAllocErr> { @@ -646,15 +653,15 @@ impl RawVec { // panic. // Don't actually need any more capacity. - // Wrapping in case they gave a bad `used_cap`. - if self.cap().wrapping_sub(used_cap) >= needed_extra_cap { + // Wrapping in case they gave a bad `used_capacity`. + if self.capacity().wrapping_sub(used_capacity) >= needed_extra_capacity { return Ok(()); } // Nothing we can really do about these checks :( let new_cap = match strategy { - Exact => used_cap.checked_add(needed_extra_cap).ok_or(CapacityOverflow)?, - Amortized => self.amortized_new_size(used_cap, needed_extra_cap)?, + Exact => used_capacity.checked_add(needed_extra_capacity).ok_or(CapacityOverflow)?, + Amortized => self.amortized_new_size(used_capacity, needed_extra_capacity)?, }; let new_layout = Layout::array::(new_cap).map_err(|_| CapacityOverflow)?; @@ -692,7 +699,7 @@ impl RawVec { /// Note that this will correctly reconstitute any `cap` changes /// that may have been performed. (see description of type for details) pub unsafe fn into_box(self) -> Box<[T]> { - // NOTE: not calling `cap()` here, actually using the real `cap` field! + // NOTE: not calling `capacity()` here, actually using the real `cap` field! let slice = slice::from_raw_parts_mut(self.ptr(), self.cap); let output: Box<[T]> = Box::from_raw(slice); mem::forget(self); @@ -796,29 +803,29 @@ mod tests { let mut v: RawVec = RawVec::new(); // First `reserve` allocates like `reserve_exact` v.reserve(0, 9); - assert_eq!(9, v.cap()); + assert_eq!(9, v.capacity()); } { let mut v: RawVec = RawVec::new(); v.reserve(0, 7); - assert_eq!(7, v.cap()); + assert_eq!(7, v.capacity()); // 97 if more than double of 7, so `reserve` should work // like `reserve_exact`. v.reserve(7, 90); - assert_eq!(97, v.cap()); + assert_eq!(97, v.capacity()); } { let mut v: RawVec = RawVec::new(); v.reserve(0, 12); - assert_eq!(12, v.cap()); + assert_eq!(12, v.capacity()); v.reserve(12, 3); // 3 is less than half of 12, so `reserve` must grow // exponentially. At the time of writing this test grow // factor is 2, so new capacity is 24, however, grow factor // of 1.5 is OK too. Hence `>= 18` in assert. - assert!(v.cap() >= 12 + 12 / 2); + assert!(v.capacity() >= 12 + 12 / 2); } } diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index cd62c3e05244..72b702de875e 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -432,7 +432,7 @@ impl Vec { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn capacity(&self) -> usize { - self.buf.cap() + self.buf.capacity() } /// Reserves capacity for at least `additional` more elements to be inserted @@ -878,7 +878,7 @@ impl Vec { assert!(index <= len); // space for the new element - if len == self.buf.cap() { + if len == self.buf.capacity() { self.reserve(1); } @@ -1019,7 +1019,7 @@ impl Vec { pub fn push(&mut self, value: T) { // This will panic or abort if we would allocate > isize::MAX bytes // or if the length increment would overflow for zero-sized types. - if self.len == self.buf.cap() { + if self.len == self.buf.capacity() { self.reserve(1); } unsafe { @@ -1750,7 +1750,7 @@ impl IntoIterator for Vec { } else { begin.add(self.len()) as *const T }; - let cap = self.buf.cap(); + let cap = self.buf.capacity(); mem::forget(self); IntoIter { buf: NonNull::new_unchecked(begin), diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index ce5e5f23a94b..619b25c79053 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -99,7 +99,7 @@ impl TypedArenaChunk { // A pointer as large as possible for zero-sized elements. !0 as *mut T } else { - self.start().add(self.storage.cap()) + self.start().add(self.storage.capacity()) } } } @@ -270,7 +270,7 @@ impl TypedArena { self.end.set(last_chunk.end()); return; } else { - new_capacity = last_chunk.storage.cap(); + new_capacity = last_chunk.storage.capacity(); loop { new_capacity = new_capacity.checked_mul(2).unwrap(); if new_capacity >= currently_used_cap + n { @@ -405,7 +405,7 @@ impl DroplessArena { self.end.set(last_chunk.end()); return; } else { - new_capacity = last_chunk.storage.cap(); + new_capacity = last_chunk.storage.capacity(); loop { new_capacity = new_capacity.checked_mul(2).unwrap(); if new_capacity >= used_bytes + needed_bytes { diff --git a/src/libcore/slice/rotate.rs b/src/libcore/slice/rotate.rs index f69b219715aa..0437937d769b 100644 --- a/src/libcore/slice/rotate.rs +++ b/src/libcore/slice/rotate.rs @@ -16,7 +16,7 @@ union RawArray { } impl RawArray { - fn cap() -> usize { + fn capacity() -> usize { if mem::size_of::() == 0 { usize::max_value() } else { @@ -55,7 +55,7 @@ impl RawArray { pub unsafe fn ptr_rotate(mut left: usize, mid: *mut T, mut right: usize) { loop { let delta = cmp::min(left, right); - if delta <= RawArray::::cap() { + if delta <= RawArray::::capacity() { // We will always hit this immediately for ZST. break; } diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs index b2d9f4c6491e..36eafa50c9b4 100644 --- a/src/libstd/sync/mpsc/sync.rs +++ b/src/libstd/sync/mpsc/sync.rs @@ -161,20 +161,20 @@ fn wakeup(token: SignalToken, guard: MutexGuard<'_, State>) { } impl Packet { - pub fn new(cap: usize) -> Packet { + pub fn new(capacity: usize) -> Packet { Packet { channels: AtomicUsize::new(1), lock: Mutex::new(State { disconnected: false, blocker: NoneBlocked, - cap, + cap: capacity, canceled: None, queue: Queue { head: ptr::null_mut(), tail: ptr::null_mut(), }, buf: Buffer { - buf: (0..cap + if cap == 0 {1} else {0}).map(|_| None).collect(), + buf: (0..capacity + if capacity == 0 {1} else {0}).map(|_| None).collect(), start: 0, size: 0, }, @@ -189,7 +189,7 @@ impl Packet { loop { let mut guard = self.lock.lock().unwrap(); // are we ready to go? - if guard.disconnected || guard.buf.size() < guard.buf.cap() { + if guard.disconnected || guard.buf.size() < guard.buf.capacity() { return guard; } // no room; actually block @@ -231,7 +231,7 @@ impl Packet { let mut guard = self.lock.lock().unwrap(); if guard.disconnected { Err(super::TrySendError::Disconnected(t)) - } else if guard.buf.size() == guard.buf.cap() { + } else if guard.buf.size() == guard.buf.capacity() { Err(super::TrySendError::Full(t)) } else if guard.cap == 0 { // With capacity 0, even though we have buffer space we can't @@ -249,7 +249,7 @@ impl Packet { // If the buffer has some space and the capacity isn't 0, then we // just enqueue the data for later retrieval, ensuring to wake up // any blocked receiver if there is one. - assert!(guard.buf.size() < guard.buf.cap()); + assert!(guard.buf.size() < guard.buf.capacity()); guard.buf.enqueue(t); match mem::replace(&mut guard.blocker, NoneBlocked) { BlockedReceiver(token) => wakeup(token, guard), @@ -475,7 +475,7 @@ impl Buffer { } fn size(&self) -> usize { self.size } - fn cap(&self) -> usize { self.buf.len() } + fn capacity(&self) -> usize { self.buf.len() } } //////////////////////////////////////////////////////////////////////////////// From 5a3625d426bbd143e8178ae76e4d7939c6c96024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakob=20St=C3=A5hl?= Date: Thu, 25 Apr 2019 19:06:04 +0200 Subject: [PATCH 0047/3207] Explicitly set height on rust logo element in docs The layout of the left side menu in docs reflows when navigating between pages because of missing height on the element of rust logo. Setting height='100' tells the browser to reserve that vertical space, leading to a less janky experience. --- src/librustdoc/html/layout.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index acf019fd2254..7453c90bf96c 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -183,13 +183,13 @@ pub fn render( if layout.logo.is_empty() { format!("\ logo", + alt='logo' width='100' height='100'>", path=p, static_root_path=static_root_path, suffix=page.resource_suffix) } else { format!("\ - logo", + logo", p, layout.logo) } From f998182fb40cace8de8981bd641a8fb93632a4a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakob=20St=C3=A5hl?= Date: Thu, 25 Apr 2019 19:06:04 +0200 Subject: [PATCH 0048/3207] Revert "Explicitly set height on rust logo element in docs" This reverts commit d79a01b72f4722611cb21b719e6243aad3e7ec3c. --- src/librustdoc/html/layout.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 7453c90bf96c..acf019fd2254 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -183,13 +183,13 @@ pub fn render( if layout.logo.is_empty() { format!("\ logo", + alt='logo' width='100'>", path=p, static_root_path=static_root_path, suffix=page.resource_suffix) } else { format!("\ - logo", + logo", p, layout.logo) } From 184e3a3f92295fad81460ca13f9e845a2a5ff74a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakob=20St=C3=A5hl?= Date: Sat, 27 Apr 2019 15:09:57 +0200 Subject: [PATCH 0049/3207] Wrap logo in container to prevent layout reflow --- src/librustdoc/html/layout.rs | 6 ++++-- src/librustdoc/html/static/rustdoc.css | 5 +++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index acf019fd2254..7176abc3db87 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -182,14 +182,16 @@ pub fn render( let p = SlashChecker(&p); if layout.logo.is_empty() { format!("\ +
\ logo", + alt='logo' width='100'>
", path=p, static_root_path=static_root_path, suffix=page.resource_suffix) } else { format!("\ - logo", +
\ + logo
", p, layout.logo) } diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 53b08cf56978..66236d7cb450 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -182,6 +182,11 @@ nav.sub { display: none !important; } +.logo-container { + height: 0; + padding-bottom: 50%; +} + .sidebar img { margin: 20px auto; display: block; From 9db0fd7fd6a09969c3f3a0018599cef9e12b4ba9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 29 Apr 2019 11:45:06 +0200 Subject: [PATCH 0050/3207] Fix image position and display --- src/librustdoc/html/layout.rs | 6 ++---- src/librustdoc/html/static/rustdoc.css | 26 ++++++++++++++++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 7176abc3db87..ae0bd1aafa8f 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -183,15 +183,13 @@ pub fn render( if layout.logo.is_empty() { format!("\
\ - logo
", + logo", path=p, static_root_path=static_root_path, suffix=page.resource_suffix) } else { format!("\ -
\ - logo
", +
logo
", p, layout.logo) } diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 66236d7cb450..f9d00cad7170 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -183,16 +183,24 @@ nav.sub { } .logo-container { - height: 0; - padding-bottom: 50%; -} - -.sidebar img { + height: 100px; + width: 100px; + position: relative; margin: 20px auto; display: block; margin-top: 10px; } +.logo-container > img { + max-width: 100px; + max-height: 100px; + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + display: block; +} + .sidebar .location { border: 1px solid; font-size: 17px; @@ -1035,14 +1043,20 @@ span.since { padding: 0; } - .sidebar img { + .sidebar .logo-container { width: 35px; + height: 35px; margin-top: 5px; margin-bottom: 5px; float: left; margin-left: 50px; } + .sidebar .logo-container > img { + max-width: 35px; + max-height: 35px; + } + .sidebar-menu { position: fixed; z-index: 10; From 67ca448dac4ccf189e2c708be3f3569b70ee2698 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 29 Apr 2019 23:24:09 +0200 Subject: [PATCH 0051/3207] Improve file sidebar in source code view page on mobile --- src/librustdoc/html/static/rustdoc.css | 78 +++++++++++++++----------- 1 file changed, 45 insertions(+), 33 deletions(-) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 358549117a30..82ef6a410a30 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1232,6 +1232,39 @@ h4 > .important-traits { margin: 5px 0; } +#sidebar-toggle { + position: fixed; + top: 30px; + left: 300px; + z-index: 10; + padding: 3px; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; + cursor: pointer; + font-weight: bold; + transition: left .5s; + font-size: 1.2em; + border: 1px solid; + border-left: 0; +} +#source-sidebar { + position: fixed; + top: 0; + bottom: 0; + left: 0; + width: 300px; + z-index: 1; + overflow: auto; + transition: left .5s; + border-right: 1px solid; +} +#source-sidebar > .title { + font-size: 1.5em; + text-align: center; + border-bottom: 1px solid; + margin-bottom: 6px; +} + @media (max-width: 700px) { h4 > .important-traits { position: absolute; @@ -1307,6 +1340,18 @@ h4 > .important-traits { #all-types { margin: 10px; } + + #sidebar-toggle { + top: 100px; + width: 30px; + font-size: 1.5rem; + text-align: center; + padding: 0; + } + + #source-sidebar { + z-index: 11; + } } @@ -1516,39 +1561,6 @@ kbd { margin-bottom: 1em; } -#sidebar-toggle { - position: fixed; - top: 30px; - left: 300px; - z-index: 10; - padding: 3px; - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; - cursor: pointer; - font-weight: bold; - transition: left .5s; - font-size: 1.2em; - border: 1px solid; - border-left: 0; -} -#source-sidebar { - position: fixed; - top: 0; - bottom: 0; - left: 0; - width: 300px; - z-index: 1; - overflow: auto; - transition: left .5s; - border-right: 1px solid; -} -#source-sidebar > .title { - font-size: 1.5em; - text-align: center; - border-bottom: 1px solid; - margin-bottom: 6px; -} - div.children { padding-left: 27px; display: none; From 87d1c17683b7911522e3bcc223a308c82702f7d8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 29 Apr 2019 23:43:39 +0200 Subject: [PATCH 0052/3207] Cleanup media queries --- src/librustdoc/html/static/rustdoc.css | 363 ++++++++++++------------- 1 file changed, 179 insertions(+), 184 deletions(-) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 82ef6a410a30..70984ea3e72a 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -998,133 +998,6 @@ span.since { opacity: 1; } -/* Media Queries */ - -@media (max-width: 700px) { - body { - padding-top: 0px; - } - - .rustdoc > .sidebar { - height: 45px; - min-height: 40px; - margin: 0; - margin-left: -15px; - padding: 0 15px; - position: static; - z-index: 11; - } - - .sidebar > .location { - float: right; - margin: 0px; - margin-top: 2px; - padding: 3px 10px 1px 10px; - min-height: 39px; - background: inherit; - text-align: left; - font-size: 24px; - } - - .sidebar .location:empty { - padding: 0; - } - - .sidebar img { - width: 35px; - margin-top: 5px; - margin-bottom: 5px; - float: left; - margin-left: 50px; - } - - .sidebar-menu { - position: fixed; - z-index: 10; - font-size: 2rem; - cursor: pointer; - width: 45px; - left: 0; - text-align: center; - display: block; - border-bottom: 1px solid; - border-right: 1px solid; - height: 45px; - } - - .sidebar-elems { - position: fixed; - z-index: 1; - left: 0; - top: 45px; - bottom: 0; - overflow-y: auto; - border-right: 1px solid; - display: none; - } - - .sidebar > .block.version { - border-bottom: none; - margin-top: 12px; - } - - nav.sub { - width: calc(100% - 32px); - float: right; - } - - .content { - margin-left: 0px; - } - - #main { - margin-top: 45px; - padding: 0; - } - - .content .in-band { - width: 100%; - } - - .content h4 > .out-of-band { - position: inherit; - } - - .toggle-wrapper > .collapse-toggle { - left: 0px; - } - - .toggle-wrapper { - height: 1.5em; - } - - #search { - margin-left: 0; - } - - .content .impl-items .method, .content .impl-items > .type, .impl-items > .associatedconstant { - display: flex; - } - - .anchor { - display: none !important; - } - - h1.fqn { - overflow: initial; - } - - #main > .line-numbers { - margin-top: 0; - } -} - -@media print { - nav.sub, .content .out-of-band, .collapse-toggle { - display: none; - } -} - .information { position: absolute; left: -20px; @@ -1265,7 +1138,177 @@ h4 > .important-traits { margin-bottom: 6px; } +.theme-picker { + position: absolute; + left: 211px; + top: 19px; +} + +.theme-picker button { + outline: none; +} + +#settings-menu { + position: absolute; + right: 0; + top: 10px; + outline: none; +} + +#theme-picker, #settings-menu { + padding: 4px; + width: 27px; + height: 29px; + border: 1px solid; + border-radius: 3px; + cursor: pointer; +} + +#theme-choices { + display: none; + position: absolute; + left: 0; + top: 28px; + border: 1px solid; + border-radius: 3px; + z-index: 1; + cursor: pointer; +} + +#theme-choices > button { + border: none; + width: 100%; + padding: 4px; + text-align: center; + background: rgba(0,0,0,0); +} + +#theme-choices > button:not(:first-child) { + border-top: 1px solid; +} + +/* Media Queries */ + @media (max-width: 700px) { + body { + padding-top: 0px; + } + + .rustdoc > .sidebar { + height: 45px; + min-height: 40px; + margin: 0; + margin-left: -15px; + padding: 0 15px; + position: static; + z-index: 11; + } + + .sidebar > .location { + float: right; + margin: 0px; + margin-top: 2px; + padding: 3px 10px 1px 10px; + min-height: 39px; + background: inherit; + text-align: left; + font-size: 24px; + } + + .sidebar .location:empty { + padding: 0; + } + + .sidebar img { + width: 35px; + margin-top: 5px; + margin-bottom: 5px; + float: left; + margin-left: 50px; + } + + .sidebar-menu { + position: fixed; + z-index: 10; + font-size: 2rem; + cursor: pointer; + width: 45px; + left: 0; + text-align: center; + display: block; + border-bottom: 1px solid; + border-right: 1px solid; + height: 45px; + } + + .sidebar-elems { + position: fixed; + z-index: 1; + left: 0; + top: 45px; + bottom: 0; + overflow-y: auto; + border-right: 1px solid; + display: none; + } + + .sidebar > .block.version { + border-bottom: none; + margin-top: 12px; + } + + nav.sub { + width: calc(100% - 32px); + float: right; + } + + .content { + margin-left: 0px; + } + + #main { + margin-top: 45px; + padding: 0; + } + + .content .in-band { + width: 100%; + } + + .content h4 > .out-of-band { + position: inherit; + } + + .toggle-wrapper > .collapse-toggle { + left: 0px; + } + + .toggle-wrapper { + height: 1.5em; + } + + #search { + margin-left: 0; + } + + .content .impl-items .method, .content .impl-items > .type, .impl-items > .associatedconstant { + display: flex; + } + + .anchor { + display: none !important; + } + + h1.fqn { + overflow: initial; + } + + .theme-picker { + left: 10px; + top: 54px; + z-index: 1; + } + h4 > .important-traits { position: absolute; left: -22px; @@ -1352,8 +1395,17 @@ h4 > .important-traits { #source-sidebar { z-index: 11; } + + #main > .line-numbers { + margin-top: 0; + } } +@media print { + nav.sub, .content .out-of-band, .collapse-toggle { + display: none; + } +} @media (max-width: 416px) { #titles { @@ -1453,63 +1505,6 @@ kbd { cursor: default; } -.theme-picker { - position: absolute; - left: 211px; - top: 19px; -} - -.theme-picker button { - outline: none; -} - -#settings-menu { - position: absolute; - right: 0; - top: 10px; - outline: none; -} - -#theme-picker, #settings-menu { - padding: 4px; - width: 27px; - height: 29px; - border: 1px solid; - border-radius: 3px; - cursor: pointer; -} - -#theme-choices { - display: none; - position: absolute; - left: 0; - top: 28px; - border: 1px solid; - border-radius: 3px; - z-index: 1; - cursor: pointer; -} - -#theme-choices > button { - border: none; - width: 100%; - padding: 4px; - text-align: center; - background: rgba(0,0,0,0); -} - -#theme-choices > button:not(:first-child) { - border-top: 1px solid; -} - -@media (max-width: 700px) { - .theme-picker { - left: 10px; - top: 54px; - z-index: 1; - } -} - .hidden-by-impl-hider, .hidden-by-usual-hider { /* important because of conflicting rule for small screens */ From bd8885d340beb20ac1728d0bd7e64321da641b91 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Wed, 1 May 2019 22:23:07 +0200 Subject: [PATCH 0053/3207] Fall back to `/dev/urandom` on `EPERM` for `getrandom` This can happen because of seccomp or some VMs. Fixes #52609. --- src/libstd/sys/unix/rand.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs index 77f1439e17b1..71c62461ee9c 100644 --- a/src/libstd/sys/unix/rand.rs +++ b/src/libstd/sys/unix/rand.rs @@ -47,7 +47,12 @@ mod imp { let err = errno() as libc::c_int; if err == libc::EINTR { continue; - } else if err == libc::ENOSYS { + } else if err == libc::ENOSYS || err == libc::EPERM { + // Fall back to reading /dev/urandom if `getrandom` is not + // supported on the current kernel. + // + // Also fall back in case it is disabled by something like + // seccomp or inside of virtual machines. GETRANDOM_UNAVAILABLE.store(true, Ordering::Relaxed); return false; } else if err == libc::EAGAIN { From e2a25007beba16caa8653f1f3c35bcb7543d659e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 2 May 2019 23:31:50 +0200 Subject: [PATCH 0054/3207] Fix search sidebar width when no crate select is present --- src/librustdoc/html/static/rustdoc.css | 4 ++-- src/librustdoc/html/static/themes/dark.css | 7 ++++--- src/librustdoc/html/static/themes/light.css | 8 ++++---- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 53b08cf56978..778677b43708 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -658,18 +658,18 @@ a { transition: border-color 300ms ease; transition: border-radius 300ms ease-in-out; transition: box-shadow 300ms ease-in-out; - width: calc(100% - 32px); + width: 100%; } #crate-search + .search-input { border-radius: 0 1px 1px 0; + width: calc(100% - 32px); } .search-input:focus { border-radius: 2px; border: 0; outline: 0; - box-shadow: 0 0 8px #078dd8; } .search-results .desc { diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index f1255f522473..e44ae2ad10ce 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -164,20 +164,21 @@ a.test-arrow { color: #111; background-color: #f0f0f0; border-color: #000; + box-shadow: 0 0 0 1px #000, 0 0 0 2px transparent; } .search-input { color: #111; - box-shadow: 0 0 0 1px #000, 0 0 0 2px transparent; background-color: #f0f0f0; + box-shadow: 0 0 0 1px #000, 0 0 0 2px transparent; } .search-input:focus { border-color: #008dfd; } -#crate-search + .search-input { - box-shadow: 1px 0 0 1px #000, 0 0 0 2px transparent; +#crate-search + .search-input:focus { + box-shadow: 0 0 8px 4px #078dd8; } .module-item .stab { diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index c052e6b37ade..4c37000dde2c 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -164,21 +164,21 @@ a.test-arrow { color: #555; background-color: white; border-color: #e0e0e0; - box-shadow: 0px 0 0 1px #e0e0e0, 0 0 0 2px transparent; + box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent; } .search-input { color: #555; - box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent; background-color: white; + box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent; } .search-input:focus { border-color: #66afe9; } -#crate-search + .search-input { - box-shadow: 1px 0 0 1px #e0e0e0, 0 0 0 2px transparent; +#crate-search + .search-input:focus { + box-shadow: 0 0 8px #078dd8; } .module-item .stab { From 7b6ad606723d29b7b7f7316a019cb55c7ee48b5c Mon Sep 17 00:00:00 2001 From: Andrea Corradi Date: Fri, 3 May 2019 00:01:41 +0200 Subject: [PATCH 0055/3207] Add custom nth_back for Chain --- src/libcore/iter/adapters/chain.rs | 23 +++++++++++++++++++++++ src/libcore/tests/iter.rs | 16 ++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/libcore/iter/adapters/chain.rs b/src/libcore/iter/adapters/chain.rs index 76239ebc0aba..0b9f7f6b609e 100644 --- a/src/libcore/iter/adapters/chain.rs +++ b/src/libcore/iter/adapters/chain.rs @@ -207,6 +207,29 @@ impl DoubleEndedIterator for Chain where } } + #[inline] + fn nth_back(&mut self, mut n: usize) -> Option { + match self.state { + ChainState::Both | ChainState::Back => { + for x in self.b.by_ref().rev() { + if n == 0 { + return Some(x) + } + n -= 1; + } + if let ChainState::Both = self.state { + self.state = ChainState::Front; + } + } + ChainState::Front => {} + } + if let ChainState::Front = self.state { + self.a.nth_back(n) + } else { + None + } + } + fn try_rfold(&mut self, init: Acc, mut f: F) -> R where Self: Sized, F: FnMut(Acc, Self::Item) -> R, R: Try { diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 7dfb1adad9ee..449e339f89cc 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -103,6 +103,22 @@ fn test_iterator_chain_nth() { assert_eq!(it.next(), None); } +#[test] +fn test_iterator_chain_nth_back() { + let xs = [0, 1, 2, 3, 4, 5]; + let ys = [30, 40, 50, 60]; + let zs = []; + let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60]; + for (i, x) in expected.iter().rev().enumerate() { + assert_eq!(Some(x), xs.iter().chain(&ys).nth_back(i)); + } + assert_eq!(zs.iter().chain(&xs).nth_back(0), Some(&5)); + + let mut it = xs.iter().chain(&zs); + assert_eq!(it.nth_back(5), Some(&0)); + assert_eq!(it.next(), None); +} + #[test] fn test_iterator_chain_last() { let xs = [0, 1, 2, 3, 4, 5]; From 4d9b9e9038102ada95d1898d303038803d752f62 Mon Sep 17 00:00:00 2001 From: "@amit.chandra" <@amit.chandra> Date: Fri, 26 Apr 2019 19:53:18 +0530 Subject: [PATCH 0056/3207] wip nth_back on chunks Signed-off-by: wizAmit --- src/libcore/slice/mod.rs | 16 ++++++++++++++++ src/libcore/tests/slice.rs | 13 +++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 8731f4867535..049d38c158ce 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4152,6 +4152,22 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { Some(snd) } } + + #[inline] + fn nth_back(&mut self, n: usize) { + let (end, overflow) = self.v.len().overflowing_sub(n); + if end < self.v.len() || overflow { + self.v = &[]; + None + } else { + let start = match end.checked_sub(self.chunk_size) { + Some(sum) => cmp::min(self.v.len(), sum), + None => self.v.len(), + }; + let nth = &self.v[start..end]; + self.v = &self.v[end..]; + } + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index acf6b03791f0..0233b96d3a72 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -134,6 +134,19 @@ fn test_chunks_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_chunks_nth_back() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5]; + let mut c = v.chunks(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next().unwrap(), &[4, 5]); + + let v2: &[i32] = &[0, 1, 2, 3, 4]; + let mut c2 = v2.chunks(3); + assert_eq!(c2.nth_back(1).unwrap(), &[0, 1]); + assert_eq!(c2.next(), None); +} + #[test] fn test_chunks_last() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; From 73ca8bc140d4b0935ecb0199ea65723ec6a6791f Mon Sep 17 00:00:00 2001 From: "@amit.chandra" <@amit.chandra> Date: Wed, 1 May 2019 23:34:07 +0530 Subject: [PATCH 0057/3207] hopefully working nth_back on chunks Signed-off-by: wizAmit --- src/libcore/slice/mod.rs | 17 +++++++++-------- src/libcore/tests/slice.rs | 9 ++++++++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 049d38c158ce..00dbe7104d1a 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4154,18 +4154,19 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { } #[inline] - fn nth_back(&mut self, n: usize) { - let (end, overflow) = self.v.len().overflowing_sub(n); - if end < self.v.len() || overflow { - self.v = &[]; + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.v.len().overflowing_sub(n * self.chunk_size); + if overflow { + self.v = &mut []; None } else { let start = match end.checked_sub(self.chunk_size) { - Some(sum) => cmp::min(self.v.len(), sum), - None => self.v.len(), + Some(res) => cmp::min(self.v.len(), res), + None => 0, }; - let nth = &self.v[start..end]; - self.v = &self.v[end..]; + let nth_back = &self.v[start..end]; + self.v = &self.v[..start]; + Some(nth_back) } } } diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 0233b96d3a72..edea405fad79 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -139,12 +139,19 @@ fn test_chunks_nth_back() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; let mut c = v.chunks(2); assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); - assert_eq!(c.next().unwrap(), &[4, 5]); + assert_eq!(c.next().unwrap(), &[0, 1]); + assert_eq!(c.next(), None); let v2: &[i32] = &[0, 1, 2, 3, 4]; let mut c2 = v2.chunks(3); assert_eq!(c2.nth_back(1).unwrap(), &[0, 1]); assert_eq!(c2.next(), None); + assert_eq!(c2.next_back(), None); + + let v3: &[i32] = &[0, 1, 2, 3, 4]; + let mut c3 = v3.chunks(10); + assert_eq!(c3.nth_back(0).unwrap(), &[0, 1, 2, 3, 4]); + assert_eq!(c3.next(), None); } #[test] From ccb9dac5ed65341bf8d9ce01a83b9aad02f42526 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sat, 4 May 2019 23:48:57 +0900 Subject: [PATCH 0058/3207] Fix intra-doc link resolution failure on re-exporting libstd --- src/liballoc/alloc.rs | 18 +++++++++++++++ src/libcore/task/wake.rs | 23 +++++++++++++++++++ src/libstd/alloc.rs | 5 ++++ src/libstd/collections/hash/map.rs | 5 +++- src/libstd/error.rs | 18 +++++++++++++++ src/libstd/ffi/os_str.rs | 2 ++ src/libstd/fs.rs | 2 ++ src/libstd/io/buffered.rs | 2 +- src/libstd/net/addr.rs | 13 +++++++++++ src/libstd/sync/mutex.rs | 2 ++ src/libstd/sync/rwlock.rs | 2 ++ src/libstd/thread/mod.rs | 1 + .../rustdoc/intra-link-libstd-re-export.rs | 3 +++ 13 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 src/test/rustdoc/intra-link-libstd-re-export.rs diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index ddc6481eec78..41ff06d70ff0 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -37,6 +37,8 @@ extern "Rust" { /// /// Note: while this type is unstable, the functionality it provides can be /// accessed through the [free functions in `alloc`](index.html#functions). +/// +/// [`Alloc`]: trait.Alloc.html #[unstable(feature = "allocator_api", issue = "32838")] #[derive(Copy, Clone, Default, Debug)] pub struct Global; @@ -54,6 +56,10 @@ pub struct Global; /// /// See [`GlobalAlloc::alloc`]. /// +/// [`Global`]: struct.Global.html +/// [`Alloc`]: trait.Alloc.html +/// [`GlobalAlloc::alloc`]: trait.GlobalAlloc.html#tymethod.alloc +/// /// # Examples /// /// ``` @@ -87,6 +93,10 @@ pub unsafe fn alloc(layout: Layout) -> *mut u8 { /// # Safety /// /// See [`GlobalAlloc::dealloc`]. +/// +/// [`Global`]: struct.Global.html +/// [`Alloc`]: trait.Alloc.html +/// [`GlobalAlloc::dealloc`]: trait.GlobalAlloc.html#tymethod.dealloc #[stable(feature = "global_alloc", since = "1.28.0")] #[inline] pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { @@ -105,6 +115,10 @@ pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) { /// # Safety /// /// See [`GlobalAlloc::realloc`]. +/// +/// [`Global`]: struct.Global.html +/// [`Alloc`]: trait.Alloc.html +/// [`GlobalAlloc::realloc`]: trait.GlobalAlloc.html#method.realloc #[stable(feature = "global_alloc", since = "1.28.0")] #[inline] pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { @@ -124,6 +138,10 @@ pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 /// /// See [`GlobalAlloc::alloc_zeroed`]. /// +/// [`Global`]: struct.Global.html +/// [`Alloc`]: trait.Alloc.html +/// [`GlobalAlloc::alloc_zeroed`]: trait.GlobalAlloc.html#method.alloc_zeroed +/// /// # Examples /// /// ``` diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs index b4e912498320..a6d611d2e93c 100644 --- a/src/libcore/task/wake.rs +++ b/src/libcore/task/wake.rs @@ -10,6 +10,8 @@ use crate::marker::{PhantomData, Unpin}; /// /// It consists of a data pointer and a [virtual function pointer table (vtable)][vtable] that /// customizes the behavior of the `RawWaker`. +/// +/// [`Waker`]: struct.Waker.html #[derive(PartialEq, Debug)] #[stable(feature = "futures_api", since = "1.36.0")] pub struct RawWaker { @@ -55,6 +57,8 @@ impl RawWaker { /// pointer of a properly constructed [`RawWaker`] object from inside the /// [`RawWaker`] implementation. Calling one of the contained functions using /// any other `data` pointer will cause undefined behavior. +/// +/// [`RawWaker`]: struct.RawWaker.html #[stable(feature = "futures_api", since = "1.36.0")] #[derive(PartialEq, Copy, Clone, Debug)] pub struct RawWakerVTable { @@ -65,6 +69,9 @@ pub struct RawWakerVTable { /// required for this additional instance of a [`RawWaker`] and associated /// task. Calling `wake` on the resulting [`RawWaker`] should result in a wakeup /// of the same task that would have been awoken by the original [`RawWaker`]. + /// + /// [`Waker`]: struct.Waker.html + /// [`RawWaker`]: struct.RawWaker.html clone: unsafe fn(*const ()) -> RawWaker, /// This function will be called when `wake` is called on the [`Waker`]. @@ -73,6 +80,9 @@ pub struct RawWakerVTable { /// The implementation of this function must make sure to release any /// resources that are associated with this instance of a [`RawWaker`] and /// associated task. + /// + /// [`Waker`]: struct.Waker.html + /// [`RawWaker`]: struct.RawWaker.html wake: unsafe fn(*const ()), /// This function will be called when `wake_by_ref` is called on the [`Waker`]. @@ -80,6 +90,9 @@ pub struct RawWakerVTable { /// /// This function is similar to `wake`, but must not consume the provided data /// pointer. + /// + /// [`Waker`]: struct.Waker.html + /// [`RawWaker`]: struct.RawWaker.html wake_by_ref: unsafe fn(*const ()), /// This function gets called when a [`RawWaker`] gets dropped. @@ -87,6 +100,8 @@ pub struct RawWakerVTable { /// The implementation of this function must make sure to release any /// resources that are associated with this instance of a [`RawWaker`] and /// associated task. + /// + /// [`RawWaker`]: struct.RawWaker.html drop: unsafe fn(*const ()), } @@ -128,6 +143,9 @@ impl RawWakerVTable { /// The implementation of this function must make sure to release any /// resources that are associated with this instance of a [`RawWaker`] and /// associated task. + /// + /// [`Waker`]: struct.Waker.html + /// [`RawWaker`]: struct.RawWaker.html #[rustc_promotable] #[cfg_attr(stage0, unstable(feature = "futures_api_const_fn_ptr", issue = "50547"))] #[cfg_attr(not(stage0), stable(feature = "futures_api", since = "1.36.0"))] @@ -201,6 +219,8 @@ impl fmt::Debug for Context<'_> { /// executor-specific wakeup behavior. /// /// Implements [`Clone`], [`Send`], and [`Sync`]. +/// +/// [`RawWaker`]: struct.RawWaker.html #[repr(transparent)] #[stable(feature = "futures_api", since = "1.36.0")] pub struct Waker { @@ -266,6 +286,9 @@ impl Waker { /// The behavior of the returned `Waker` is undefined if the contract defined /// in [`RawWaker`]'s and [`RawWakerVTable`]'s documentation is not upheld. /// Therefore this method is unsafe. + /// + /// [`RawWaker`]: struct.RawWaker.html + /// [`RawWakerVTable`]: struct.RawWakerVTable.html #[inline] #[stable(feature = "futures_api", since = "1.36.0")] pub unsafe fn from_raw(waker: RawWaker) -> Waker { diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index 4241f47b661d..ff52974775b0 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -173,6 +173,9 @@ static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut()); /// about the allocation that failed. /// /// The allocation error hook is a global resource. +/// +/// [`set_alloc_error_hook`]: fn.set_alloc_error_hook.html +/// [`take_alloc_error_hook`]: fn.take_alloc_error_hook.html #[unstable(feature = "alloc_error_hook", issue = "51245")] pub fn set_alloc_error_hook(hook: fn(Layout)) { HOOK.store(hook as *mut (), Ordering::SeqCst); @@ -183,6 +186,8 @@ pub fn set_alloc_error_hook(hook: fn(Layout)) { /// *See also the function [`set_alloc_error_hook`].* /// /// If no custom hook is registered, the default hook will be returned. +/// +/// [`set_alloc_error_hook`]: fn.set_alloc_error_hook.html #[unstable(feature = "alloc_error_hook", issue = "51245")] pub fn take_alloc_error_hook() -> fn(Layout) { let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst); diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index f9fb392f9f52..af4f911a7842 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -2492,7 +2492,10 @@ impl DefaultHasher { #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] impl Default for DefaultHasher { - /// Creates a new `DefaultHasher` using [`new`][DefaultHasher::new]. + // FIXME: here should link `new` to [DefaultHasher::new], but it occurs intra-doc link + // resolution failure when re-exporting libstd items. When #56922 fixed, + // link `new` to [DefaultHasher::new] again. + /// Creates a new `DefaultHasher` using `new`. /// See its documentation for more. fn default() -> DefaultHasher { DefaultHasher::new() diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 081fff0562b1..71227c31c553 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -207,6 +207,8 @@ pub trait Error: Debug + Display { impl<'a, E: Error + 'a> From for Box { /// Converts a type of [`Error`] into a box of dyn [`Error`]. /// + /// [`Error`]: ../error/trait.Error.html + /// /// # Examples /// /// ``` @@ -244,6 +246,8 @@ impl<'a, E: Error + Send + Sync + 'a> From for Box From for Box for Box { /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// + /// [`Error`]: ../error/trait.Error.html + /// /// # Examples /// /// ``` @@ -318,6 +324,8 @@ impl From for Box { impl From for Box { /// Converts a [`String`] into a box of dyn [`Error`]. /// + /// [`Error`]: ../error/trait.Error.html + /// /// # Examples /// /// ``` @@ -339,6 +347,8 @@ impl From for Box { impl<'a> From<&str> for Box { /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// + /// [`Error`]: ../error/trait.Error.html + /// /// # Examples /// /// ``` @@ -359,6 +369,8 @@ impl<'a> From<&str> for Box { impl From<&str> for Box { /// Converts a [`str`] into a box of dyn [`Error`]. /// + /// [`Error`]: ../error/trait.Error.html + /// /// # Examples /// /// ``` @@ -378,6 +390,9 @@ impl From<&str> for Box { impl<'a, 'b> From> for Box { /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// + /// [`Cow`]: ../borrow/enum.Cow.html + /// [`Error`]: ../error/trait.Error.html + /// /// # Examples /// /// ``` @@ -399,6 +414,9 @@ impl<'a, 'b> From> for Box { impl<'a> From> for Box { /// Converts a [`Cow`] into a box of dyn [`Error`]. /// + /// [`Cow`]: ../borrow/enum.Cow.html + /// [`Error`]: ../error/trait.Error.html + /// /// # Examples /// /// ``` diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 13aee783750f..c7c5849a00fa 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -351,6 +351,8 @@ impl From for OsString { /// Converts a [`String`] into a [`OsString`]. /// /// The conversion copies the data, and includes an allocation on the heap. + /// + /// [`OsString`]: ../../std/ffi/struct.OsString.html fn from(s: String) -> OsString { OsString { inner: Buf::from_string(s) } } diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 991b45fd4a2e..616b5eb836ff 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -1812,6 +1812,8 @@ pub fn canonicalize>(path: P) -> io::Result { /// function.) /// * `path` already exists. /// +/// [`create_dir_all`]: fn.create_dir_all.html +/// /// # Examples /// /// ```no_run diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 5be2687d8f5f..e309f81192cf 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -754,7 +754,7 @@ impl fmt::Display for IntoInnerError { /// completed, rather than the entire buffer at once. Enter `LineWriter`. It /// does exactly that. /// -/// Like [`BufWriter`], a `LineWriter`’s buffer will also be flushed when the +/// Like [`BufWriter`][bufwriter], a `LineWriter`’s buffer will also be flushed when the /// `LineWriter` goes out of scope or when its internal buffer is full. /// /// [bufwriter]: struct.BufWriter.html diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index ec54d8a042a3..b3f0508221a5 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -546,6 +546,9 @@ impl FromInner for SocketAddrV6 { #[stable(feature = "ip_from_ip", since = "1.16.0")] impl From for SocketAddr { /// Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`]. + /// + /// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html + /// [`SocketAddr::V4`]: ../../std/net/enum.SocketAddr.html#variant.V4 fn from(sock4: SocketAddrV4) -> SocketAddr { SocketAddr::V4(sock4) } @@ -554,6 +557,9 @@ impl From for SocketAddr { #[stable(feature = "ip_from_ip", since = "1.16.0")] impl From for SocketAddr { /// Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`]. + /// + /// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html + /// [`SocketAddr::V6`]: ../../std/net/enum.SocketAddr.html#variant.V6 fn from(sock6: SocketAddrV6) -> SocketAddr { SocketAddr::V6(sock6) } @@ -567,6 +573,13 @@ impl> From<(I, u16)> for SocketAddr { /// and creates a [`SocketAddr::V6`] for a [`IpAddr::V6`]. /// /// `u16` is treated as port of the newly created [`SocketAddr`]. + /// + /// [`IpAddr`]: ../../std/net/enum.IpAddr.html + /// [`IpAddr::V4`]: ../../std/net/enum.IpAddr.html#variant.V4 + /// [`IpAddr::V6`]: ../../std/net/enum.IpAddr.html#variant.V6 + /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html + /// [`SocketAddr::V4`]: ../../std/net/enum.SocketAddr.html#variant.V4 + /// [`SocketAddr::V6`]: ../../std/net/enum.SocketAddr.html#variant.V6 fn from(pieces: (I, u16)) -> SocketAddr { SocketAddr::new(pieces.0.into(), pieces.1) } diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 11ac34fcb24f..87c2318a9377 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -376,6 +376,8 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Mutex { impl From for Mutex { /// Creates a new mutex in an unlocked state ready for use. /// This is equivalent to [`Mutex::new`]. + /// + /// [`Mutex::new`]: ../../std/sync/struct.Mutex.html#method.new fn from(t: T) -> Self { Mutex::new(t) } diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 1299a7440956..b1b56f321fc6 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -453,6 +453,8 @@ impl Default for RwLock { impl From for RwLock { /// Creates a new instance of an `RwLock` which is unlocked. /// This is equivalent to [`RwLock::new`]. + /// + /// [`RwLock::new`]: ../../std/sync/struct.RwLock.html#method.new fn from(t: T) -> Self { RwLock::new(t) } diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index fce28ffd9c38..35de4f4008b6 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -443,6 +443,7 @@ impl Builder { /// [`Builder::spawn`]: ../../std/thread/struct.Builder.html#method.spawn /// [`io::Result`]: ../../std/io/type.Result.html /// [`JoinHandle`]: ../../std/thread/struct.JoinHandle.html + /// [`JoinHandle::join`]: ../../std/thread/struct.JoinHandle.html#method.join #[unstable(feature = "thread_spawn_unchecked", issue = "55132")] pub unsafe fn spawn_unchecked<'a, F, T>(self, f: F) -> io::Result> where F: FnOnce() -> T, F: Send + 'a, T: Send + 'a diff --git a/src/test/rustdoc/intra-link-libstd-re-export.rs b/src/test/rustdoc/intra-link-libstd-re-export.rs new file mode 100644 index 000000000000..6f239292ec20 --- /dev/null +++ b/src/test/rustdoc/intra-link-libstd-re-export.rs @@ -0,0 +1,3 @@ +#![deny(intra_doc_link_resolution_failure)] + +pub use std::*; From 5eb0e08d0feab69f9e5f3b6881bde328a9105c96 Mon Sep 17 00:00:00 2001 From: Tim Vermeulen Date: Sun, 5 May 2019 11:21:30 +0200 Subject: [PATCH 0059/3207] Implement nth_back for RChunks(Exact)(Mut) --- src/libcore/slice/mod.rs | 72 ++++++++++++++++++++++++++++++++++++++ src/libcore/tests/slice.rs | 52 +++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 8731f4867535..f7a7976faecd 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4643,6 +4643,23 @@ impl<'a, T> DoubleEndedIterator for RChunks<'a, T> { Some(fst) } } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &[]; + None + } else { + // can't underflow because `n < len` + let offset_from_end = (len - 1 - n) * self.chunk_size; + let end = self.v.len() - offset_from_end; + let start = end.saturating_sub(self.chunk_size); + let nth_back = &self.v[start..end]; + self.v = &self.v[end..]; + Some(nth_back) + } + } } #[stable(feature = "rchunks", since = "1.31.0")] @@ -4768,6 +4785,24 @@ impl<'a, T> DoubleEndedIterator for RChunksMut<'a, T> { Some(head) } } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &mut []; + None + } else { + // can't underflow because `n < len` + let offset_from_end = (len - 1 - n) * self.chunk_size; + let end = self.v.len() - offset_from_end; + let start = end.saturating_sub(self.chunk_size); + let (tmp, tail) = mem::replace(&mut self.v, &mut []).split_at_mut(end); + let (_, nth_back) = tmp.split_at_mut(start); + self.v = tail; + Some(nth_back) + } + } } #[stable(feature = "rchunks", since = "1.31.0")] @@ -4892,6 +4927,24 @@ impl<'a, T> DoubleEndedIterator for RChunksExact<'a, T> { Some(fst) } } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &[]; + None + } else { + // now that we know that `n` corresponds to a chunk, + // none of these operations can underflow/overflow + let offset = (len - n) * self.chunk_size; + let start = self.v.len() - offset; + let end = start + self.chunk_size; + let nth_back = &self.v[start..end]; + self.v = &self.v[end..]; + Some(nth_back) + } + } } #[stable(feature = "rchunks", since = "1.31.0")] @@ -5010,6 +5063,25 @@ impl<'a, T> DoubleEndedIterator for RChunksExactMut<'a, T> { Some(head) } } + + #[inline] + fn nth_back(&mut self, n: usize) -> Option { + let len = self.len(); + if n >= len { + self.v = &mut []; + None + } else { + // now that we know that `n` corresponds to a chunk, + // none of these operations can underflow/overflow + let offset = (len - n) * self.chunk_size; + let start = self.v.len() - offset; + let end = start + self.chunk_size; + let (tmp, tail) = mem::replace(&mut self.v, &mut []).split_at_mut(end); + let (_, nth_back) = tmp.split_at_mut(start); + self.v = tail; + Some(nth_back) + } + } } #[stable(feature = "rchunks", since = "1.31.0")] diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index acf6b03791f0..cd520a052a00 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -356,6 +356,19 @@ fn test_rchunks_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_rchunks_nth_back() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5]; + let mut c = v.rchunks(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next_back().unwrap(), &[4, 5]); + + let v2: &[i32] = &[0, 1, 2, 3, 4]; + let mut c2 = v2.rchunks(3); + assert_eq!(c2.nth_back(1).unwrap(), &[2, 3, 4]); + assert_eq!(c2.next_back(), None); +} + #[test] fn test_rchunks_last() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; @@ -407,6 +420,19 @@ fn test_rchunks_mut_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_rchunks_mut_nth_back() { + let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; + let mut c = v.rchunks_mut(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next_back().unwrap(), &[4, 5]); + + let v2: &mut [i32] = &mut [0, 1, 2, 3, 4]; + let mut c2 = v2.rchunks_mut(3); + assert_eq!(c2.nth_back(1).unwrap(), &[2, 3, 4]); + assert_eq!(c2.next_back(), None); +} + #[test] fn test_rchunks_mut_last() { let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; @@ -460,6 +486,19 @@ fn test_rchunks_exact_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_rchunks_exact_nth_back() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5]; + let mut c = v.rchunks_exact(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next_back().unwrap(), &[4, 5]); + + let v2: &[i32] = &[0, 1, 2, 3, 4, 5, 6]; + let mut c2 = v2.rchunks_exact(3); + assert_eq!(c2.nth_back(1).unwrap(), &[4, 5, 6]); + assert_eq!(c2.next(), None); +} + #[test] fn test_rchunks_exact_last() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; @@ -518,6 +557,19 @@ fn test_rchunks_exact_mut_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_rchunks_exact_mut_nth_back() { + let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; + let mut c = v.rchunks_exact_mut(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next_back().unwrap(), &[4, 5]); + + let v2: &mut [i32] = &mut [0, 1, 2, 3, 4, 5, 6]; + let mut c2 = v2.rchunks_exact_mut(3); + assert_eq!(c2.nth_back(1).unwrap(), &[4, 5, 6]); + assert_eq!(c2.next(), None); +} + #[test] fn test_rchunks_exact_mut_last() { let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; From af6ace62090aa03617fee2ef185363702634cff0 Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Mon, 6 May 2019 14:54:27 +0200 Subject: [PATCH 0060/3207] convert custom try macro to `?` resolves #60580 --- src/libstd/sys/redox/process.rs | 49 +++++++++------------ src/libstd/sys/unix/process/process_unix.rs | 27 +++++------- 2 files changed, 31 insertions(+), 45 deletions(-) diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs index 8e6f50773abf..5039c2e3ddfb 100644 --- a/src/libstd/sys/redox/process.rs +++ b/src/libstd/sys/redox/process.rs @@ -254,44 +254,37 @@ impl Command { // have the drop glue anyway because this code never returns (the // child will either exec() or invoke syscall::exit) unsafe fn do_exec(&mut self, stdio: ChildPipes) -> io::Error { - macro_rules! t { - ($e:expr) => (match $e { - Ok(e) => e, - Err(e) => return e, - }) - } - if let Some(fd) = stdio.stderr.fd() { - t!(cvt(syscall::dup2(fd, 2, &[]))); - let mut flags = t!(cvt(syscall::fcntl(2, syscall::F_GETFD, 0))); + cvt(syscall::dup2(fd, 2, &[]))?; + let mut flags = cvt(syscall::fcntl(2, syscall::F_GETFD, 0))?; flags &= ! syscall::O_CLOEXEC; - t!(cvt(syscall::fcntl(2, syscall::F_SETFD, flags))); + cvt(syscall::fcntl(2, syscall::F_SETFD, flags))?; } if let Some(fd) = stdio.stdout.fd() { - t!(cvt(syscall::dup2(fd, 1, &[]))); - let mut flags = t!(cvt(syscall::fcntl(1, syscall::F_GETFD, 0))); + cvt(syscall::dup2(fd, 1, &[]))?; + let mut flags = cvt(syscall::fcntl(1, syscall::F_GETFD, 0))?; flags &= ! syscall::O_CLOEXEC; - t!(cvt(syscall::fcntl(1, syscall::F_SETFD, flags))); + cvt(syscall::fcntl(1, syscall::F_SETFD, flags))?; } if let Some(fd) = stdio.stdin.fd() { - t!(cvt(syscall::dup2(fd, 0, &[]))); - let mut flags = t!(cvt(syscall::fcntl(0, syscall::F_GETFD, 0))); + cvt(syscall::dup2(fd, 0, &[]))?; + let mut flags = cvt(syscall::fcntl(0, syscall::F_GETFD, 0))?; flags &= ! syscall::O_CLOEXEC; - t!(cvt(syscall::fcntl(0, syscall::F_SETFD, flags))); + cvt(syscall::fcntl(0, syscall::F_SETFD, flags))?; } if let Some(g) = self.gid { - t!(cvt(syscall::setregid(g as usize, g as usize))); + cvt(syscall::setregid(g as usize, g as usize))?; } if let Some(u) = self.uid { - t!(cvt(syscall::setreuid(u as usize, u as usize))); + cvt(syscall::setreuid(u as usize, u as usize))?; } if let Some(ref cwd) = self.cwd { - t!(cvt(syscall::chdir(cwd))); + cvt(syscall::chdir(cwd))?; } for callback in self.closures.iter_mut() { - t!(callback()); + callback()?; } self.env.apply(); @@ -313,7 +306,7 @@ impl Command { }; let mut file = if let Some(program) = program { - t!(File::open(program.as_os_str())) + File::open(program.as_os_str())? } else { return io::Error::from_raw_os_error(syscall::ENOENT); }; @@ -327,7 +320,7 @@ impl Command { let mut shebang = [0; 2]; let mut read = 0; loop { - match t!(reader.read(&mut shebang[read..])) { + match reader.read(&mut shebang[read..])? { 0 => break, n => read += n, } @@ -338,9 +331,9 @@ impl Command { // First of all, since we'll be passing another file to // fexec(), we need to manually check that we have permission // to execute this file: - let uid = t!(cvt(syscall::getuid())); - let gid = t!(cvt(syscall::getgid())); - let meta = t!(file.metadata()); + let uid = cvt(syscall::getuid())?; + let gid = cvt(syscall::getgid())?; + let meta = file.metadata()?; let mode = if uid == meta.uid() as usize { meta.mode() >> 3*2 & 0o7 @@ -355,7 +348,7 @@ impl Command { // Second of all, we need to actually read which interpreter it wants let mut interpreter = Vec::new(); - t!(reader.read_until(b'\n', &mut interpreter)); + reader.read_until(b'\n', &mut interpreter)?; // Pop one trailing newline, if any if interpreter.ends_with(&[b'\n']) { interpreter.pop().unwrap(); @@ -373,11 +366,11 @@ impl Command { }; if let Some(ref interpreter) = interpreter { let path: &OsStr = OsStr::from_bytes(&interpreter); - file = t!(File::open(path)); + file = File::open(path)?; args.push([interpreter.as_ptr() as usize, interpreter.len()]); } else { - t!(file.seek(SeekFrom::Start(0))); + file.seek(SeekFrom::Start(0))?; } args.push([self.program.as_ptr() as usize, self.program.len()]); diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index 220b1fd45313..07f813315e8c 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -167,26 +167,19 @@ impl Command { ) -> io::Error { use crate::sys::{self, cvt_r}; - macro_rules! t { - ($e:expr) => (match $e { - Ok(e) => e, - Err(e) => return e, - }) - } - if let Some(fd) = stdio.stdin.fd() { - t!(cvt_r(|| libc::dup2(fd, libc::STDIN_FILENO))); + cvt_r(|| libc::dup2(fd, libc::STDIN_FILENO))?; } if let Some(fd) = stdio.stdout.fd() { - t!(cvt_r(|| libc::dup2(fd, libc::STDOUT_FILENO))); + cvt_r(|| libc::dup2(fd, libc::STDOUT_FILENO))?; } if let Some(fd) = stdio.stderr.fd() { - t!(cvt_r(|| libc::dup2(fd, libc::STDERR_FILENO))); + cvt_r(|| libc::dup2(fd, libc::STDERR_FILENO))?; } if cfg!(not(any(target_os = "l4re"))) { if let Some(u) = self.get_gid() { - t!(cvt(libc::setgid(u as gid_t))); + cvt(libc::setgid(u as gid_t))?; } if let Some(u) = self.get_uid() { // When dropping privileges from root, the `setgroups` call @@ -198,11 +191,11 @@ impl Command { // privilege dropping function. let _ = libc::setgroups(0, ptr::null()); - t!(cvt(libc::setuid(u as uid_t))); + cvt(libc::setuid(u as uid_t))?; } } if let Some(ref cwd) = *self.get_cwd() { - t!(cvt(libc::chdir(cwd.as_ptr()))); + cvt(libc::chdir(cwd.as_ptr()))?; } // emscripten has no signal support. @@ -225,10 +218,10 @@ impl Command { 0, mem::size_of::()); } else { - t!(cvt(libc::sigemptyset(&mut set))); + cvt(libc::sigemptyset(&mut set))?; } - t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set, - ptr::null_mut()))); + cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set, + ptr::null_mut()))?; let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL); if ret == libc::SIG_ERR { return io::Error::last_os_error() @@ -236,7 +229,7 @@ impl Command { } for callback in self.get_closures().iter_mut() { - t!(callback()); + callback()?; } // Although we're performing an exec here we may also return with an From 5458b651b1ecad5cc334b494209352ac935360ce Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Mon, 6 May 2019 15:40:34 +0200 Subject: [PATCH 0061/3207] use exhaustive_patterns to be able to use `?` --- src/libstd/sys/redox/process.rs | 16 +++++++++------- src/libstd/sys/unix/process/process_unix.rs | 11 ++++++----- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs index 5039c2e3ddfb..2a553b2c93bd 100644 --- a/src/libstd/sys/redox/process.rs +++ b/src/libstd/sys/redox/process.rs @@ -150,7 +150,7 @@ impl Command { match cvt(syscall::clone(0))? { 0 => { drop(input); - let err = self.do_exec(theirs); + let Err(err) = self.do_exec(theirs); let errno = err.raw_os_error().unwrap_or(syscall::EINVAL) as u32; let bytes = [ (errno >> 24) as u8, @@ -218,7 +218,10 @@ impl Command { } match self.setup_io(default, true) { - Ok((_, theirs)) => unsafe { self.do_exec(theirs) }, + Ok((_, theirs)) => unsafe { + let Err(e) = self.do_exec(theirs); + e + }, Err(e) => e, } } @@ -253,7 +256,7 @@ impl Command { // allocation). Instead we just close it manually. This will never // have the drop glue anyway because this code never returns (the // child will either exec() or invoke syscall::exit) - unsafe fn do_exec(&mut self, stdio: ChildPipes) -> io::Error { + unsafe fn do_exec(&mut self, stdio: ChildPipes) -> Result { if let Some(fd) = stdio.stderr.fd() { cvt(syscall::dup2(fd, 2, &[]))?; let mut flags = cvt(syscall::fcntl(2, syscall::F_GETFD, 0))?; @@ -308,7 +311,7 @@ impl Command { let mut file = if let Some(program) = program { File::open(program.as_os_str())? } else { - return io::Error::from_raw_os_error(syscall::ENOENT); + return Err(io::Error::from_raw_os_error(syscall::ENOENT)); }; // Push all the arguments @@ -343,7 +346,7 @@ impl Command { meta.mode() & 0o7 }; if mode & 1 == 0 { - return io::Error::from_raw_os_error(syscall::EPERM); + return Err(io::Error::from_raw_os_error(syscall::EPERM)); } // Second of all, we need to actually read which interpreter it wants @@ -389,13 +392,12 @@ impl Command { } if let Err(err) = syscall::fexec(file.as_raw_fd(), &args, &vars) { - io::Error::from_raw_os_error(err.errno as i32) + Err(io::Error::from_raw_os_error(err.errno as i32)) } else { panic!("return from exec without err"); } } - fn setup_io(&self, default: Stdio, needs_stdin: bool) -> io::Result<(StdioPipes, ChildPipes)> { let null = Stdio::Null; diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index 07f813315e8c..80fe763aecc8 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -47,7 +47,7 @@ impl Command { match result { 0 => { drop(input); - let err = self.do_exec(theirs, envp.as_ref()); + let Err(err) = self.do_exec(theirs, envp.as_ref()); let errno = err.raw_os_error().unwrap_or(libc::EINVAL) as u32; let bytes = [ (errno >> 24) as u8, @@ -123,7 +123,8 @@ impl Command { // environment lock before we try to exec. let _lock = sys::os::env_lock(); - self.do_exec(theirs, envp.as_ref()) + let Err(e) = self.do_exec(theirs, envp.as_ref()); + e } } Err(e) => e, @@ -164,7 +165,7 @@ impl Command { &mut self, stdio: ChildPipes, maybe_envp: Option<&CStringArray> - ) -> io::Error { + ) -> Result { use crate::sys::{self, cvt_r}; if let Some(fd) = stdio.stdin.fd() { @@ -224,7 +225,7 @@ impl Command { ptr::null_mut()))?; let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL); if ret == libc::SIG_ERR { - return io::Error::last_os_error() + return Err(io::Error::last_os_error()) } } @@ -254,7 +255,7 @@ impl Command { } libc::execvp(self.get_argv()[0], self.get_argv().as_ptr()); - io::Error::last_os_error() + Err(io::Error::last_os_error()) } #[cfg(not(any(target_os = "macos", target_os = "freebsd", From 20a5aa302e786acba8f845e326e226f16ca56afb Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Wed, 17 Apr 2019 20:17:12 -0500 Subject: [PATCH 0062/3207] set the default edition when pre-parsing a doctest --- src/librustdoc/config.rs | 25 ++++++------ src/librustdoc/externalfiles.rs | 9 +++-- src/librustdoc/html/markdown.rs | 54 +++++++++++++------------ src/librustdoc/html/render.rs | 18 ++++++--- src/librustdoc/lib.rs | 11 +++-- src/librustdoc/markdown.rs | 12 ++++-- src/librustdoc/test.rs | 8 +++- src/tools/error_index_generator/main.rs | 4 +- 8 files changed, 86 insertions(+), 55 deletions(-) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 72421c9decc6..0a403f61e9c2 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -386,18 +386,6 @@ impl Options { } } - let mut id_map = html::markdown::IdMap::new(); - id_map.populate(html::render::initial_ids()); - let external_html = match ExternalHtml::load( - &matches.opt_strs("html-in-header"), - &matches.opt_strs("html-before-content"), - &matches.opt_strs("html-after-content"), - &matches.opt_strs("markdown-before-content"), - &matches.opt_strs("markdown-after-content"), &diag, &mut id_map) { - Some(eh) => eh, - None => return Err(3), - }; - let edition = matches.opt_str("edition").unwrap_or("2015".to_string()); let edition = match edition.parse() { Ok(e) => e, @@ -407,6 +395,19 @@ impl Options { } }; + let mut id_map = html::markdown::IdMap::new(); + id_map.populate(html::render::initial_ids()); + let external_html = match ExternalHtml::load( + &matches.opt_strs("html-in-header"), + &matches.opt_strs("html-before-content"), + &matches.opt_strs("html-after-content"), + &matches.opt_strs("markdown-before-content"), + &matches.opt_strs("markdown-after-content"), + &diag, &mut id_map, edition) { + Some(eh) => eh, + None => return Err(3), + }; + match matches.opt_str("r").as_ref().map(|s| &**s) { Some("rust") | None => {} Some(s) => { diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs index 0378b12662da..d604ba11d418 100644 --- a/src/librustdoc/externalfiles.rs +++ b/src/librustdoc/externalfiles.rs @@ -3,6 +3,7 @@ use std::path::Path; use std::str; use errors; use crate::syntax::feature_gate::UnstableFeatures; +use crate::syntax::edition::Edition; use crate::html::markdown::{IdMap, ErrorCodes, Markdown}; use std::cell::RefCell; @@ -23,7 +24,7 @@ pub struct ExternalHtml { impl ExternalHtml { pub fn load(in_header: &[String], before_content: &[String], after_content: &[String], md_before_content: &[String], md_after_content: &[String], diag: &errors::Handler, - id_map: &mut IdMap) + id_map: &mut IdMap, edition: Edition) -> Option { let codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()); load_external_files(in_header, diag) @@ -34,7 +35,8 @@ impl ExternalHtml { .and_then(|(ih, bc)| load_external_files(md_before_content, diag) .map(|m_bc| (ih, - format!("{}{}", bc, Markdown(&m_bc, &[], RefCell::new(id_map), codes)))) + format!("{}{}", bc, Markdown(&m_bc, &[], RefCell::new(id_map), + codes, edition)))) ) .and_then(|(ih, bc)| load_external_files(after_content, diag) @@ -43,7 +45,8 @@ impl ExternalHtml { .and_then(|(ih, bc, ac)| load_external_files(md_after_content, diag) .map(|m_ac| (ih, bc, - format!("{}{}", ac, Markdown(&m_ac, &[], RefCell::new(id_map), codes)))) + format!("{}{}", ac, Markdown(&m_ac, &[], RefCell::new(id_map), + codes, edition)))) ) .map(|(ih, bc, ac)| ExternalHtml { diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index a3b041c6954c..5f450fcf6fca 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -42,14 +42,21 @@ fn opts() -> Options { /// A unit struct which has the `fmt::Display` trait implemented. When /// formatted, this struct will emit the HTML corresponding to the rendered /// version of the contained markdown string. -/// The second parameter is a list of link replacements +/// +/// The second parameter is a list of link replacements. +/// +/// The third is the current list of used header IDs. +/// +/// The fourth is whether to allow the use of explicit error codes in doctest lang strings. +/// +/// The fifth is what default edition to use when parsing doctests (to add a `fn main`). pub struct Markdown<'a>( - pub &'a str, pub &'a [(String, String)], pub RefCell<&'a mut IdMap>, pub ErrorCodes); + pub &'a str, pub &'a [(String, String)], pub RefCell<&'a mut IdMap>, pub ErrorCodes, pub Edition); /// A unit struct like `Markdown`, that renders the markdown with a /// table of contents. -pub struct MarkdownWithToc<'a>(pub &'a str, pub RefCell<&'a mut IdMap>, pub ErrorCodes); +pub struct MarkdownWithToc<'a>(pub &'a str, pub RefCell<&'a mut IdMap>, pub ErrorCodes, pub Edition); /// A unit struct like `Markdown`, that renders the markdown escaping HTML tags. -pub struct MarkdownHtml<'a>(pub &'a str, pub RefCell<&'a mut IdMap>, pub ErrorCodes); +pub struct MarkdownHtml<'a>(pub &'a str, pub RefCell<&'a mut IdMap>, pub ErrorCodes, pub Edition); /// A unit struct like `Markdown`, that renders only the first paragraph. pub struct MarkdownSummaryLine<'a>(pub &'a str, pub &'a [(String, String)]); @@ -146,13 +153,15 @@ thread_local!(pub static PLAYGROUND: RefCell, String)>> = struct CodeBlocks<'a, I: Iterator>> { inner: I, check_error_codes: ErrorCodes, + edition: Edition, } impl<'a, I: Iterator>> CodeBlocks<'a, I> { - fn new(iter: I, error_codes: ErrorCodes) -> Self { + fn new(iter: I, error_codes: ErrorCodes, edition: Edition) -> Self { CodeBlocks { inner: iter, check_error_codes: error_codes, + edition, } } } @@ -177,6 +186,9 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'a, I> { return event; } + let explicit_edition = edition.is_some(); + let edition = edition.unwrap_or(self.edition); + let mut origtext = String::new(); for event in &mut self.inner { match event { @@ -202,22 +214,14 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'a, I> { .collect::>>().join("\n"); let krate = krate.as_ref().map(|s| &**s); let (test, _) = test::make_test(&test, krate, false, - &Default::default()); + &Default::default(), edition); let channel = if test.contains("#![feature(") { "&version=nightly" } else { "" }; - let edition_string = if let Some(e @ Edition::Edition2018) = edition { - format!("&edition={}{}", e, - if channel == "&version=nightly" { "" } - else { "&version=nightly" }) - } else if let Some(e) = edition { - format!("&edition={}", e) - } else { - "".to_owned() - }; + let edition_string = format!("&edition={}", edition); // These characters don't need to be escaped in a URI. // FIXME: use a library function for percent encoding. @@ -247,8 +251,8 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'a, I> { Some(("This example is not tested".to_owned(), "ignore")) } else if compile_fail { Some(("This example deliberately fails to compile".to_owned(), "compile_fail")) - } else if let Some(e) = edition { - Some((format!("This code runs with edition {}", e), "edition")) + } else if explicit_edition { + Some((format!("This code runs with edition {}", edition), "edition")) } else { None }; @@ -259,7 +263,7 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'a, I> { Some(&format!("rust-example-rendered{}", if ignore { " ignore" } else if compile_fail { " compile_fail" } - else if edition.is_some() { " edition " } + else if explicit_edition { " edition " } else { "" })), playground_button.as_ref().map(String::as_str), Some((s1.as_str(), s2)))); @@ -270,7 +274,7 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'a, I> { Some(&format!("rust-example-rendered{}", if ignore { " ignore" } else if compile_fail { " compile_fail" } - else if edition.is_some() { " edition " } + else if explicit_edition { " edition " } else { "" })), playground_button.as_ref().map(String::as_str), None)); @@ -659,7 +663,7 @@ impl LangString { impl<'a> fmt::Display for Markdown<'a> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let Markdown(md, links, ref ids, codes) = *self; + let Markdown(md, links, ref ids, codes, edition) = *self; let mut ids = ids.borrow_mut(); // This is actually common enough to special-case @@ -678,7 +682,7 @@ impl<'a> fmt::Display for Markdown<'a> { let p = HeadingLinks::new(p, None, &mut ids); let p = LinkReplacer::new(p, links); - let p = CodeBlocks::new(p, codes); + let p = CodeBlocks::new(p, codes, edition); let p = Footnotes::new(p); html::push_html(&mut s, p); @@ -688,7 +692,7 @@ impl<'a> fmt::Display for Markdown<'a> { impl<'a> fmt::Display for MarkdownWithToc<'a> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let MarkdownWithToc(md, ref ids, codes) = *self; + let MarkdownWithToc(md, ref ids, codes, edition) = *self; let mut ids = ids.borrow_mut(); let p = Parser::new_ext(md, opts()); @@ -699,7 +703,7 @@ impl<'a> fmt::Display for MarkdownWithToc<'a> { { let p = HeadingLinks::new(p, Some(&mut toc), &mut ids); - let p = CodeBlocks::new(p, codes); + let p = CodeBlocks::new(p, codes, edition); let p = Footnotes::new(p); html::push_html(&mut s, p); } @@ -712,7 +716,7 @@ impl<'a> fmt::Display for MarkdownWithToc<'a> { impl<'a> fmt::Display for MarkdownHtml<'a> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let MarkdownHtml(md, ref ids, codes) = *self; + let MarkdownHtml(md, ref ids, codes, edition) = *self; let mut ids = ids.borrow_mut(); // This is actually common enough to special-case @@ -728,7 +732,7 @@ impl<'a> fmt::Display for MarkdownHtml<'a> { let mut s = String::with_capacity(md.len() * 3 / 2); let p = HeadingLinks::new(p, None, &mut ids); - let p = CodeBlocks::new(p, codes); + let p = CodeBlocks::new(p, codes, edition); let p = Footnotes::new(p); html::push_html(&mut s, p); diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 472192a64649..d92681c4f235 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -47,6 +47,7 @@ use std::rc::Rc; use errors; use serialize::json::{ToJson, Json, as_json}; use syntax::ast; +use syntax::edition::Edition; use syntax::ext::base::MacroKind; use syntax::source_map::FileName; use syntax::feature_gate::UnstableFeatures; @@ -107,6 +108,8 @@ struct Context { /// publicly reused items to redirect to the right location. pub render_redirect_pages: bool, pub codes: ErrorCodes, + /// The default edition used to parse doctests. + pub edition: Edition, /// The map used to ensure all generated 'id=' attributes are unique. id_map: Rc>, pub shared: Arc, @@ -513,7 +516,8 @@ pub fn run(mut krate: clean::Crate, options: RenderOptions, passes: FxHashSet, renderinfo: RenderInfo, - diag: &errors::Handler) -> Result<(), Error> { + diag: &errors::Handler, + edition: Edition) -> Result<(), Error> { // need to save a copy of the options for rendering the index page let md_opts = options.clone(); let RenderOptions { @@ -603,6 +607,7 @@ pub fn run(mut krate: clean::Crate, dst, render_redirect_pages: false, codes: ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()), + edition, id_map: Rc::new(RefCell::new(id_map)), shared: Arc::new(scx), }; @@ -1127,7 +1132,7 @@ themePicker.onblur = handleThemeButtonsBlur; md_opts.output = cx.dst.clone(); md_opts.external_html = (*cx.shared).layout.external_html.clone(); - crate::markdown::render(index_page, md_opts, diag); + crate::markdown::render(index_page, md_opts, diag, cx.edition); } else { let dst = cx.dst.join("index.html"); let mut w = BufWriter::new(try_err!(File::create(&dst), &dst)); @@ -2552,7 +2557,7 @@ fn render_markdown(w: &mut fmt::Formatter<'_>, if is_hidden { " hidden" } else { "" }, prefix, Markdown(md_text, &links, RefCell::new(&mut ids), - cx.codes)) + cx.codes, cx.edition)) } fn document_short( @@ -2917,7 +2922,7 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec { if let Some(note) = note { let mut ids = cx.id_map.borrow_mut(); - let html = MarkdownHtml(¬e, RefCell::new(&mut ids), error_codes); + let html = MarkdownHtml(¬e, RefCell::new(&mut ids), error_codes, cx.edition); message.push_str(&format!(": {}", html)); } stability.push(format!("
{}
", message)); @@ -2966,7 +2971,7 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec { message = format!( "
{}{}
", message, - MarkdownHtml(&unstable_reason, RefCell::new(&mut ids), error_codes) + MarkdownHtml(&unstable_reason, RefCell::new(&mut ids), error_codes, cx.edition) ); } @@ -4179,7 +4184,8 @@ fn render_impl(w: &mut fmt::Formatter<'_>, cx: &Context, i: &Impl, link: AssocIt if let Some(ref dox) = cx.shared.maybe_collapsed_doc_value(&i.impl_item) { let mut ids = cx.id_map.borrow_mut(); write!(w, "
{}
", - Markdown(&*dox, &i.impl_item.links(), RefCell::new(&mut ids), cx.codes))?; + Markdown(&*dox, &i.impl_item.links(), RefCell::new(&mut ids), + cx.codes, cx.edition))?; } } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 5b76f6861de7..f5061b671828 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -391,7 +391,10 @@ fn main_args(args: &[String]) -> i32 { match (options.should_test, options.markdown_input()) { (true, true) => return markdown::test(options, &diag), (true, false) => return test::run(options), - (false, true) => return markdown::render(options.input, options.render_options, &diag), + (false, true) => return markdown::render(options.input, + options.render_options, + &diag, + options.edition), (false, false) => {} } @@ -399,7 +402,8 @@ fn main_args(args: &[String]) -> i32 { // but we can't crates the Handler ahead of time because it's not Send let diag_opts = (options.error_format, options.debugging_options.treat_err_as_bug, - options.debugging_options.ui_testing); + options.debugging_options.ui_testing, + options.edition); let show_coverage = options.show_coverage; rust_input(options, move |out| { if show_coverage { @@ -410,7 +414,7 @@ fn main_args(args: &[String]) -> i32 { let Output { krate, passes, renderinfo, renderopts } = out; info!("going to format"); - let (error_format, treat_err_as_bug, ui_testing) = diag_opts; + let (error_format, treat_err_as_bug, ui_testing, edition) = diag_opts; let diag = core::new_handler(error_format, None, treat_err_as_bug, ui_testing); match html::render::run( krate, @@ -418,6 +422,7 @@ fn main_args(args: &[String]) -> i32 { passes.into_iter().collect(), renderinfo, &diag, + edition, ) { Ok(_) => rustc_driver::EXIT_SUCCESS, Err(e) => { diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index c496dde8426c..b0a37ea9c808 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -5,6 +5,7 @@ use std::cell::RefCell; use errors; use testing; +use syntax::edition::Edition; use syntax::source_map::DUMMY_SP; use syntax::feature_gate::UnstableFeatures; @@ -36,7 +37,12 @@ fn extract_leading_metadata<'a>(s: &'a str) -> (Vec<&'a str>, &'a str) { /// Render `input` (e.g., "foo.md") into an HTML file in `output` /// (e.g., output = "bar" => "bar/foo.html"). -pub fn render(input: PathBuf, options: RenderOptions, diag: &errors::Handler) -> i32 { +pub fn render( + input: PathBuf, + options: RenderOptions, + diag: &errors::Handler, + edition: Edition +) -> i32 { let mut output = options.output; output.push(input.file_stem().unwrap()); output.set_extension("html"); @@ -76,9 +82,9 @@ pub fn render(input: PathBuf, options: RenderOptions, diag: &errors::Handler) -> let mut ids = IdMap::new(); let error_codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()); let text = if !options.markdown_no_toc { - MarkdownWithToc(text, RefCell::new(&mut ids), error_codes).to_string() + MarkdownWithToc(text, RefCell::new(&mut ids), error_codes, edition).to_string() } else { - Markdown(text, &[], RefCell::new(&mut ids), error_codes).to_string() + Markdown(text, &[], RefCell::new(&mut ids), error_codes, edition).to_string() }; let err = write!( diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 5c0a4da1cd7e..7a9b82c71653 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -167,7 +167,7 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize, maybe_sysroot: Option, linker: Option, edition: Edition, persist_doctests: Option) { let (test, line_offset) = match panic::catch_unwind(|| { - make_test(test, Some(cratename), as_test_harness, opts) + make_test(test, Some(cratename), as_test_harness, opts, edition) }) { Ok((test, line_offset)) => (test, line_offset), Err(cause) if cause.is::() => { @@ -356,7 +356,8 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize, pub fn make_test(s: &str, cratename: Option<&str>, dont_insert_main: bool, - opts: &TestOptions) + opts: &TestOptions, + edition: Edition) -> (String, usize) { let (crate_attrs, everything_else, crates) = partition_source(s); let everything_else = everything_else.trim(); @@ -390,6 +391,8 @@ pub fn make_test(s: &str, use errors::emitter::EmitterWriter; use errors::Handler; + syntax::ext::hygiene::set_default_edition(edition); + let filename = FileName::anon_source_code(s); let source = crates + &everything_else; @@ -397,6 +400,7 @@ pub fn make_test(s: &str, // send all the errors that libsyntax emits directly into a `Sink` instead of stderr. let cm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let emitter = EmitterWriter::new(box io::sink(), None, false, false, false); + // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser let handler = Handler::with_emitter(false, None, box emitter); let sess = ParseSess::with_span_handler(handler, cm); diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index 04986b59ea0f..38bd3fc006dc 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -15,6 +15,7 @@ use std::path::Path; use std::path::PathBuf; use std::cell::RefCell; +use syntax::edition::DEFAULT_EDITION; use syntax::diagnostics::metadata::{get_metadata_dir, ErrorMetadataMap, ErrorMetadata}; use rustdoc::html::markdown::{Markdown, IdMap, ErrorCodes, PLAYGROUND}; @@ -97,7 +98,8 @@ impl Formatter for HTMLFormatter { Some(ref desc) => { let mut id_map = self.0.borrow_mut(); write!(output, "{}", - Markdown(desc, &[], RefCell::new(&mut id_map), ErrorCodes::Yes))? + Markdown(desc, &[], RefCell::new(&mut id_map), + ErrorCodes::Yes, DEFAULT_EDITION))? }, None => write!(output, "

No description.

\n")?, } From e66e1c7186f027a17a0959d0e8f42367446217c1 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Thu, 18 Apr 2019 09:10:08 -0500 Subject: [PATCH 0063/3207] update playground url tests with new edition behavior --- src/test/rustdoc/playground-arg.rs | 2 +- src/test/rustdoc/playground.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/rustdoc/playground-arg.rs b/src/test/rustdoc/playground-arg.rs index fb1be7397e65..018716ad45af 100644 --- a/src/test/rustdoc/playground-arg.rs +++ b/src/test/rustdoc/playground-arg.rs @@ -11,4 +11,4 @@ pub fn dummy() {} // ensure that `extern crate foo;` was inserted into code snips automatically: -// @matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=%23!%5Ballow(unused)%5D%0Aextern%20crate%20foo%3B%0Afn%20main()%20%7B%0Ause%20foo%3A%3Adummy%3B%0Adummy()%3B%0A%7D"]' "Run" +// @matches foo/index.html '//a[@class="test-arrow"][@href="https://example.com/?code=%23!%5Ballow(unused)%5D%0Aextern%20crate%20foo%3B%0Afn%20main()%20%7B%0Ause%20foo%3A%3Adummy%3B%0Adummy()%3B%0A%7D&edition=2015"]' "Run" diff --git a/src/test/rustdoc/playground.rs b/src/test/rustdoc/playground.rs index 1b76e6c88534..9971c7b4297a 100644 --- a/src/test/rustdoc/playground.rs +++ b/src/test/rustdoc/playground.rs @@ -24,6 +24,6 @@ //! } //! ``` -// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D"]' "Run" -// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn%20main()%20%7B%0Aprintln!(%22Hello%2C%20world!%22)%3B%0A%7D"]' "Run" -// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D&version=nightly"]' "Run" +// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D&edition=2015"]' "Run" +// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0Afn%20main()%20%7B%0Aprintln!(%22Hello%2C%20world!%22)%3B%0A%7D&edition=2015"]' "Run" +// @matches foo/index.html '//a[@class="test-arrow"][@href="https://www.example.com/?code=%23!%5Ballow(unused)%5D%0A%23!%5Bfeature(something)%5D%0A%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22Hello%2C%20world!%22)%3B%0A%7D&version=nightly&edition=2015"]' "Run" From a6d26eb053e9c56fdc9d9e20a2952041a165e559 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Thu, 18 Apr 2019 09:15:39 -0500 Subject: [PATCH 0064/3207] add test for `async move` in a doctest --- src/test/rustdoc/async-move-doctest.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/test/rustdoc/async-move-doctest.rs diff --git a/src/test/rustdoc/async-move-doctest.rs b/src/test/rustdoc/async-move-doctest.rs new file mode 100644 index 000000000000..42723132782c --- /dev/null +++ b/src/test/rustdoc/async-move-doctest.rs @@ -0,0 +1,14 @@ +// compile-flags:--test +// edition:2018 + +// prior to setting the default edition for the doctest pre-parser, this doctest would fail due to +// a fatal parsing error +// see https://github.com/rust-lang/rust/issues/59313 + +//! ``` +//! #![feature(async_await)] +//! +//! fn foo() { +//! drop(async move {}); +//! } +//! ``` From 5b167bf4bbdff169ca735476e66fdf9b4e6501fd Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Thu, 18 Apr 2019 12:23:54 -0500 Subject: [PATCH 0065/3207] update rustdoc unit tests --- src/librustdoc/html/markdown.rs | 11 +++++++---- src/librustdoc/test.rs | 35 +++++++++++++++++---------------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 5f450fcf6fca..df01ac2f4440 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -1050,7 +1050,7 @@ mod tests { use super::{ErrorCodes, LangString, Markdown, MarkdownHtml, IdMap}; use super::plain_summary_line; use std::cell::RefCell; - use syntax::edition::Edition; + use syntax::edition::{Edition, DEFAULT_EDITION}; #[test] fn test_lang_string_parse() { @@ -1102,7 +1102,8 @@ mod tests { fn test_header() { fn t(input: &str, expect: &str) { let mut map = IdMap::new(); - let output = Markdown(input, &[], RefCell::new(&mut map), ErrorCodes::Yes).to_string(); + let output = Markdown(input, &[], RefCell::new(&mut map), + ErrorCodes::Yes, DEFAULT_EDITION).to_string(); assert_eq!(output, expect, "original: {}", input); } @@ -1124,7 +1125,8 @@ mod tests { fn test_header_ids_multiple_blocks() { let mut map = IdMap::new(); fn t(map: &mut IdMap, input: &str, expect: &str) { - let output = Markdown(input, &[], RefCell::new(map), ErrorCodes::Yes).to_string(); + let output = Markdown(input, &[], RefCell::new(map), + ErrorCodes::Yes, DEFAULT_EDITION).to_string(); assert_eq!(output, expect, "original: {}", input); } @@ -1161,7 +1163,8 @@ mod tests { fn test_markdown_html_escape() { fn t(input: &str, expect: &str) { let mut idmap = IdMap::new(); - let output = MarkdownHtml(input, RefCell::new(&mut idmap), ErrorCodes::Yes).to_string(); + let output = MarkdownHtml(input, RefCell::new(&mut idmap), + ErrorCodes::Yes, DEFAULT_EDITION).to_string(); assert_eq!(output, expect, "original: {}", input); } diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 7a9b82c71653..268f0602d487 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -884,6 +884,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> { #[cfg(test)] mod tests { use super::{TestOptions, make_test}; + use syntax::edition::DEFAULT_EDITION; #[test] fn make_test_basic() { @@ -896,7 +897,7 @@ mod tests { fn main() { assert_eq!(2+2, 4); }".to_string(); - let output = make_test(input, None, false, &opts); + let output = make_test(input, None, false, &opts, DEFAULT_EDITION); assert_eq!(output, (expected, 2)); } @@ -912,7 +913,7 @@ assert_eq!(2+2, 4); fn main() { assert_eq!(2+2, 4); }".to_string(); - let output = make_test(input, Some("asdf"), false, &opts); + let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); assert_eq!(output, (expected, 2)); } @@ -931,7 +932,7 @@ fn main() { use asdf::qwop; assert_eq!(2+2, 4); }".to_string(); - let output = make_test(input, Some("asdf"), false, &opts); + let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); assert_eq!(output, (expected, 3)); } @@ -953,7 +954,7 @@ fn main() { use asdf::qwop; assert_eq!(2+2, 4); }".to_string(); - let output = make_test(input, Some("asdf"), false, &opts); + let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); assert_eq!(output, (expected, 2)); } @@ -972,7 +973,7 @@ fn main() { use std::*; assert_eq!(2+2, 4); }".to_string(); - let output = make_test(input, Some("std"), false, &opts); + let output = make_test(input, Some("std"), false, &opts, DEFAULT_EDITION); assert_eq!(output, (expected, 2)); } @@ -992,7 +993,7 @@ fn main() { use asdf::qwop; assert_eq!(2+2, 4); }".to_string(); - let output = make_test(input, Some("asdf"), false, &opts); + let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); assert_eq!(output, (expected, 2)); } @@ -1010,7 +1011,7 @@ fn main() { use asdf::qwop; assert_eq!(2+2, 4); }".to_string(); - let output = make_test(input, Some("asdf"), false, &opts); + let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); assert_eq!(output, (expected, 2)); } @@ -1030,7 +1031,7 @@ fn main() { use asdf::qwop; assert_eq!(2+2, 4); }".to_string(); - let output = make_test(input, Some("asdf"), false, &opts); + let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); assert_eq!(output, (expected, 3)); // Adding more will also bump the returned line offset. @@ -1043,7 +1044,7 @@ fn main() { use asdf::qwop; assert_eq!(2+2, 4); }".to_string(); - let output = make_test(input, Some("asdf"), false, &opts); + let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); assert_eq!(output, (expected, 4)); } @@ -1061,7 +1062,7 @@ assert_eq!(2+2, 4);"; fn main() { assert_eq!(2+2, 4); }".to_string(); - let output = make_test(input, None, false, &opts); + let output = make_test(input, None, false, &opts, DEFAULT_EDITION); assert_eq!(output, (expected, 2)); } @@ -1078,7 +1079,7 @@ assert_eq!(2+2, 4); fn main() { assert_eq!(2+2, 4); }".to_string(); - let output = make_test(input, None, false, &opts); + let output = make_test(input, None, false, &opts, DEFAULT_EDITION); assert_eq!(output, (expected, 1)); } @@ -1095,7 +1096,7 @@ assert_eq!(2+2, 4);"; fn main() { assert_eq!(2+2, 4); }".to_string(); - let output = make_test(input, None, false, &opts); + let output = make_test(input, None, false, &opts, DEFAULT_EDITION); assert_eq!(output, (expected, 2)); } @@ -1110,7 +1111,7 @@ assert_eq!(2+2, 4);"; "#![allow(unused)] //Ceci n'est pas une `fn main` assert_eq!(2+2, 4);".to_string(); - let output = make_test(input, None, true, &opts); + let output = make_test(input, None, true, &opts, DEFAULT_EDITION); assert_eq!(output, (expected, 1)); } @@ -1125,7 +1126,7 @@ assert_eq!(2+2, 4);".to_string(); "fn main() { assert_eq!(2+2, 4); }".to_string(); - let output = make_test(input, None, false, &opts); + let output = make_test(input, None, false, &opts, DEFAULT_EDITION); assert_eq!(output, (expected, 1)); } @@ -1144,7 +1145,7 @@ fn main() { assert_eq!(2+2, 4); }".to_string(); - let output = make_test(input, None, false, &opts); + let output = make_test(input, None, false, &opts, DEFAULT_EDITION); assert_eq!(output, (expected, 2)); let input = @@ -1159,7 +1160,7 @@ fn main() { assert_eq!(asdf::foo, 4); }".to_string(); - let output = make_test(input, Some("asdf"), false, &opts); + let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION); assert_eq!(output, (expected, 3)); } @@ -1178,7 +1179,7 @@ test_wrapper! { fn main() {} }".to_string(); - let output = make_test(input, Some("my_crate"), false, &opts); + let output = make_test(input, Some("my_crate"), false, &opts, DEFAULT_EDITION); assert_eq!(output, (expected, 1)); } } From e61ff7717e6936929c3fb7cdb001383c64105cf3 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Thu, 18 Apr 2019 14:20:18 -0500 Subject: [PATCH 0066/3207] update rustdoc doc test --- src/librustdoc/html/markdown.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index df01ac2f4440..12d10254c4d0 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -8,12 +8,16 @@ //! ``` //! #![feature(rustc_private)] //! +//! extern crate syntax; +//! +//! use syntax::edition::Edition; //! use rustdoc::html::markdown::{IdMap, Markdown, ErrorCodes}; //! use std::cell::RefCell; //! //! let s = "My *markdown* _text_"; //! let mut id_map = IdMap::new(); -//! let html = format!("{}", Markdown(s, &[], RefCell::new(&mut id_map), ErrorCodes::Yes)); +//! let html = format!("{}", Markdown(s, &[], RefCell::new(&mut id_map), +//! ErrorCodes::Yes, Edition::Edition2015)); //! // ... something using html //! ``` From 76b49007f3400a6bc5af5586c2a31121c2525568 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Fri, 19 Apr 2019 08:54:26 -0500 Subject: [PATCH 0067/3207] don't pre-allocate the default edition string --- src/librustdoc/config.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 0a403f61e9c2..d17d27271ce6 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -13,7 +13,7 @@ use rustc::session::config::{nightly_options, build_codegen_options, build_debug use rustc::session::search_paths::SearchPath; use rustc_driver; use rustc_target::spec::TargetTriple; -use syntax::edition::Edition; +use syntax::edition::{Edition, DEFAULT_EDITION}; use crate::core::new_handler; use crate::externalfiles::ExternalHtml; @@ -386,13 +386,16 @@ impl Options { } } - let edition = matches.opt_str("edition").unwrap_or("2015".to_string()); - let edition = match edition.parse() { - Ok(e) => e, - Err(_) => { - diag.struct_err("could not parse edition").emit(); - return Err(1); + let edition = if let Some(e) = matches.opt_str("edition") { + match e.parse() { + Ok(e) => e, + Err(_) => { + diag.struct_err("could not parse edition").emit(); + return Err(1); + } } + } else { + DEFAULT_EDITION }; let mut id_map = html::markdown::IdMap::new(); From 48d1be4f46225350bb59f87a46bf2f6cba041013 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Mon, 6 May 2019 17:06:59 -0400 Subject: [PATCH 0068/3207] Test interaction of unions with non-zero/niche-filling optimization Notably this nails down part of the behavior that MaybeUninit assumes, e.g. that a Option> does not take advantage of non-zero optimization, and thus is a safe construct. --- src/test/run-pass/union/union-nonzero.rs | 30 +++++++++++++++++++ src/test/ui/print_type_sizes/niche-filling.rs | 17 +++++++++++ .../ui/print_type_sizes/niche-filling.stdout | 26 ++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 src/test/run-pass/union/union-nonzero.rs diff --git a/src/test/run-pass/union/union-nonzero.rs b/src/test/run-pass/union/union-nonzero.rs new file mode 100644 index 000000000000..614aa9ec0ce1 --- /dev/null +++ b/src/test/run-pass/union/union-nonzero.rs @@ -0,0 +1,30 @@ +// run-pass +#![allow(dead_code)] + +use std::mem::{size_of, transmute}; + +union U1 { + a: A, +} + +union U2 { + a: A, + b: B, +} + +fn main() { + // Unions do not participate in niche-filling/non-zero optimization... + assert!(size_of::>>() > size_of::>()); + assert!(size_of::>>() > size_of::>()); + + // ...even when theoretically possible: + assert!(size_of::>>() > size_of::>()); + assert!(size_of::>>() > size_of::>()); + + // The unused bits of the () variant can have any value. + let zeroed: U2<&u8, ()> = unsafe { transmute(std::ptr::null::()) }; + + if let None = Some(zeroed) { + panic!() + } +} diff --git a/src/test/ui/print_type_sizes/niche-filling.rs b/src/test/ui/print_type_sizes/niche-filling.rs index bed1e32a6015..0127261b2b7d 100644 --- a/src/test/ui/print_type_sizes/niche-filling.rs +++ b/src/test/ui/print_type_sizes/niche-filling.rs @@ -57,6 +57,15 @@ pub enum Enum4 { Four(D) } +pub union Union1 { + a: A, +} + +pub union Union2 { + a: A, + b: B, +} + #[start] fn start(_: isize, _: *const *const u8) -> isize { let _x: MyOption = Default::default(); @@ -69,5 +78,13 @@ fn start(_: isize, _: *const *const u8) -> isize { let _e: Enum4<(), char, (), ()> = Enum4::One(()); let _f: Enum4<(), (), bool, ()> = Enum4::One(()); let _g: Enum4<(), (), (), MyOption> = Enum4::One(()); + + // Unions do not currently participate in niche filling. + let _h: MyOption> = Default::default(); + + // ...even when theoretically possible. + let _i: MyOption> = Default::default(); + let _j: MyOption> = Default::default(); + 0 } diff --git a/src/test/ui/print_type_sizes/niche-filling.stdout b/src/test/ui/print_type_sizes/niche-filling.stdout index 9cdb2ae4f57e..301edc0d086b 100644 --- a/src/test/ui/print_type_sizes/niche-filling.stdout +++ b/src/test/ui/print_type_sizes/niche-filling.stdout @@ -14,6 +14,21 @@ print-type-size field `.post`: 2 bytes print-type-size field `.pre`: 1 bytes print-type-size variant `None`: 0 bytes print-type-size end padding: 1 bytes +print-type-size type: `MyOption>`: 8 bytes, alignment: 4 bytes +print-type-size discriminant: 4 bytes +print-type-size variant `Some`: 4 bytes +print-type-size field `.0`: 4 bytes +print-type-size variant `None`: 0 bytes +print-type-size type: `MyOption>`: 8 bytes, alignment: 4 bytes +print-type-size discriminant: 4 bytes +print-type-size variant `Some`: 4 bytes +print-type-size field `.0`: 4 bytes +print-type-size variant `None`: 0 bytes +print-type-size type: `MyOption>`: 8 bytes, alignment: 4 bytes +print-type-size discriminant: 4 bytes +print-type-size variant `Some`: 4 bytes +print-type-size field `.0`: 4 bytes +print-type-size variant `None`: 0 bytes print-type-size type: `NestedNonZero`: 8 bytes, alignment: 4 bytes print-type-size field `.val`: 4 bytes print-type-size field `.post`: 2 bytes @@ -36,6 +51,17 @@ print-type-size type: `MyOption`: 4 bytes, alignment: 4 by print-type-size variant `Some`: 4 bytes print-type-size field `.0`: 4 bytes print-type-size variant `None`: 0 bytes +print-type-size type: `Union1`: 4 bytes, alignment: 4 bytes +print-type-size variant `Union1`: 4 bytes +print-type-size field `.a`: 4 bytes +print-type-size type: `Union2`: 4 bytes, alignment: 4 bytes +print-type-size variant `Union2`: 4 bytes +print-type-size field `.a`: 4 bytes +print-type-size field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes +print-type-size type: `Union2`: 4 bytes, alignment: 4 bytes +print-type-size variant `Union2`: 4 bytes +print-type-size field `.a`: 4 bytes +print-type-size field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes print-type-size type: `std::num::NonZeroU32`: 4 bytes, alignment: 4 bytes print-type-size field `.0`: 4 bytes print-type-size type: `Enum4<(), (), (), MyOption>`: 2 bytes, alignment: 1 bytes From 76c52290214c49a9ba0cf506ac7e636543e087ff Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Tue, 7 May 2019 12:16:33 -0400 Subject: [PATCH 0069/3207] Document purpose of union-nonzero test --- src/test/run-pass/union/union-nonzero.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test/run-pass/union/union-nonzero.rs b/src/test/run-pass/union/union-nonzero.rs index 614aa9ec0ce1..07a58aa7746d 100644 --- a/src/test/run-pass/union/union-nonzero.rs +++ b/src/test/run-pass/union/union-nonzero.rs @@ -1,6 +1,18 @@ // run-pass #![allow(dead_code)] +// Tests that unions aren't subject to unsafe non-zero/niche-filling optimizations. +// +// For example, if a union `U` can contain both a `&T` and a `*const T`, there's definitely no +// bit-value that an `Option` could reuse as `None`; this test makes sure that isn't done. +// +// Secondly, this tests the status quo to not apply such optimizations to types containing unions +// even if they're theoretically possible. (discussion: https://github.com/rust-lang/rust/issues/36394) +// +// Notably this nails down part of the behavior that `MaybeUninit` assumes: that a +// `Option>` does not take advantage of non-zero optimization, and thus is a safe +// construct. + use std::mem::{size_of, transmute}; union U1 { From aa1db2476a7b6e3155bf40cc48f6bc897575c622 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Tue, 7 May 2019 12:17:28 -0400 Subject: [PATCH 0070/3207] Add non-non-zero test to union-nonzero test --- src/test/run-pass/union/union-nonzero.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/test/run-pass/union/union-nonzero.rs b/src/test/run-pass/union/union-nonzero.rs index 07a58aa7746d..2108cc3a4ea7 100644 --- a/src/test/run-pass/union/union-nonzero.rs +++ b/src/test/run-pass/union/union-nonzero.rs @@ -24,10 +24,18 @@ union U2 { b: B, } +// Option uses a value other than 0 and 1 as None +#[derive(Clone,Copy)] +enum E { + A = 0, + B = 1, +} + fn main() { // Unions do not participate in niche-filling/non-zero optimization... assert!(size_of::>>() > size_of::>()); assert!(size_of::>>() > size_of::>()); + assert!(size_of::>>() > size_of::>()); // ...even when theoretically possible: assert!(size_of::>>() > size_of::>()); From 1acd37fde5b07c66853b925d7d91dd3be6dc2a78 Mon Sep 17 00:00:00 2001 From: Dodo Date: Thu, 9 May 2019 20:30:36 +0200 Subject: [PATCH 0071/3207] make vecdeque_rotate stable --- src/liballoc/collections/vec_deque.rs | 8 ++------ src/liballoc/tests/lib.rs | 1 - 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index d65c24f7350a..7e7a854d2f33 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1934,8 +1934,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(vecdeque_rotate)] - /// /// use std::collections::VecDeque; /// /// let mut buf: VecDeque<_> = (0..10).collect(); @@ -1949,7 +1947,7 @@ impl VecDeque { /// } /// assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); /// ``` - #[unstable(feature = "vecdeque_rotate", issue = "56686")] + #[stable(feature = "vecdeque_rotate", since = "1.35.0")] pub fn rotate_left(&mut self, mid: usize) { assert!(mid <= self.len()); let k = self.len() - mid; @@ -1979,8 +1977,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(vecdeque_rotate)] - /// /// use std::collections::VecDeque; /// /// let mut buf: VecDeque<_> = (0..10).collect(); @@ -1994,7 +1990,7 @@ impl VecDeque { /// } /// assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); /// ``` - #[unstable(feature = "vecdeque_rotate", issue = "56686")] + #[stable(feature = "vecdeque_rotate", since = "1.35.0")] pub fn rotate_right(&mut self, k: usize) { assert!(k <= self.len()); let mid = self.len() - k; diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index b736750c5760..ddb3120e89d7 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -6,7 +6,6 @@ #![feature(repeat_generic_slice)] #![feature(try_reserve)] #![feature(unboxed_closures)] -#![feature(vecdeque_rotate)] #![deny(rust_2018_idioms)] use std::hash::{Hash, Hasher}; From 4d033990fcb96023739a13c43e72b341de51e865 Mon Sep 17 00:00:00 2001 From: Dodo Date: Thu, 9 May 2019 20:50:02 +0200 Subject: [PATCH 0072/3207] supposed to be 1.36.0 --- src/liballoc/collections/vec_deque.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 7e7a854d2f33..65a888a97036 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1947,7 +1947,7 @@ impl VecDeque { /// } /// assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); /// ``` - #[stable(feature = "vecdeque_rotate", since = "1.35.0")] + #[stable(feature = "vecdeque_rotate", since = "1.36.0")] pub fn rotate_left(&mut self, mid: usize) { assert!(mid <= self.len()); let k = self.len() - mid; @@ -1990,7 +1990,7 @@ impl VecDeque { /// } /// assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); /// ``` - #[stable(feature = "vecdeque_rotate", since = "1.35.0")] + #[stable(feature = "vecdeque_rotate", since = "1.36.0")] pub fn rotate_right(&mut self, k: usize) { assert!(k <= self.len()); let mid = self.len() - k; From 699376ada01dc6223e5365e79ae11c79502fd2ef Mon Sep 17 00:00:00 2001 From: John Erickson Date: Mon, 6 May 2019 11:15:52 -0700 Subject: [PATCH 0073/3207] Add Azure Pipelines --- .azure-pipelines/auto.fanout.yml | 521 ++++++++++++++++++ .azure-pipelines/auto.yml | 361 ++++++++++++ .azure-pipelines/master.yml | 22 + .azure-pipelines/pr.yml | 26 + .azure-pipelines/steps/linux.yml | 42 ++ .azure-pipelines/steps/macos.yml | 47 ++ .azure-pipelines/steps/run-script.yml | 24 + .azure-pipelines/steps/show-disk-usage.yml | 5 + .../steps/show-environment-variables.yml | 3 + .../steps/verify-publish-toolstate.yml | 9 + .azure-pipelines/steps/windows.yml | 160 ++++++ .azure-pipelines/test.yml | 131 +++++ .azure-pipelines/try.yml | 29 + README.md | 2 + appveyor.yml | 8 +- src/bootstrap/README.md | 3 +- src/bootstrap/mk/Makefile.in | 74 ++- src/bootstrap/native.rs | 9 +- src/bootstrap/util.rs | 4 + .../{i686-gnu => i686-gnu-1}/Dockerfile | 9 +- src/ci/docker/i686-gnu-2/Dockerfile | 21 + src/ci/docker/run.sh | 39 +- src/ci/docker/scripts/sccache.sh | 3 +- src/ci/docker/x86_64-gnu-tools/checktools.sh | 2 +- src/ci/run.sh | 42 +- src/ci/shared.sh | 16 + src/test/run-pass/fds-are-cloexec.rs | 1 + 27 files changed, 1566 insertions(+), 47 deletions(-) create mode 100644 .azure-pipelines/auto.fanout.yml create mode 100644 .azure-pipelines/auto.yml create mode 100644 .azure-pipelines/master.yml create mode 100644 .azure-pipelines/pr.yml create mode 100644 .azure-pipelines/steps/linux.yml create mode 100644 .azure-pipelines/steps/macos.yml create mode 100644 .azure-pipelines/steps/run-script.yml create mode 100644 .azure-pipelines/steps/show-disk-usage.yml create mode 100644 .azure-pipelines/steps/show-environment-variables.yml create mode 100644 .azure-pipelines/steps/verify-publish-toolstate.yml create mode 100644 .azure-pipelines/steps/windows.yml create mode 100644 .azure-pipelines/test.yml create mode 100644 .azure-pipelines/try.yml rename src/ci/docker/{i686-gnu => i686-gnu-1}/Dockerfile (54%) create mode 100644 src/ci/docker/i686-gnu-2/Dockerfile diff --git a/.azure-pipelines/auto.fanout.yml b/.azure-pipelines/auto.fanout.yml new file mode 100644 index 000000000000..08cba3c47ca8 --- /dev/null +++ b/.azure-pipelines/auto.fanout.yml @@ -0,0 +1,521 @@ +# +# Azure Pipelines "auto" branch build for Rust on Linux, macOS, and Windows. +# +# Notes: +# To get sccache working, I (John Erickson) had to build it with the Azure feature enabled +# and with openssl statically-linked for Linux. +# Here's the build (with a backpointer to source) of where the bits came from: +# https://dev.azure.com/johnterickson/rust-lang/_build/results?buildId=275 + +name: fanout +pr: none +trigger: +- auto + +variables: +- group: caching + +jobs: +# WINDOWS JOBS +- job: Windows + timeoutInMinutes: 600 + variables: + TAR_COMMAND: tar + pool: + vmImage: 'vs2017-win2016' + steps: + - template: steps/windows.yml + strategy: + matrix: + # 32/64 bit MSVC tests + x86_64-msvc-1: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + SCRIPT: make ci-subset-1 + x86_64-msvc-2: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + SCRIPT: make ci-subset-2 + +- job: Windows_build + timeoutInMinutes: 600 + variables: + TAR_COMMAND: tar + pool: + vmImage: 'vs2017-win2016' + steps: + - template: steps/windows.yml + - script: | + echo on + echo "##vso[task.setvariable variable=TAR_PATH]%TEMP%\drop.tar" + - bash: | + set -x + $TAR_COMMAND --dereference --exclude=.git --exclude=citools $SUBMODULES_EXCLUDES -cf $TEMP/drop.tar . + $TAR_COMMAND --append --file=$TEMP/drop.tar citools + - task: PublishPipelineArtifact@0 + inputs: + artifactName: $(System.JobDisplayName) + targetPath: $(TAR_PATH) + strategy: + matrix: + # 32/64 bit MSVC tests + x86_64-msvc-build: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + SCRIPT: make ci-test-prepare + +- job: Windows_test + dependsOn: Windows_build + timeoutInMinutes: 600 + variables: + TAR_COMMAND: tar + SKIP_PREP: 1 + KEEP_STAGE: '--keep-stage 0 --keep-stage 1' + SKIP_LLVM_BUILD: 1 + pool: + vmImage: 'vs2017-win2016' + steps: + - checkout: self + fetchDepth: 2 + - script: | + set MSYS_PATH=%CD%\citools\msys64 + set PATH=%MSYS_PATH%\usr\bin;%PATH% + where rev + rev --help + where make + echo ##vso[task.prependpath]%MSYS_PATH%\usr\bin + displayName: Install msys2 + + # # If we need to download a custom MinGW, do so here and set the path + # # appropriately. + # # + # # Note that this *also* means that we're not using what is typically + # # /mingw32/bin/python2.7.exe, which is a "correct" python interpreter where + # # /usr/bin/python2.7.exe is not. To ensure we use the right interpreter we + # # move `C:\Python27` ahead in PATH and then also make sure the `python2.7.exe` + # # file exists in there (which it doesn't by default). + # - script: | + # powershell -Command "iwr -outf %MINGW_ARCHIVE% %MINGW_URL%/%MINGW_ARCHIVE%" + # 7z x -y %MINGW_ARCHIVE% > nul + # echo ##vso[task.prependpath]%CD%\%MINGW_DIR%\bin + # condition: and(succeeded(), ne(variables['MINGW_URL'],'')) + # displayName: Download custom MinGW + + # If we're compiling for MSVC then we, like most other distribution builders, + # switch to clang as the compiler. This'll allow us eventually to enable LTO + # amongst LLVM and rustc. Note that we only do this on MSVC as I don't think + # clang has an output mode compatible with MinGW that we need. If it does we + # should switch to clang for MinGW as well! + # + # Note that the LLVM installer is an NSIS installer + # + # Original downloaded here came from + # http://releases.llvm.org/7.0.0/LLVM-7.0.0-win64.exe + - script: | + # powershell -Command "iwr -outf LLVM-7.0.0-win64.exe https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/LLVM-7.0.0-win64.exe" + # .\LLVM-7.0.0-win64.exe /S /NCRC /D=C:\clang-rust + set CLANG_DIR=%CD%\citools\clang-rust + set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --set llvm.clang-cl=%CLANG_DIR%\bin\clang-cl.exe + echo ##vso[task.setvariable variable=RUST_CONFIGURE_ARGS]%RUST_CONFIGURE_ARGS% + condition: and(succeeded(), eq(variables['MINGW_URL'],'')) + displayName: Download clang + + # # Here we do a pretty heinous thing which is to mangle the MinGW installation + # # we just had above. Currently, as of this writing, we're using MinGW-w64 + # # builds of gcc, and that's currently at 6.3.0. We use 6.3.0 as it appears to + # # be the first version which contains a fix for #40546, builds randomly + # # failing during LLVM due to ar.exe/ranlib.exe failures. + # # + # # Unfortunately, though, 6.3.0 *also* is the first version of MinGW-w64 builds + # # to contain a regression in gdb (#40184). As a result if we were to use the + # # gdb provided (7.11.1) then we would fail all debuginfo tests. + # # + # # In order to fix spurious failures (pretty high priority) we use 6.3.0. To + # # avoid disabling gdb tests we download an *old* version of gdb, specifically + # # that found inside the 6.2.0 distribution. We then overwrite the 6.3.0 gdb + # # with the 6.2.0 gdb to get tests passing. + # # + # # Note that we don't literally overwrite the gdb.exe binary because it appears + # # to just use gdborig.exe, so that's the binary we deal with instead. + # - script: | + # echo ON + # powershell -Command "iwr -outf 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_URL%/2017-04-20-%MSYS_BITS%bit-gdborig.exe" + # mv 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_DIR%\bin\gdborig.exe + # condition: and(succeeded(), ne(variables['MINGW_URL'],'')) + # displayName: Override with 6.3.0 gdb with 6.2.0 gdb + + # Otherwise pull in the MinGW installed on appveyor + - script: | + echo Find mingw + set PATH | findstr /i msys + set PATH | findstr /i mingw + echo ##vso[task.prependpath]C:\msys64\mingw%MSYS_BITS%\bin + condition: and(succeeded(), eq(variables['MINGW_URL'],'')) + displayName: Add MinGW to path + + - script: | + copy C:\Python27amd64\python.exe C:\Python27amd64\python2.7.exe + echo ##vso[task.prependpath]C:\Python27amd64 + displayName: Prefer the "native" Python as LLVM has trouble building with MSYS sometimes + + - script: | + REM md sccache + REM powershell -Command "iwr -outf sccache\sccache.exe https://rustlangtools.blob.core.windows.net/public/stable-x86_64-pc-windows-msvc.sccache.exe" + echo ##vso[task.prependpath]%CD%\sccache + displayName: Download and install sccache + + # Note that this is originally from the github releases patch of Ninja + - script: | + REM md ninja + REM powershell -Command "iwr -outf 2017-03-15-ninja-win.zip https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-03-15-ninja-win.zip" + REM 7z x -oninja 2017-03-15-ninja-win.zip + REM del 2017-03-15-ninja-win.zip + set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --enable-ninja + echo ##vso[task.setvariable variable=RUST_CONFIGURE_ARGS]%RUST_CONFIGURE_ARGS% + echo ##vso[task.prependpath]%CD%\ninja + displayName: Download and install ninja + + - script: | + IF NOT "%DISABLE_DISK_SPACE_HACK%"=="1" ( + IF NOT EXIST build ( + mkdir c:\MORE_SPACE + mklink /J build c:\MORE_SPACE + ) + ) + - script: | + echo on + echo ##vso[task.setvariable variable=TAR_FOLDER_PATH]%TEMP% + - template: steps/show-environment-variables.yml + - task: DownloadPipelineArtifact@1 + inputs: + artifactName: $(ARTIFACT_NAME) + downloadPath: $(TAR_FOLDER_PATH) + # - task: DownloadPipelineArtifact@1 + # inputs: + # artifactName: $(ARTIFACT_NAME) + # downloadPath: $(TAR_FOLDER_PATH) + # buildType: specific + # project: rust + # pipeline: 8 + # buildVersionToDownload: specific + # buildId: 200 + # # https://dev.azure.com/rust-lang-azure/rust/_build/results?buildId=145 + + # - template: steps/macos.yml + - bash: $TAR_COMMAND -tvf $TEMP/drop.tar + - bash: $TAR_COMMAND --touch -xf $TEMP/drop.tar + - bash: rm $TEMP/drop.tar + - script: | + REM mkdir handle + REM powershell -Command "iwr -outf 2017-05-15-Handle.zip https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-05-15-Handle.zip" + REM 7z x -ohandle 2017-05-15-Handle.zip + REM del 2017-05-15-Handle.zip + set PATH=%PATH%;%CD%\handle + handle.exe -accepteula -help + echo ##vso[task.setvariable variable=PATH]%PATH% + displayName: Help debug handle issues + - script: | + REM echo force the specific VS version https://github.com/johnterickson/rust/issues/8 + IF "%VCVARS_BAT%" NEQ "" ( + CALL "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\%VCVARS_BAT%" + ) + + where sccache + where rev + set | findstr /v SCCACHE_AZURE_CONNECTION_STRING + + if not exist D:\cache\rustsrc\NUL mkdir D:\cache\rustsrc + + sh src/ci/run.sh + env: + CI: true + CI_JOB_NAME: $(System.JobDisplayName) + SRC: . + NO_CCACHE: 1 + + # explicitly decrypt secret variables + # see https://docs.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch + SCCACHE_AZURE_CONNECTION_STRING: $(SCCACHE_AZURE_CONNECTION_STRING_SECRET) + DOCKER_LAYER_CACHE_AZURE_STORAGE_ACCOUNT_KEY: $(DOCKER_LAYER_CACHE_AZURE_STORAGE_ACCOUNT_KEY_SECRET) + displayName: Run script + + strategy: + matrix: + # 32/64 bit MSVC tests + x86_64-msvc-A: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + ARTIFACT_NAME: x86_64-msvc-build + SCRIPT: make ci-resume-subset-A + x86_64-msvc-B: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + ARTIFACT_NAME: x86_64-msvc-build + SCRIPT: make ci-resume-subset-B + x86_64-msvc-C: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + ARTIFACT_NAME: x86_64-msvc-build + SCRIPT: make ci-resume-subset-C + x86_64-msvc-D: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + ARTIFACT_NAME: x86_64-msvc-build + SCRIPT: make ci-resume-subset-D + x86_64-msvc-E: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + ARTIFACT_NAME: x86_64-msvc-build + SCRIPT: make ci-resume-subset-E + x86_64-msvc-F: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + ARTIFACT_NAME: x86_64-msvc-build + SCRIPT: make ci-resume-subset-F + x86_64-msvc-G: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + ARTIFACT_NAME: x86_64-msvc-build + SCRIPT: make ci-resume-subset-G + x86_64-msvc-H: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + ARTIFACT_NAME: x86_64-msvc-build + SCRIPT: make ci-resume-subset-H + +# macOS JOBS +- job: macOS + timeoutInMinutes: 600 + variables: + TAR_COMMAND: gtar + pool: + vmImage: macos-10.13 + steps: + - checkout: self + fetchDepth: 2 + - template: steps/macos.yml + strategy: + matrix: + x86_64-apple: + RUST_CHECK_TARGET: check + RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + +- job: macOS_build + timeoutInMinutes: 600 + variables: + TAR_COMMAND: gtar + pool: + vmImage: macos-10.13 + steps: + - checkout: self + fetchDepth: 2 + - template: steps/macos.yml + - script: | + set -x + + git submodule + export SUBMODULES_EXCLUDES=$(git submodule | grep -Eow 'src/[^ ]+' | sed 's/\(.*\)/--exclude=\1\/\.git/') + echo $SUBMODULES_EXCLUDES + + $TAR_COMMAND --exclude=.git $SUBMODULES_EXCLUDES -cf /tmp/drop.tar . + - task: PublishPipelineArtifact@0 + inputs: + artifactName: $(System.JobDisplayName) + targetPath: '/tmp/drop.tar' + + strategy: + matrix: + # macOS builders. These are placed near the beginning because they are very + # slow to run. + + # OSX builders running tests, these run the full test suite. + # NO_DEBUG_ASSERTIONS=1 to make them go faster, but also do have some + # runners that run `//ignore-debug` tests. + # + # Note that the compiler is compiled to target 10.8 here because the Xcode + # version that we're using, 8.2, cannot compile LLVM for OSX 10.7. + x86_64-apple-build: + RUST_CHECK_TARGET: check + RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + SCRIPT: make ci-test-prepare + +- job: macOS_test + dependsOn: macOS_build + timeoutInMinutes: 600 + variables: + TAR_COMMAND: gtar + SKIP_PREP: 1 + KEEP_STAGE: '--keep-stage 0 --keep-stage 1' + SKIP_LLVM_BUILD: 1 + pool: + vmImage: macos-10.13 + steps: + - checkout: self + fetchDepth: 2 + - bash: brew install gnu-tar + displayName: install a tar that works well + + - template: steps/show-disk-usage.yml + + - task: DownloadPipelineArtifact@1 + inputs: + artifactName: $(ARTIFACT_NAME) + downloadPath: $(System.DefaultWorkingDirectory) + # - task: DownloadPipelineArtifact@1 + # inputs: + # artifactName: $(ARTIFACT_NAME) + # downloadPath: $(System.DefaultWorkingDirectory) + # buildType: specific + # project: rust + # pipeline: 8 + # buildVersionToDownload: specific + # buildId: 200 + + # - template: steps/macos.yml + - template: steps/show-disk-usage.yml + - bash: $TAR_COMMAND -tvf ./drop.tar + - bash: $TAR_COMMAND -xf ./drop.tar + - bash: rm ./drop.tar + - template: steps/show-disk-usage.yml + - bash: | + export PATH=$PATH:$HOME/.local/bin:$HOME/Library/Python/2.7/bin/ + mkdir -p $HOME/rustsrc + echo "##vso[task.setvariable variable=PATH;]$PATH" + + curl -fo /usr/local/bin/sccache https://rustlangtools.blob.core.windows.net/public/stable-x86_64-apple-darwin.sccache + chmod +x /usr/local/bin/sccache + + curl -fo /usr/local/bin/stamp https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-03-17-stamp-x86_64-apple-darwin + chmod +x /usr/local/bin/stamp + + export CC=`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang + echo "##vso[task.setvariable variable=CC]$CC" + + export CXX=`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang++ + echo "##vso[task.setvariable variable=CXX]$CXX" + + echo "##vso[task.setvariable variable=AR]ar" + displayName: Prep + + - bash: brew install gnu-tar + displayName: install a tar that works well + + - bash: | + brew update + brew install xz + brew install swig + condition: and(succeeded(), eq(variables['RUST_CHECK_TARGET'],'dist')) + displayName: Install xz and swigw + + - bash: | + export RUN_SCRIPT="src/ci/run.sh" + echo "##vso[task.setvariable variable=RUN_SCRIPT]$RUN_SCRIPT" + displayName: Prepare run script (init and run) + + - template: steps/show-environment-variables.yml + + - template: steps/verify-publish-toolstate.yml + + - template: steps/run-script.yml + + strategy: + matrix: + # macOS builders. These are placed near the beginning because they are very + # slow to run. + + # OSX builders running tests, these run the full test suite. + # NO_DEBUG_ASSERTIONS=1 to make them go faster, but also do have some + # runners that run `//ignore-debug` tests. + # + # Note that the compiler is compiled to target 10.8 here because the Xcode + # version that we're using, 8.2, cannot compile LLVM for OSX 10.7. + x86_64-apple-A: + RUST_CHECK_TARGET: check + RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + ARTIFACT_NAME: x86_64-apple-build + SCRIPT: make ci-resume-subset-A + x86_64-apple-B: + RUST_CHECK_TARGET: check + RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + ARTIFACT_NAME: x86_64-apple-build + SCRIPT: make ci-resume-subset-B + x86_64-apple-C: + RUST_CHECK_TARGET: check + RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + ARTIFACT_NAME: x86_64-apple-build + SCRIPT: make ci-resume-subset-C + x86_64-apple-D: + RUST_CHECK_TARGET: check + RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + ARTIFACT_NAME: x86_64-apple-build + SCRIPT: make ci-resume-subset-D + x86_64-apple-E: + RUST_CHECK_TARGET: check + RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + ARTIFACT_NAME: x86_64-apple-build + SCRIPT: make ci-resume-subset-E + x86_64-apple-F: + RUST_CHECK_TARGET: check + RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + ARTIFACT_NAME: x86_64-apple-build + SCRIPT: make ci-resume-subset-F + x86_64-apple-G: + RUST_CHECK_TARGET: check + RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + ARTIFACT_NAME: x86_64-apple-build + SCRIPT: make ci-resume-subset-G + x86_64-apple-H: + RUST_CHECK_TARGET: check + RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + ARTIFACT_NAME: x86_64-apple-build + SCRIPT: make ci-resume-subset-H diff --git a/.azure-pipelines/auto.yml b/.azure-pipelines/auto.yml new file mode 100644 index 000000000000..818b613740e6 --- /dev/null +++ b/.azure-pipelines/auto.yml @@ -0,0 +1,361 @@ +# +# Azure Pipelines "auto" branch build for Rust on Linux, macOS, and Windows. +# +# Notes: +# To get sccache working, I (John Erickson) had to build it with the Azure feature enabled +# and with openssl statically-linked for Linux. +# Here's the build (with a backpointer to source) of where the bits came from: +# https://dev.azure.com/johnterickson/rust-lang/_build/results?buildId=275 + +pr: none +# trigger: +# - auto + +variables: +- group: caching + +jobs: +- job: Linux + timeoutInMinutes: 600 + pool: + vmImage: ubuntu-16.04 + steps: + - template: steps/linux.yml + strategy: + matrix: + x86_64-gnu-llvm-6.0: + IMAGE: x86_64-gnu-llvm-6.0 + RUST_BACKTRACE: 1 + + dist-x86_64-linux: + IMAGE: dist-x86_64-linux + DEPLOY: 1 + + # "alternate" deployments, these are "nightlies" but have LLVM assertions + # turned on, they're deployed to a different location primarily for + # additional testing. + dist-x86_64-linux-alt: + IMAGE: dist-x86_64-linux + DEPLOY_ALT: 1 + + # Linux builders, remaining docker images + arm-android: + IMAGE: arm-android + + armhf-gnu: + IMAGE: armhf-gnu + + dist-various-1: + IMAGE: dist-various-1 + DEPLOY: 1 + + dist-various-2: + IMAGE: dist-various-2 + DEPLOY: 1 + + dist-aarch64-linux: + IMAGE: dist-aarch64-linux + DEPLOY: 1 + + dist-android: + IMAGE: dist-android + DEPLOY: 1 + + dist-arm-linux: + IMAGE: dist-arm-linux + DEPLOY: 1 + + dist-armhf-linux: + IMAGE: dist-armhf-linux + DEPLOY: 1 + + dist-armv7-linux: + IMAGE: dist-armv7-linux + DEPLOY: 1 + + dist-i586-gnu-i586-i686-musl: + IMAGE: dist-i586-gnu-i586-i686-musl + DEPLOY: 1 + + dist-i686-freebsd: + IMAGE: dist-i686-freebsd + DEPLOY: 1 + + dist-i686-linux: + IMAGE: dist-i686-linux + DEPLOY: 1 + + dist-mips-linux: + IMAGE: dist-mips-linux + DEPLOY: 1 + + dist-mips64-linux: + IMAGE: dist-mips64-linux + DEPLOY: 1 + + dist-mips64el-linux: + IMAGE: dist-mips64el-linux + DEPLOY: 1 + + dist-mipsel-linux: + IMAGE: dist-mipsel-linux + DEPLOY: 1 + + dist-powerpc-linux: + IMAGE: dist-powerpc-linux + DEPLOY: 1 + + dist-powerpc64-linux: + IMAGE: dist-powerpc64-linux + DEPLOY: 1 + + dist-powerpc64le-linux: + IMAGE: dist-powerpc64le-linux + DEPLOY: 1 + + dist-s390x-linux: + IMAGE: dist-s390x-linux + DEPLOY: 1 + + dist-x86_64-freebsd: + IMAGE: dist-x86_64-freebsd + DEPLOY: 1 + + dist-x86_64-musl: + IMAGE: dist-x86_64-musl + DEPLOY: 1 + + dist-x86_64-netbsd: + IMAGE: dist-x86_64-netbsd + DEPLOY: 1 + + asmjs: + IMAGE: asmjs + i686-gnu-1: + IMAGE: i686-gnu-1 + i686-gnu-2: + IMAGE: i686-gnu-2 + i686-gnu-nopt: + IMAGE: i686-gnu-nopt + test-various: + IMAGE: test-various + x86_64-gnu: + IMAGE: x86_64-gnu + x86_64-gnu-full-bootstrap: + IMAGE: x86_64-gnu-full-bootstrap + x86_64-gnu-aux: + IMAGE: x86_64-gnu-aux + x86_64-gnu-tools: + IMAGE: x86_64-gnu-tools + # FIXME if: branch = auto OR (type = pull_request AND commit_message =~ /(?i:^update.*\b(rls|rustfmt|clippy|miri|cargo)\b)/) + x86_64-gnu-debug: + IMAGE: x86_64-gnu-debug + x86_64-gnu-nopt: + IMAGE: x86_64-gnu-nopt + x86_64-gnu-distcheck: + IMAGE: x86_64-gnu-distcheck + mingw-check: + IMAGE: mingw-check + +- job: macOS + timeoutInMinutes: 600 + pool: + vmImage: macos-10.13 + steps: + - checkout: self + fetchDepth: 2 + - template: steps/macos.yml + strategy: + matrix: + dist-x86_64-apple-alt: + RUST_CHECK_TARGET: dist + RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --enable-lldb --set rust.jemalloc + DEPLOY_ALT: 1 + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + + # macOS builders. These are placed near the beginning because they are very + # slow to run. + + # OSX builders running tests, these run the full test suite. + # NO_DEBUG_ASSERTIONS=1 to make them go faster, but also do have some + # runners that run `//ignore-debug` tests. + # + # Note that the compiler is compiled to target 10.8 here because the Xcode + # version that we're using, 8.2, cannot compile LLVM for OSX 10.7. + x86_64-apple: + RUST_CHECK_TARGET: check + RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + + i686-apple: + RUST_CHECK_TARGET: check + RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + + dist-i686-apple: + RUST_CHECK_TARGET: dist + RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb --set rust.jemalloc + DEPLOY: 1 + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + DIST_REQUIRE_ALL_TOOLS: 1 + + dist-x86_64-apple: + RUST_CHECK_TARGET: dist + RUST_CONFIGURE_ARGS: --target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --enable-lldb --set rust.jemalloc + DEPLOY: 1 + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + DIST_REQUIRE_ALL_TOOLS: 1 + +- job: Windows + timeoutInMinutes: 600 + pool: + vmImage: 'vs2017-win2016' + steps: + - template: steps/windows.yml + strategy: + matrix: + # 32/64 bit MSVC tests + x86_64-msvc-1: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + SCRIPT: make ci-subset-1 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + x86_64-msvc-2: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + SCRIPT: make ci-subset-2 + i686-msvc-1: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc + SCRIPT: make ci-subset-1 + i686-msvc-2: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc + SCRIPT: make ci-subset-2 + # MSVC aux tests + x86_64-msvc-aux: + MSYS_BITS: 64 + RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + x86_64-msvc-cargo: + MSYS_BITS: 64 + SCRIPT: python x.py test src/tools/cargotest src/tools/cargo + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + VCVARS_BAT: vcvars64.bat + # MSVC tools tests + x86_64-msvc-tools: + MSYS_BITS: 64 + SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri + + # 32/64-bit MinGW builds. + # + # We are using MinGW with posix threads since LLVM does not compile with + # the win32 threads version due to missing support for C++'s std::thread. + # + # Instead of relying on the MinGW version installed on appveryor we download + # and install one ourselves so we won't be surprised by changes to appveyor's + # build image. + # + # Finally, note that the downloads below are all in the `rust-lang-ci` S3 + # bucket, but they cleraly didn't originate there! The downloads originally + # came from the mingw-w64 SourceForge download site. Unfortunately + # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. + i686-mingw-1: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + SCRIPT: make ci-subset-1 + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z + MINGW_DIR: mingw32 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + i686-mingw-2: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + SCRIPT: make ci-subset-2 + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z + MINGW_DIR: mingw32 + x86_64-mingw-1: + MSYS_BITS: 64 + SCRIPT: make ci-subset-1 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z + MINGW_DIR: mingw64 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + x86_64-mingw-2: + MSYS_BITS: 64 + SCRIPT: make ci-subset-2 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z + MINGW_DIR: mingw64 + + # 32/64 bit MSVC and GNU deployment + dist-x86_64-msvc: + RUST_CONFIGURE_ARGS: > + --build=x86_64-pc-windows-msvc + --target=x86_64-pc-windows-msvc,aarch64-pc-windows-msvc + --enable-full-tools + --enable-profiler + SCRIPT: python x.py dist + DIST_REQUIRE_ALL_TOOLS: 1 + DEPLOY: 1 + dist-i686-msvc: + RUST_CONFIGURE_ARGS: > + --build=i686-pc-windows-msvc + --target=i586-pc-windows-msvc + --enable-full-tools + --enable-profiler + SCRIPT: python x.py dist + DIST_REQUIRE_ALL_TOOLS: 1 + DEPLOY: 1 + dist-i686-mingw: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools + SCRIPT: python x.py dist + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z + MINGW_DIR: mingw32 + DIST_REQUIRE_ALL_TOOLS: 1 + DEPLOY: 1 + dist-x86_64-mingw: + MSYS_BITS: 64 + SCRIPT: python x.py dist + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z + MINGW_DIR: mingw64 + DIST_REQUIRE_ALL_TOOLS: 1 + DEPLOY: 1 + + # "alternate" deployment, see .travis.yml for more info + dist-x86_64-msvc-alt: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler + SCRIPT: python x.py dist + DEPLOY_ALT: 1 diff --git a/.azure-pipelines/master.yml b/.azure-pipelines/master.yml new file mode 100644 index 000000000000..e30c73c5e924 --- /dev/null +++ b/.azure-pipelines/master.yml @@ -0,0 +1,22 @@ +# +# Azure Pipelines job to publish toolstate. Only triggers on pushes to master. +# + +pr: none +trigger: +- master + +pool: + vmImage: ubuntu-16.04 + +steps: +- checkout: self + fetchDepth: 2 + +- script: | + export MESSAGE_FILE=$(mktemp -t msg.XXXXXX) + . src/ci/docker/x86_64-gnu-tools/repo.sh + commit_toolstate_change "$MESSAGE_FILE" "$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" "$(git log --format=%s -n1 HEAD)" "$MESSAGE_FILE" "$TOOLSTATE_REPO_ACCESS_TOKEN" + displayName: Publish toolstate + env: + TOOLSTATE_REPO_ACCESS_TOKEN: $(TOOLSTATE_REPO_ACCESS_TOKEN_SECRET) diff --git a/.azure-pipelines/pr.yml b/.azure-pipelines/pr.yml new file mode 100644 index 000000000000..a2a4fc251668 --- /dev/null +++ b/.azure-pipelines/pr.yml @@ -0,0 +1,26 @@ +# +# Azure Pipelines pull request build for Rust +# + +trigger: none +pr: +- master # FIXME: really just want any branch, but want an explicit "pr" property set so it's clear + +variables: +- group: caching-pr + +jobs: +- job: Linux + timeoutInMinutes: 600 + pool: + vmImage: ubuntu-16.04 + steps: + - template: steps/linux.yml + strategy: + matrix: + x86_64-gnu-llvm-6.0: + RUST_BACKTRACE: 1 + + x86_64-gnu-tools: {} + # if: branch = auto OR (type = pull_request AND commit_message =~ /(?i:^update.*\b(rls|rustfmt|clippy|miri|cargo)\b)/) + mingw-check: {} diff --git a/.azure-pipelines/steps/linux.yml b/.azure-pipelines/steps/linux.yml new file mode 100644 index 000000000000..288c4c9854e5 --- /dev/null +++ b/.azure-pipelines/steps/linux.yml @@ -0,0 +1,42 @@ +steps: +- checkout: self + fetchDepth: 2 + +- template: show-environment-variables.yml +- template: show-disk-usage.yml + +- bash: | + sudo apt install gdb + + curl -fo $HOME/stamp https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-03-17-stamp-x86_64-unknown-linux-musl + chmod +x $HOME/stamp + + export PATH=$PATH:$HOME/.local/bin:$HOME/Library/Python/2.7/bin/:$HOME + echo "##vso[task.setvariable variable=PATH;]$PATH" + + mkdir -p $HOME/rustsrc + displayName: Prep + +# FIXME(#46924): these two commands are required to enable IPv6, +# they shouldn't exist, please revert once more official solutions appeared. +# see https://github.com/travis-ci/travis-ci/issues/8891#issuecomment-353403729 +- bash: | + echo '{"ipv6":true,"fixed-cidr-v6":"fd9a:8454:6789:13f7::/64"}' | sudo tee /etc/docker/daemon.json + sudo service docker restart + displayName: Enable IPv6 + +# FIXME: using the job display name feels brittle. Is there a better variable that represents the current matrix key? +- bash: | + export RUN_SCRIPT="$BUILD_SOURCESDIRECTORY/src/ci/init_repo.sh . $HOME/rustsrc && src/ci/docker/run.sh $IMAGE" + echo "##vso[task.setvariable variable=IMAGE]$IMAGE" + echo "##vso[task.setvariable variable=RUN_SCRIPT]$RUN_SCRIPT" + displayName: Prepare run script + +- template: show-environment-variables.yml + +- bash: sudo sh -c 'echo "/checkout/obj/cores/core.%p.%E" > /proc/sys/kernel/core_pattern' + displayName: Enable core dump + +- template: verify-publish-toolstate.yml + +- template: run-script.yml diff --git a/.azure-pipelines/steps/macos.yml b/.azure-pipelines/steps/macos.yml new file mode 100644 index 000000000000..a217df6f3081 --- /dev/null +++ b/.azure-pipelines/steps/macos.yml @@ -0,0 +1,47 @@ +steps: +- template: show-disk-usage.yml + +- bash: | + export PATH=$PATH:$HOME/.local/bin:$HOME/Library/Python/2.7/bin/ + mkdir -p $HOME/rustsrc + echo "##vso[task.setvariable variable=PATH;]$PATH" + + curl -fo /usr/local/bin/sccache https://rustlangtools.blob.core.windows.net/public/stable-x86_64-apple-darwin.sccache + chmod +x /usr/local/bin/sccache + + curl -fo /usr/local/bin/stamp https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-03-17-stamp-x86_64-apple-darwin + chmod +x /usr/local/bin/stamp + + export CC=`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang + echo "##vso[task.setvariable variable=CC]$CC" + + export CXX=`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang++ + echo "##vso[task.setvariable variable=CXX]$CXX" + + echo "##vso[task.setvariable variable=AR]ar" + displayName: Prep + +- bash: brew install gnu-tar + displayName: install a tar that works well + +- bash: | + curl -f http://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz | tar xJf - + displayName: Download clang + +- bash: | + brew update + brew install xz + brew install swig + condition: and(succeeded(), eq(variables['RUST_CHECK_TARGET'],'dist')) + displayName: Install xz and swigw + +- bash: | + export RUN_SCRIPT="$BUILD_SOURCESDIRECTORY/src/ci/init_repo.sh . $HOME/rustsrc && src/ci/run.sh" + echo "##vso[task.setvariable variable=RUN_SCRIPT]$RUN_SCRIPT" + displayName: Prepare run script (init and run) + +- template: show-environment-variables.yml + +- template: verify-publish-toolstate.yml + +- template: run-script.yml diff --git a/.azure-pipelines/steps/run-script.yml b/.azure-pipelines/steps/run-script.yml new file mode 100644 index 000000000000..4ab3e2e06d36 --- /dev/null +++ b/.azure-pipelines/steps/run-script.yml @@ -0,0 +1,24 @@ +steps: +# Log time information from this machine and an external machine for insight into possible +# clock drift. Timezones don't matter since relative deltas give all the necessary info. +- bash: | + date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true) + displayName: Log time information (before) + +- bash: | + which sccache + stamp sh -x -c "$RUN_SCRIPT" + env: + CI: true + CI_JOB_NAME: $(IMAGE) + SRC: . + + # Explicitly decrypt secret variables + # See https://docs.microsoft.com/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch#secret-variables + SCCACHE_AZURE_CONNECTION_STRING: $(SCCACHE_AZURE_CONNECTION_STRING_SECRET) + DOCKER_LAYER_CACHE_AZURE_STORAGE_ACCOUNT_KEY: $(DOCKER_LAYER_CACHE_AZURE_STORAGE_ACCOUNT_KEY_SECRET) + displayName: Run script + +- bash: | + date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true) + displayName: Log time information (after) diff --git a/.azure-pipelines/steps/show-disk-usage.yml b/.azure-pipelines/steps/show-disk-usage.yml new file mode 100644 index 000000000000..902d80364717 --- /dev/null +++ b/.azure-pipelines/steps/show-disk-usage.yml @@ -0,0 +1,5 @@ +steps: +- bash: | + df -h + du . | sort -nr | head -n100 + displayName: Show disk usage diff --git a/.azure-pipelines/steps/show-environment-variables.yml b/.azure-pipelines/steps/show-environment-variables.yml new file mode 100644 index 000000000000..f6ed063ec6be --- /dev/null +++ b/.azure-pipelines/steps/show-environment-variables.yml @@ -0,0 +1,3 @@ +steps: +- bash: printenv | sort + displayName: Show environment variables \ No newline at end of file diff --git a/.azure-pipelines/steps/verify-publish-toolstate.yml b/.azure-pipelines/steps/verify-publish-toolstate.yml new file mode 100644 index 000000000000..5531c90e090a --- /dev/null +++ b/.azure-pipelines/steps/verify-publish-toolstate.yml @@ -0,0 +1,9 @@ +steps: +- bash: | + git clone --depth=1 https://github.com/rust-lang-nursery/rust-toolstate.git + cd rust-toolstate + python2.7 "$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" "$(git log --format=%s -n1 HEAD)" "" "" + cd .. + rm -rf rust-toolstate + condition: and(succeeded(), eq(variables['IMAGE'], 'mingw-check')) + displayName: Verify the publish_toolstate script works diff --git a/.azure-pipelines/steps/windows.yml b/.azure-pipelines/steps/windows.yml new file mode 100644 index 000000000000..5dcba664bee8 --- /dev/null +++ b/.azure-pipelines/steps/windows.yml @@ -0,0 +1,160 @@ +steps: +- checkout: self + fetchDepth: 2 + +- bash: | + set -x + git submodule + export SUBMODULES_EXCLUDES=$(git submodule | grep -Eow 'src/[^ ]+' | sed 's/\(.*\)/--exclude=\1\/\.git/') + echo "##vso[task.setvariable variable=SUBMODULES_EXCLUDES;]$SUBMODULES_EXCLUDES" + +- script: | + REM echo hack as drive D is too small + IF NOT "%DISABLE_DISK_SPACE_HACK%"=="1" ( + mkdir c:\MORE_SPACE + mklink /J build c:\MORE_SPACE + ) + +- script: | + set MSYS_PATH=%CD%\citools\msys64 + choco install msys2 --params="/InstallDir:%MSYS_PATH% /NoPath" -y + set PATH=%MSYS_PATH%\usr\bin;%PATH% + pacman -S --noconfirm --needed base-devel ca-certificates make diffutils tar + IF "%MINGW_URL%"=="" ( + IF "%MSYS_BITS%"=="32" pacman -S --noconfirm --needed mingw-w64-i686-toolchain mingw-w64-i686-cmake mingw-w64-i686-gcc mingw-w64-i686-python2 + IF "%MSYS_BITS%"=="64" pacman -S --noconfirm --needed mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake mingw-w64-x86_64-gcc mingw-w64-x86_64-python2 + ) + where rev + rev --help + where make + + echo ##vso[task.setvariable variable=MSYS_PATH]%MSYS_PATH% + echo ##vso[task.prependpath]%MSYS_PATH%\usr\bin + displayName: Install msys2 + +# If we need to download a custom MinGW, do so here and set the path +# appropriately. +# +# Note that this *also* means that we're not using what is typically +# /mingw32/bin/python2.7.exe, which is a "correct" python interpreter where +# /usr/bin/python2.7.exe is not. To ensure we use the right interpreter we +# move `C:\Python27` ahead in PATH and then also make sure the `python2.7.exe` +# file exists in there (which it doesn't by default). +- script: | + powershell -Command "iwr -outf %MINGW_ARCHIVE% %MINGW_URL%/%MINGW_ARCHIVE%" + 7z x -y %MINGW_ARCHIVE% > nul + echo ##vso[task.prependpath]%CD%\%MINGW_DIR%\bin + condition: and(succeeded(), ne(variables['MINGW_URL'],'')) + displayName: Download custom MinGW + +# If we're compiling for MSVC then we, like most other distribution builders, +# switch to clang as the compiler. This'll allow us eventually to enable LTO +# amongst LLVM and rustc. Note that we only do this on MSVC as I don't think +# clang has an output mode compatible with MinGW that we need. If it does we +# should switch to clang for MinGW as well! +# +# Note that the LLVM installer is an NSIS installer +# +# Original downloaded here came from +# http://releases.llvm.org/7.0.0/LLVM-7.0.0-win64.exe +- script: | + powershell -Command "iwr -outf %TEMP%\LLVM-7.0.0-win64.exe https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/LLVM-7.0.0-win64.exe" + set CLANG_DIR=%CD%\citools\clang-rust + %TEMP%\LLVM-7.0.0-win64.exe /S /NCRC /D=%CLANG_DIR% + set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --set llvm.clang-cl=%CLANG_DIR%\bin\clang-cl.exe + echo ##vso[task.setvariable variable=RUST_CONFIGURE_ARGS]%RUST_CONFIGURE_ARGS% + condition: and(succeeded(), eq(variables['MINGW_URL'],'')) + displayName: Download clang + +# Here we do a pretty heinous thing which is to mangle the MinGW installation +# we just had above. Currently, as of this writing, we're using MinGW-w64 +# builds of gcc, and that's currently at 6.3.0. We use 6.3.0 as it appears to +# be the first version which contains a fix for #40546, builds randomly +# failing during LLVM due to ar.exe/ranlib.exe failures. +# +# Unfortunately, though, 6.3.0 *also* is the first version of MinGW-w64 builds +# to contain a regression in gdb (#40184). As a result if we were to use the +# gdb provided (7.11.1) then we would fail all debuginfo tests. +# +# In order to fix spurious failures (pretty high priority) we use 6.3.0. To +# avoid disabling gdb tests we download an *old* version of gdb, specifically +# that found inside the 6.2.0 distribution. We then overwrite the 6.3.0 gdb +# with the 6.2.0 gdb to get tests passing. +# +# Note that we don't literally overwrite the gdb.exe binary because it appears +# to just use gdborig.exe, so that's the binary we deal with instead. +- script: | + echo ON + powershell -Command "iwr -outf 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_URL%/2017-04-20-%MSYS_BITS%bit-gdborig.exe" + mv 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_DIR%\bin\gdborig.exe + condition: and(succeeded(), ne(variables['MINGW_URL'],'')) + displayName: Override with 6.3.0 gdb with 6.2.0 gdb + +# Otherwise pull in the MinGW installed on appveyor +- script: | + echo Find mingw + set PATH | findstr /i msys + set PATH | findstr /i mingw + echo ##vso[task.prependpath]%MSYS_PATH%\mingw%MSYS_BITS%\bin + condition: and(succeeded(), eq(variables['MINGW_URL'],'')) + displayName: Add MinGW to path + +- script: | + copy C:\Python27amd64\python.exe C:\Python27amd64\python2.7.exe + echo ##vso[task.prependpath]C:\Python27amd64 + displayName: Prefer the "native" Python as LLVM has trouble building with MSYS sometimes + +- script: | + md sccache + powershell -Command "iwr -outf sccache\sccache.exe https://rustlangtools.blob.core.windows.net/public/stable-x86_64-pc-windows-msvc.sccache.exe" + echo ##vso[task.prependpath]%CD%\sccache + displayName: Download and install sccache + +# Note that this is originally from the github releases patch of Ninja +- script: | + md ninja + powershell -Command "iwr -outf 2017-03-15-ninja-win.zip https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-03-15-ninja-win.zip" + 7z x -oninja 2017-03-15-ninja-win.zip + del 2017-03-15-ninja-win.zip + set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --enable-ninja + echo ##vso[task.setvariable variable=RUST_CONFIGURE_ARGS]%RUST_CONFIGURE_ARGS% + echo ##vso[task.prependpath]%CD%\ninja + displayName: Download and install ninja + +- script: | + mkdir handle + powershell -Command "iwr -outf 2017-05-15-Handle.zip https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-05-15-Handle.zip" + 7z x -ohandle 2017-05-15-Handle.zip + del 2017-05-15-Handle.zip + set PATH=%PATH%;%CD%\handle + handle.exe -accepteula -help + echo ##vso[task.setvariable variable=PATH]%PATH% + displayName: Help debug handle issues + +- template: show-environment-variables.yml + +- script: | + REM echo force the specific VS version https://github.com/johnterickson/rust/issues/8 + IF "%VCVARS_BAT%" NEQ "" ( + CALL "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\%VCVARS_BAT%" + ) + + where sccache + where rev + set | findstr /v SCCACHE_AZURE_CONNECTION_STRING + + if not exist D:\cache\rustsrc\NUL mkdir D:\cache\rustsrc + + sh src/ci/init_repo.sh . /d/cache/rustsrc + sh src/ci/run.sh + env: + CI: true + CI_JOB_NAME: $(System.JobDisplayName) + SRC: . + NO_CCACHE: 1 + + # explicitly decrypt secret variables + # see https://docs.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch + SCCACHE_AZURE_CONNECTION_STRING: $(SCCACHE_AZURE_CONNECTION_STRING_SECRET) + DOCKER_LAYER_CACHE_AZURE_STORAGE_ACCOUNT_KEY: $(DOCKER_LAYER_CACHE_AZURE_STORAGE_ACCOUNT_KEY_SECRET) + displayName: Run script diff --git a/.azure-pipelines/test.yml b/.azure-pipelines/test.yml new file mode 100644 index 000000000000..c4004aa46a97 --- /dev/null +++ b/.azure-pipelines/test.yml @@ -0,0 +1,131 @@ +# +# Azure Pipelines test build for Rust on Linux, macOS, and Windows. +# + +pr: none +trigger: none + +variables: +- group: caching + +jobs: +- job: Linux + timeoutInMinutes: 600 + pool: + vmImage: ubuntu-16.04 + steps: + - template: steps/linux.yml + strategy: + matrix: + x86_64-gnu-llvm-6.0: + RUST_BACKTRACE: 1 + + dist-x86_64-linux: + DEPLOY: 1 + + # "alternate" deployments, these are "nightlies" but have LLVM assertions + # turned on, they're deployed to a different location primarily for + # additional testing. + dist-x86_64-linux-alt: + IMAGE: dist-x86_64-linux + DEPLOY_ALT: 1 + + dist-various-1: + DEPLOY: 1 + + dist-android: + DEPLOY: 1 + + dist-x86_64-freebsd: + DEPLOY: 1 + + i686-gnu-nopt: {} + test-various: {} + x86_64-gnu-tools: {} + # FIXME if: branch = auto OR (type = pull_request AND commit_message =~ /(?i:^update.*\b(rls|rustfmt|clippy|miri|cargo)\b)/) + x86_64-gnu-nopt: {} + x86_64-gnu-distcheck: {} + mingw-check: {} + +- job: macOS + timeoutInMinutes: 600 + pool: + vmImage: macos-10.13 + steps: + - template: steps/macos.yml + strategy: + matrix: + dist-x86_64-apple-alt: + RUST_CHECK_TARGET: dist + RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --enable-lldb --set rust.jemalloc + DEPLOY_ALT: 1 + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + + # macOS builders. These are placed near the beginning because they are very + # slow to run. + + # OSX builders running tests, these run the full test suite. + # NO_DEBUG_ASSERTIONS=1 to make them go faster, but also do have some + # runners that run `//ignore-debug` tests. + # + # Note that the compiler is compiled to target 10.8 here because the Xcode + # version that we're using, 8.2, cannot compile LLVM for OSX 10.7. + x86_64-apple: + RUST_CHECK_TARGET: check + RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + +- job: Windows + timeoutInMinutes: 600 + pool: + vmImage: 'vs2017-win2016' + steps: + - template: steps/windows.yml + strategy: + matrix: + x86_64-msvc-tools: + MSYS_BITS: 64 + SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri + + # 32/64-bit MinGW builds. + # + # We are using MinGW with posix threads since LLVM does not compile with + # the win32 threads version due to missing support for C++'s std::thread. + # + # Instead of relying on the MinGW version installed on appveryor we download + # and install one ourselves so we won't be surprised by changes to appveyor's + # build image. + # + # Finally, note that the downloads below are all in the `rust-lang-ci` S3 + # bucket, but they cleraly didn't originate there! The downloads originally + # came from the mingw-w64 SourceForge download site. Unfortunately + # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. + i686-mingw-1: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + SCRIPT: make ci-subset-1 + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z + MINGW_DIR: mingw32 + x86_64-mingw: + MSYS_BITS: 64 + SCRIPT: python x.py test + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z + MINGW_DIR: mingw64 + + # "alternate" deployment, see .travis.yml for more info + dist-x86_64-msvc-alt: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler + SCRIPT: python x.py dist + DEPLOY_ALT: 1 diff --git a/.azure-pipelines/try.yml b/.azure-pipelines/try.yml new file mode 100644 index 000000000000..0b7233fb2e72 --- /dev/null +++ b/.azure-pipelines/try.yml @@ -0,0 +1,29 @@ +# +# Azure Pipelines "try" branch build for Rust +# + +pr: none +trigger: +- try + +variables: +- group: caching + +jobs: +- job: Linux + timeoutInMinutes: 300 + pool: + vmImage: ubuntu-16.04 + strategy: + matrix: + dist-x86_64-linux: + DEPLOY: 1 + + # "alternate" deployments, these are "nightlies" but have LLVM assertions + # turned on, they're deployed to a different location primarily for + # additional testing. + dist-x86_64-linux-alt: + IMAGE: dist-x86_64-linux + DEPLOY_ALT: 1 + steps: + - template: steps/linux.yml diff --git a/README.md b/README.md index f6f796911b8f..8fa12a6571b8 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![Build Status](https://dev.azure.com/rust-lang-azure/rust/_apis/build/status/johnterickson.rust?branchName=master)](https://dev.azure.com/rust-lang-azure/rust/_build/latest?definitionId=6&branchName=master) + # The Rust Programming Language This is the main source code repository for [Rust]. It contains the compiler, diff --git a/appveyor.yml b/appveyor.yml index dffd79c56e48..c35da8927ce9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -20,11 +20,11 @@ environment: - CI_JOB_NAME: i686-msvc-1 MSYS_BITS: 32 RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc - SCRIPT: make appveyor-subset-1 + SCRIPT: make ci-subset-1 - CI_JOB_NAME: i686-msvc-2 MSYS_BITS: 32 RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc - SCRIPT: make appveyor-subset-2 + SCRIPT: make ci-subset-2 # MSVC aux tests - CI_JOB_NAME: x86_64-msvc-aux @@ -58,7 +58,7 @@ environment: - CI_JOB_NAME: i686-mingw-1 MSYS_BITS: 32 RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - SCRIPT: make appveyor-subset-1 + SCRIPT: make ci-subset-1 MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z MINGW_DIR: mingw32 @@ -68,7 +68,7 @@ environment: - CI_JOB_NAME: i686-mingw-2 MSYS_BITS: 32 RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - SCRIPT: make appveyor-subset-2 + SCRIPT: make ci-subset-2 MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z MINGW_DIR: mingw32 diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index 1e01d68fb3a6..c47c0f765f0f 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -39,8 +39,7 @@ The script accepts commands, flags, and arguments to determine what to do: ``` If files are dirty that would normally be rebuilt from stage 0, that can be - overridden using `--keep-stage 0`. Using `--keep-stage n` will skip all steps - that belong to stage n or earlier: + overridden using `--keep-stage 0`. ``` # keep old build products for stage 0 and build stage 1 diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 07be27c2f5a0..29b0cdaef63f 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -14,9 +14,10 @@ endif BOOTSTRAP := $(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap.py -all: +build: $(Q)$(BOOTSTRAP) build $(BOOTSTRAP_ARGS) - $(Q)$(BOOTSTRAP) doc $(BOOTSTRAP_ARGS) + +all: build doc help: $(Q)echo 'Welcome to the rustbuild build system!' @@ -80,10 +81,75 @@ TESTS_IN_2 := \ src/test/run-pass-fulldeps \ src/tools/linkchecker -appveyor-subset-1: +MIN_TEST := \ + src/test/debuginfo + +ci-subset-1: $(Q)$(BOOTSTRAP) test $(TESTS_IN_2:%=--exclude %) -appveyor-subset-2: +ci-subset-2: $(Q)$(BOOTSTRAP) test $(TESTS_IN_2) +ci-test-prepare: + $(Q)$(BOOTSTRAP) test $(MIN_TEST) + +ci-resume-subset-1: + $(Q)$(BOOTSTRAP) test $(TESTS_IN_2:%=--exclude %) +ci-resume-subset-2: + $(Q)$(BOOTSTRAP) test $(TESTS_IN_2) + +TESTS_IN_B := \ + src/tools/linkchecker + +TESTS_IN_C := \ + src/test/run-pass \ + src/test/run-pass-fulldeps + +TESTS_IN_D := \ + src/test/compile-fail \ + src/test/rustdoc \ + src/test/pretty + +TESTS_IN_E := \ + src/test/ui + +TESTS_IN_F := \ + src/test/run-fail \ + src/liballoc \ + src/libcore + +TESTS_IN_G := \ + src/tools/rustdoc \ + src/test/rustdoc-js-std \ + src/test/run-make-fulldeps \ + src/libstd + +TESTS_IN_H := \ + src/librustc_driver + +ci-resume-subset-A: + $(Q)$(BOOTSTRAP) test \ + $(KEEP_STAGE) \ + $(TESTS_IN_B:%=--exclude %) \ + $(TESTS_IN_C:%=--exclude %) \ + $(TESTS_IN_D:%=--exclude %) \ + $(TESTS_IN_E:%=--exclude %) \ + $(TESTS_IN_F:%=--exclude %) \ + $(TESTS_IN_G:%=--exclude %) \ + $(TESTS_IN_H:%=--exclude %) \ + $(MIN_TEST:%=--exclude %) +ci-resume-subset-B: + $(Q)$(BOOTSTRAP) test $(KEEP_STAGE) $(TESTS_IN_B) +ci-resume-subset-C: + $(Q)$(BOOTSTRAP) test $(KEEP_STAGE) $(TESTS_IN_C) +ci-resume-subset-D: + $(Q)$(BOOTSTRAP) test $(KEEP_STAGE) $(TESTS_IN_D) +ci-resume-subset-E: + $(Q)$(BOOTSTRAP) test $(KEEP_STAGE) $(TESTS_IN_E) +ci-resume-subset-F: + $(Q)$(BOOTSTRAP) test $(KEEP_STAGE) $(TESTS_IN_F) +ci-resume-subset-G: + $(Q)$(BOOTSTRAP) test $(KEEP_STAGE) $(TESTS_IN_G) +ci-resume-subset-H: + $(Q)$(BOOTSTRAP) test $(KEEP_STAGE) $(TESTS_IN_H) .PHONY: dist diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 5777331b9bfd..62a8b7aad031 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -81,6 +81,13 @@ impl Step for Llvm { (info, "src/llvm-project/llvm", builder.llvm_out(target), dir.join("bin")) }; + let build_llvm_config = llvm_config_ret_dir + .join(exe("llvm-config", &*builder.config.build)); + + if env::var_os("SKIP_LLVM_BUILD").is_some() { + return build_llvm_config + } + if !llvm_info.is_git() { println!( "git could not determine the LLVM submodule commit hash. \ @@ -88,8 +95,6 @@ impl Step for Llvm { ); } - let build_llvm_config = llvm_config_ret_dir - .join(exe("llvm-config", &*builder.config.build)); let done_stamp = out_dir.join("llvm-finished-building"); if let Some(llvm_commit) = llvm_info.sha() { diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index a162c65672f8..e79700d92d89 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -326,6 +326,8 @@ pub enum CiEnv { Travis, /// The AppVeyor environment, for Windows builds. AppVeyor, + /// The Azure Pipelines environment, for Linux (including Docker), Window, and macOS builds. + AzurePipelines, } impl CiEnv { @@ -335,6 +337,8 @@ impl CiEnv { CiEnv::Travis } else if env::var("APPVEYOR").ok().map_or(false, |e| &*e == "True") { CiEnv::AppVeyor + } else if env::var("TF_BUILD").ok().map_or(false, |e| &*e == "True") { + CiEnv::AzurePipelines } else { CiEnv::None } diff --git a/src/ci/docker/i686-gnu/Dockerfile b/src/ci/docker/i686-gnu-1/Dockerfile similarity index 54% rename from src/ci/docker/i686-gnu/Dockerfile rename to src/ci/docker/i686-gnu-1/Dockerfile index 17441ddb4546..1a04b8af4c17 100644 --- a/src/ci/docker/i686-gnu/Dockerfile +++ b/src/ci/docker/i686-gnu-1/Dockerfile @@ -18,10 +18,5 @@ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu -# Exclude some tests that are unlikely to be platform specific, to speed up -# this slow job. -ENV SCRIPT python2.7 ../x.py test \ - --exclude src/bootstrap \ - --exclude src/test/rustdoc-js \ - --exclude src/tools/error_index_generator \ - --exclude src/tools/linkchecker +ENV SCRIPT make ci-subset-1 + diff --git a/src/ci/docker/i686-gnu-2/Dockerfile b/src/ci/docker/i686-gnu-2/Dockerfile new file mode 100644 index 000000000000..b1a0ea6f0e99 --- /dev/null +++ b/src/ci/docker/i686-gnu-2/Dockerfile @@ -0,0 +1,21 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + g++-multilib \ + make \ + file \ + curl \ + ca-certificates \ + python2.7 \ + git \ + cmake \ + sudo \ + gdb \ + xz-utils + + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu +ENV SCRIPT make ci-subset-2 diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 98a765e1cec9..cd913e30d112 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash +# ignore-tidy-linelength + set -e export MSYS_NO_PATHCONV=1 @@ -40,9 +42,24 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then docker --version >> $hash_key cksum=$(sha512sum $hash_key | \ awk '{print $1}') - s3url="s3://$SCCACHE_BUCKET/docker/$cksum" - url="https://s3-us-west-1.amazonaws.com/$SCCACHE_BUCKET/docker/$cksum" - echo "Attempting to download $s3url" + + if [ "$DOCKER_LAYER_CACHE_AZURE_STORAGE_ACCOUNT" != "" ]; then + # install azcopy + echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-xenial-prod/ xenial main" > azure.list + sudo cp ./azure.list /etc/apt/sources.list.d/ + sudo apt-key adv --keyserver packages.microsoft.com --recv-keys EB3E94ADBE1229CF + sudo apt-get update + sudo apt-get install azcopy + + url="https://$DOCKER_LAYER_CACHE_AZURE_STORAGE_ACCOUNT.blob.core.windows.net/$DOCKER_LAYER_CACHE_AZURE_STORAGE_CONTAINER/$cksum" + upload="azcopy --quiet --destination $url --dest-key $DOCKER_LAYER_CACHE_AZURE_STORAGE_ACCOUNT_KEY" + else + s3url="s3://$SCCACHE_BUCKET/docker/$cksum" + url="https://s3-us-west-1.amazonaws.com/$SCCACHE_BUCKET/docker/$cksum" + upload="aws s3 cp - $s3url" + fi + + echo "Attempting to download $url" rm -f /tmp/rustci_docker_cache set +e retry curl -y 30 -Y 10 --connect-timeout 30 -f -L -C - -o /tmp/rustci_docker_cache "$url" @@ -65,17 +82,17 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then -f "$dockerfile" \ "$context" - if [ "$s3url" != "" ]; then + if [ "$upload" != "" ]; then digest=$(docker inspect rust-ci --format '{{.Id}}') echo "Built container $digest" if ! grep -q "$digest" <(echo "$loaded_images"); then - echo "Uploading finished image to $s3url" + echo "Uploading finished image to $url" set +e docker history -q rust-ci | \ grep -v missing | \ xargs docker save | \ gzip | \ - aws s3 cp - $s3url + $upload set -e else echo "Looks like docker image is the same as before, not uploading" @@ -87,8 +104,8 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then echo "$digest" >>"$info" fi elif [ -f "$docker_dir/disabled/$image/Dockerfile" ]; then - if [ -n "$TRAVIS_OS_NAME" ]; then - echo Cannot run disabled images on travis! + if isCI; then + echo Cannot run disabled images on CI! exit 1 fi # retry messes with the pipe from tar to docker. Not needed on non-travis @@ -117,6 +134,9 @@ if [ "$SCCACHE_BUCKET" != "" ]; then args="$args --env SCCACHE_REGION" args="$args --env AWS_ACCESS_KEY_ID" args="$args --env AWS_SECRET_ACCESS_KEY" +elif [ "$SCCACHE_AZURE_CONNECTION_STRING" != "" ]; then + args="$args --env SCCACHE_AZURE_CONNECTION_STRING" + args="$args --env SCCACHE_AZURE_BLOB_CONTAINER" else mkdir -p $HOME/.cache/sccache args="$args --env SCCACHE_DIR=/sccache --volume $HOME/.cache/sccache:/sccache" @@ -140,8 +160,11 @@ exec docker \ --env DEPLOY \ --env DEPLOY_ALT \ --env LOCAL_USER_ID=`id -u` \ + --env CI \ --env TRAVIS \ --env TRAVIS_BRANCH \ + --env TF_BUILD \ + --env BUILD_SOURCEBRANCHNAME \ --env TOOLSTATE_REPO_ACCESS_TOKEN \ --env CI_JOB_NAME="${CI_JOB_NAME-$IMAGE}" \ --volume "$HOME/.cargo:/cargo" \ diff --git a/src/ci/docker/scripts/sccache.sh b/src/ci/docker/scripts/sccache.sh index 4c03419894e7..d6f2f4fadb2c 100644 --- a/src/ci/docker/scripts/sccache.sh +++ b/src/ci/docker/scripts/sccache.sh @@ -1,6 +1,7 @@ set -ex +echo Use sccache built with Azure Storage support curl -fo /usr/local/bin/sccache \ - https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-02-sccache-x86_64-unknown-linux-musl + https://rustlangtools.blob.core.windows.net/public/stable-x86_64-unknown-linux-musl.sccache chmod +x /usr/local/bin/sccache diff --git a/src/ci/docker/x86_64-gnu-tools/checktools.sh b/src/ci/docker/x86_64-gnu-tools/checktools.sh index af0198705a2f..c7e64cd8c3e7 100755 --- a/src/ci/docker/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/x86_64-gnu-tools/checktools.sh @@ -6,7 +6,7 @@ X_PY="$1" TOOLSTATE_FILE="$(realpath $2)" OS="$3" COMMIT="$(git rev-parse HEAD)" -CHANGED_FILES="$(git diff --name-status HEAD HEAD^)" +CHANGED_FILES="$(git diff --name-status HEAD HEAD^ || echo)" SIX_WEEK_CYCLE="$(( ($(date +%s) / 86400 - 20) % 42 ))" # ^ Number of days after the last promotion of beta. # Its value is 41 on the Tuesday where "Promote master to beta (T-2)" happens. diff --git a/src/ci/run.sh b/src/ci/run.sh index 42d0d7db5964..08ede122d65c 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -23,7 +23,9 @@ fi ci_dir=`cd $(dirname $0) && pwd` source "$ci_dir/shared.sh" -if [ "$TRAVIS" != "true" ] || [ "$TRAVIS_BRANCH" == "auto" ]; then +branch_name=$(getCIBranch) + +if [ ! isCI ] || [ "$branch_name" = "auto" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.print-step-timings --enable-verbose-tests" fi @@ -44,7 +46,7 @@ fi # FIXME: need a scheme for changing this `nightly` value to `beta` and `stable` # either automatically or manually. export RUST_RELEASE_CHANNEL=nightly -if [ "$DEPLOY$DEPLOY_ALT" != "" ]; then +if [ "$DEPLOY$DEPLOY_ALT" = "1" ]; then RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=$RUST_RELEASE_CHANNEL" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp" RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.remap-debuginfo" @@ -88,28 +90,30 @@ if [ "$RUN_CHECK_WITH_PARALLEL_QUERIES" != "" ]; then rm -rf build fi -travis_fold start configure -travis_time_start -$SRC/configure $RUST_CONFIGURE_ARGS -travis_fold end configure -travis_time_finish +if [ "$SKIP_PREP" != "1" ]; then + travis_fold start configure + travis_time_start + $SRC/configure $RUST_CONFIGURE_ARGS + travis_fold end configure + travis_time_finish -travis_fold start make-prepare -travis_time_start -retry make prepare -travis_fold end make-prepare -travis_time_finish + travis_fold start make-prepare + travis_time_start + retry make prepare + travis_fold end make-prepare + travis_time_finish -travis_fold start check-bootstrap -travis_time_start -make check-bootstrap -travis_fold end check-bootstrap -travis_time_finish + travis_fold start check-bootstrap + travis_time_start + make check-bootstrap + travis_fold end check-bootstrap + travis_time_finish +fi # Display the CPU and memory information. This helps us know why the CI timing # is fluctuating. travis_fold start log-system-info -if [ "$TRAVIS_OS_NAME" = "osx" ]; then +if isOSX; then system_profiler SPHardwareDataType || true sysctl hw || true ncpus=$(sysctl -n hw.ncpu) @@ -138,3 +142,5 @@ else do_make all do_make "$RUST_CHECK_TARGET" fi + +sccache --show-stats diff --git a/src/ci/shared.sh b/src/ci/shared.sh index 3ba64ad41206..1e667fca5875 100644 --- a/src/ci/shared.sh +++ b/src/ci/shared.sh @@ -24,6 +24,22 @@ function retry { done } +function isCI { + [ "$CI" = "true" ] || [ "$TRAVIS" = "true" ] || [ "$TF_BUILD" = "True" ] +} + +function isOSX { + [ "$TRAVIS_OS_NAME" = "osx" ] || [ "$AGENT_OS" = "Darwin" ] +} + +function getCIBranch { + if [ "$TRAVIS" = "true" ]; then + echo "$TRAVIS_BRANCH" + else + echo "$BUILD_SOURCEBRANCHNAME" + fi; +} + if ! declare -F travis_fold; then if [ "${TRAVIS-false}" = 'true' ]; then # This is a trimmed down copy of diff --git a/src/test/run-pass/fds-are-cloexec.rs b/src/test/run-pass/fds-are-cloexec.rs index 3bc0ceb5cf2f..bcfc3245db30 100644 --- a/src/test/run-pass/fds-are-cloexec.rs +++ b/src/test/run-pass/fds-are-cloexec.rs @@ -3,6 +3,7 @@ // ignore-cloudabi no processes // ignore-emscripten no processes // ignore-haiku +// ignore-macos #![feature(rustc_private)] From e234a901b6594ee90654f0b74cd1cf7948fab6e0 Mon Sep 17 00:00:00 2001 From: John Erickson Date: Mon, 6 May 2019 09:53:20 -0700 Subject: [PATCH 0074/3207] Disable 32-bit OSX --- .azure-pipelines/auto.yml | 60 +++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/.azure-pipelines/auto.yml b/.azure-pipelines/auto.yml index 818b613740e6..2cefa5993a81 100644 --- a/.azure-pipelines/auto.yml +++ b/.azure-pipelines/auto.yml @@ -167,15 +167,6 @@ jobs: - template: steps/macos.yml strategy: matrix: - dist-x86_64-apple-alt: - RUST_CHECK_TARGET: dist - RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --enable-lldb --set rust.jemalloc - DEPLOY_ALT: 1 - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - # macOS builders. These are placed near the beginning because they are very # slow to run. @@ -194,25 +185,6 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 - i686-apple: - RUST_CHECK_TARGET: check - RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.8 - MACOSX_STD_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - - dist-i686-apple: - RUST_CHECK_TARGET: dist - RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb --set rust.jemalloc - DEPLOY: 1 - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - DIST_REQUIRE_ALL_TOOLS: 1 - dist-x86_64-apple: RUST_CHECK_TARGET: dist RUST_CONFIGURE_ARGS: --target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --enable-lldb --set rust.jemalloc @@ -223,6 +195,38 @@ jobs: NO_DEBUG_ASSERTIONS: 1 DIST_REQUIRE_ALL_TOOLS: 1 + dist-x86_64-apple-alt: + RUST_CHECK_TARGET: dist + RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --enable-lldb --set rust.jemalloc + DEPLOY_ALT: 1 + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + + # # temp disabled + # # https://github.com/johnterickson/rust/issues/18 + # i686-apple: + # RUST_CHECK_TARGET: check + # RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --set rust.jemalloc + # RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + # MACOSX_DEPLOYMENT_TARGET: 10.8 + # MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + # NO_LLVM_ASSERTIONS: 1 + # NO_DEBUG_ASSERTIONS: 1 + + # dist-i686-apple: + # RUST_CHECK_TARGET: dist + # RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb --set rust.jemalloc + # DEPLOY: 1 + # RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + # MACOSX_DEPLOYMENT_TARGET: 10.7 + # NO_LLVM_ASSERTIONS: 1 + # NO_DEBUG_ASSERTIONS: 1 + # DIST_REQUIRE_ALL_TOOLS: 1 + + + - job: Windows timeoutInMinutes: 600 pool: From c50517ae85960a9f16de0fa1f02e93413a8f1578 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Fri, 10 May 2019 09:56:46 +0200 Subject: [PATCH 0075/3207] ci: reduce all azure timeouts to 3 hours As the infra team we decided to have an hard timeout of 3 hours on all the jobs: while this sometimes causes spurious timeout errors it's a great limit to prevent CI time to grow even more. --- .azure-pipelines/auto.fanout.yml | 12 ++++++------ .azure-pipelines/auto.yml | 6 +++--- .azure-pipelines/pr.yml | 2 +- .azure-pipelines/test.yml | 6 +++--- .azure-pipelines/try.yml | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.azure-pipelines/auto.fanout.yml b/.azure-pipelines/auto.fanout.yml index 08cba3c47ca8..e12836257d93 100644 --- a/.azure-pipelines/auto.fanout.yml +++ b/.azure-pipelines/auto.fanout.yml @@ -18,7 +18,7 @@ variables: jobs: # WINDOWS JOBS - job: Windows - timeoutInMinutes: 600 + timeoutInMinutes: 180 variables: TAR_COMMAND: tar pool: @@ -38,7 +38,7 @@ jobs: SCRIPT: make ci-subset-2 - job: Windows_build - timeoutInMinutes: 600 + timeoutInMinutes: 180 variables: TAR_COMMAND: tar pool: @@ -66,7 +66,7 @@ jobs: - job: Windows_test dependsOn: Windows_build - timeoutInMinutes: 600 + timeoutInMinutes: 180 variables: TAR_COMMAND: tar SKIP_PREP: 1 @@ -285,7 +285,7 @@ jobs: # macOS JOBS - job: macOS - timeoutInMinutes: 600 + timeoutInMinutes: 180 variables: TAR_COMMAND: gtar pool: @@ -306,7 +306,7 @@ jobs: NO_DEBUG_ASSERTIONS: 1 - job: macOS_build - timeoutInMinutes: 600 + timeoutInMinutes: 180 variables: TAR_COMMAND: gtar pool: @@ -351,7 +351,7 @@ jobs: - job: macOS_test dependsOn: macOS_build - timeoutInMinutes: 600 + timeoutInMinutes: 180 variables: TAR_COMMAND: gtar SKIP_PREP: 1 diff --git a/.azure-pipelines/auto.yml b/.azure-pipelines/auto.yml index 2cefa5993a81..5f4c155ce98b 100644 --- a/.azure-pipelines/auto.yml +++ b/.azure-pipelines/auto.yml @@ -16,7 +16,7 @@ variables: jobs: - job: Linux - timeoutInMinutes: 600 + timeoutInMinutes: 180 pool: vmImage: ubuntu-16.04 steps: @@ -158,7 +158,7 @@ jobs: IMAGE: mingw-check - job: macOS - timeoutInMinutes: 600 + timeoutInMinutes: 180 pool: vmImage: macos-10.13 steps: @@ -228,7 +228,7 @@ jobs: - job: Windows - timeoutInMinutes: 600 + timeoutInMinutes: 180 pool: vmImage: 'vs2017-win2016' steps: diff --git a/.azure-pipelines/pr.yml b/.azure-pipelines/pr.yml index a2a4fc251668..ffdb4301e935 100644 --- a/.azure-pipelines/pr.yml +++ b/.azure-pipelines/pr.yml @@ -11,7 +11,7 @@ variables: jobs: - job: Linux - timeoutInMinutes: 600 + timeoutInMinutes: 180 pool: vmImage: ubuntu-16.04 steps: diff --git a/.azure-pipelines/test.yml b/.azure-pipelines/test.yml index c4004aa46a97..358806fe14c9 100644 --- a/.azure-pipelines/test.yml +++ b/.azure-pipelines/test.yml @@ -10,7 +10,7 @@ variables: jobs: - job: Linux - timeoutInMinutes: 600 + timeoutInMinutes: 180 pool: vmImage: ubuntu-16.04 steps: @@ -48,7 +48,7 @@ jobs: mingw-check: {} - job: macOS - timeoutInMinutes: 600 + timeoutInMinutes: 180 pool: vmImage: macos-10.13 steps: @@ -83,7 +83,7 @@ jobs: NO_DEBUG_ASSERTIONS: 1 - job: Windows - timeoutInMinutes: 600 + timeoutInMinutes: 180 pool: vmImage: 'vs2017-win2016' steps: diff --git a/.azure-pipelines/try.yml b/.azure-pipelines/try.yml index 0b7233fb2e72..eaa50729b0d2 100644 --- a/.azure-pipelines/try.yml +++ b/.azure-pipelines/try.yml @@ -11,7 +11,7 @@ variables: jobs: - job: Linux - timeoutInMinutes: 300 + timeoutInMinutes: 180 pool: vmImage: ubuntu-16.04 strategy: From abd4b3a83cdc6b2a8e36a238d096afa9c83d3eb5 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Fri, 10 May 2019 10:04:34 +0200 Subject: [PATCH 0076/3207] ci: remove travis ipv6 docker hack on azure --- .azure-pipelines/steps/linux.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.azure-pipelines/steps/linux.yml b/.azure-pipelines/steps/linux.yml index 288c4c9854e5..b347549ccb7d 100644 --- a/.azure-pipelines/steps/linux.yml +++ b/.azure-pipelines/steps/linux.yml @@ -17,14 +17,6 @@ steps: mkdir -p $HOME/rustsrc displayName: Prep -# FIXME(#46924): these two commands are required to enable IPv6, -# they shouldn't exist, please revert once more official solutions appeared. -# see https://github.com/travis-ci/travis-ci/issues/8891#issuecomment-353403729 -- bash: | - echo '{"ipv6":true,"fixed-cidr-v6":"fd9a:8454:6789:13f7::/64"}' | sudo tee /etc/docker/daemon.json - sudo service docker restart - displayName: Enable IPv6 - # FIXME: using the job display name feels brittle. Is there a better variable that represents the current matrix key? - bash: | export RUN_SCRIPT="$BUILD_SOURCESDIRECTORY/src/ci/init_repo.sh . $HOME/rustsrc && src/ci/docker/run.sh $IMAGE" From 476ea9ef1c0ba7250e369a2ec7205506b09474b7 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Mon, 13 May 2019 01:37:04 -0400 Subject: [PATCH 0077/3207] Always try to project predicates when finding auto traits in rustdoc Fixes #60726 Previous, AutoTraitFinder would only try to project predicates when the predicate type contained an inference variable. When finding auto traits, we only project to try to unify inference variables - we don't otherwise learn any new information about the required bounds. However, this lead to failing to properly generate a negative auto trait impl (indicating that a type never implements a certain auto trait) in the following unusual scenario: In almost all cases, a type has an (implicit) negative impl of an auto trait due some other type having an explicit *negative* impl of that auto trait. For example: struct MyType { field: *const T } has an implicit 'impl !Send for MyType', due to the explicit negative impl (in libcore) 'impl !Send for *const T'. However, as exposed by the 'abi_stable' crate, this isn't always the case. This minimzed example shows how a type can never implement 'Send', due to a projection error: ``` pub struct True; pub struct False; pub trait MyTrait { type Project; } pub struct MyStruct { field: T } impl MyTrait for u8 { type Project = False; } unsafe impl Send for MyStruct where T: MyTrait {} pub struct Wrapper { inner: MyStruct } ``` In this example, `::Project == True' must hold for 'MyStruct: Send' to hold. However, '::Project == False' holds instead To properly account for this unusual case, we need to call 'poly_project_and_unify' on *all* predicates, not just those with inference variables. This ensures that we catch the projection error that occurs above, and don't incorrectly determine that 'Wrapper: Send' holds. --- src/librustc/traits/auto_trait.rs | 85 ++++++++++++++++++++++++------- src/test/rustdoc/issue-60726.rs | 35 +++++++++++++ 2 files changed, 103 insertions(+), 17 deletions(-) create mode 100644 src/test/rustdoc/issue-60726.rs diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index 57f5e2391888..2fa896962daf 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -700,22 +700,64 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { } } - // We can only call poly_project_and_unify_type when our predicate's - // Ty contains an inference variable - otherwise, there won't be anything to - // unify - if p.ty().skip_binder().has_infer_types() { - debug!("Projecting and unifying projection predicate {:?}", - predicate); - match poly_project_and_unify_type(select, &obligation.with(p)) { - Err(e) => { - debug!( - "evaluate_nested_obligations: Unable to unify predicate \ - '{:?}' '{:?}', bailing out", - ty, e - ); - return false; - } - Ok(Some(v)) => { + // There are three possible cases when we project a predicate: + // + // 1. We encounter an error. This means that it's impossible for + // our current type to implement the auto trait - there's bound + // that we could add to our ParamEnv that would 'fix' this kind + // of error, as it's not caused by an unimplemented type. + // + // 2. We succesfully project the predicate (Ok(Some(_))), generating + // some subobligations. We then process these subobligations + // like any other generated sub-obligations. + // + // 3. We receieve an 'ambiguous' result (Ok(None)) + // If we were actually trying to compile a crate, + // we would need to re-process this obligation later. + // However, all we care about is finding out what bounds + // are needed for our type to implement a particular auto trait. + // We've already added this obligation to our computed ParamEnv + // above (if it was necessary). Therefore, we don't need + // to do any further processing of the obligation. + // + // Note that we *must* try to project *all* projection predicates + // we encounter, even ones without inference variable. + // This ensures that we detect any projection errors, + // which indicate that our type can *never* implement the given + // auto trait. In that case, we will generate an explicit negative + // impl (e.g. 'impl !Send for MyType'). However, we don't + // try to process any of the generated subobligations - + // they contain no new information, since we already know + // that our type implements the projected-through trait, + // and can lead to weird region issues. + // + // Normally, we'll generate a negative impl as a result of encountering + // a type with an explicit negative impl of an auto trait + // (for example, raw pointers have !Send and !Sync impls) + // However, through some **interesting** manipulations of the type + // system, it's actually possible to write a type that never + // implements an auto trait due to a projection error, not a normal + // negative impl error. To properly handle this case, we need + // to ensure that we catch any potential projection errors, + // and turn them into an explicit negative impl for our type. + debug!("Projecting and unifying projection predicate {:?}", + predicate); + + match poly_project_and_unify_type(select, &obligation.with(p)) { + Err(e) => { + debug!( + "evaluate_nested_obligations: Unable to unify predicate \ + '{:?}' '{:?}', bailing out", + ty, e + ); + return false; + } + Ok(Some(v)) => { + // We only care about sub-obligations + // when we started out trying to unify + // some inference variables. See the comment above + // for more infomration + if p.ty().skip_binder().has_infer_types() { if !self.evaluate_nested_obligations( ty, v.clone().iter().cloned(), @@ -728,7 +770,16 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { return false; } } - Ok(None) => { + } + Ok(None) => { + // It's ok not to make progress when hvave no inference variables - + // in that case, we were only performing unifcation to check if an + // error occured (which would indicate that it's impossible for our + // type to implement the auto trait). + // However, we should always make progress (either by generating + // subobligations or getting an error) when we started off with + // inference variables + if p.ty().skip_binder().has_infer_types() { panic!("Unexpected result when selecting {:?} {:?}", ty, obligation) } } diff --git a/src/test/rustdoc/issue-60726.rs b/src/test/rustdoc/issue-60726.rs new file mode 100644 index 000000000000..6acc86277385 --- /dev/null +++ b/src/test/rustdoc/issue-60726.rs @@ -0,0 +1,35 @@ +use std::marker::PhantomData; + +pub struct True; +pub struct False; + +pub trait InterfaceType{ + type Send; +} + + +pub struct FooInterface(PhantomDataT>); + +impl InterfaceType for FooInterface { + type Send=False; +} + + +pub struct DynTrait{ + _interface:PhantomDataI>, + _unsync_unsend:PhantomData<::std::rc::Rc<()>>, +} + +unsafe impl Send for DynTrait +where + I:InterfaceType +{} + +// @has issue_60726/struct.IntoIter.html +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl !Send for \ +// IntoIter" +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl !Sync for \ +// IntoIter" +pub struct IntoIter{ + hello:DynTrait>, +} From 869ddd8d0019683c007956bae17fc07cd30f39f7 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Fri, 10 May 2019 10:17:52 +0200 Subject: [PATCH 0078/3207] ci: still use aws for caches --- .azure-pipelines/auto.fanout.yml | 4 ++-- .azure-pipelines/auto.yml | 5 ----- .azure-pipelines/steps/macos.yml | 10 +++++----- .azure-pipelines/steps/run-script.yml | 6 +++--- .azure-pipelines/steps/windows.yml | 6 +++--- src/ci/docker/run.sh | 23 +++-------------------- src/ci/docker/scripts/sccache.sh | 3 +-- 7 files changed, 17 insertions(+), 40 deletions(-) diff --git a/.azure-pipelines/auto.fanout.yml b/.azure-pipelines/auto.fanout.yml index e12836257d93..def19a87076d 100644 --- a/.azure-pipelines/auto.fanout.yml +++ b/.azure-pipelines/auto.fanout.yml @@ -160,7 +160,7 @@ jobs: - script: | REM md sccache - REM powershell -Command "iwr -outf sccache\sccache.exe https://rustlangtools.blob.core.windows.net/public/stable-x86_64-pc-windows-msvc.sccache.exe" + REM powershell -Command "iwr -outf sccache\sccache.exe https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-26-sccache-x86_64-pc-windows-msvc" echo ##vso[task.prependpath]%CD%\sccache displayName: Download and install sccache @@ -392,7 +392,7 @@ jobs: mkdir -p $HOME/rustsrc echo "##vso[task.setvariable variable=PATH;]$PATH" - curl -fo /usr/local/bin/sccache https://rustlangtools.blob.core.windows.net/public/stable-x86_64-apple-darwin.sccache + curl -fo /usr/local/bin/sccache https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-02-sccache-x86_64-apple-darwin chmod +x /usr/local/bin/sccache curl -fo /usr/local/bin/stamp https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-03-17-stamp-x86_64-apple-darwin diff --git a/.azure-pipelines/auto.yml b/.azure-pipelines/auto.yml index 5f4c155ce98b..189536cff5f4 100644 --- a/.azure-pipelines/auto.yml +++ b/.azure-pipelines/auto.yml @@ -1,11 +1,6 @@ # # Azure Pipelines "auto" branch build for Rust on Linux, macOS, and Windows. # -# Notes: -# To get sccache working, I (John Erickson) had to build it with the Azure feature enabled -# and with openssl statically-linked for Linux. -# Here's the build (with a backpointer to source) of where the bits came from: -# https://dev.azure.com/johnterickson/rust-lang/_build/results?buildId=275 pr: none # trigger: diff --git a/.azure-pipelines/steps/macos.yml b/.azure-pipelines/steps/macos.yml index a217df6f3081..e88b5613e46d 100644 --- a/.azure-pipelines/steps/macos.yml +++ b/.azure-pipelines/steps/macos.yml @@ -3,21 +3,21 @@ steps: - bash: | export PATH=$PATH:$HOME/.local/bin:$HOME/Library/Python/2.7/bin/ - mkdir -p $HOME/rustsrc + mkdir -p $HOME/rustsrc echo "##vso[task.setvariable variable=PATH;]$PATH" - curl -fo /usr/local/bin/sccache https://rustlangtools.blob.core.windows.net/public/stable-x86_64-apple-darwin.sccache + curl -fo /usr/local/bin/sccache https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-02-sccache-x86_64-apple-darwin chmod +x /usr/local/bin/sccache curl -fo /usr/local/bin/stamp https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-03-17-stamp-x86_64-apple-darwin chmod +x /usr/local/bin/stamp - + export CC=`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang echo "##vso[task.setvariable variable=CC]$CC" - + export CXX=`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang++ echo "##vso[task.setvariable variable=CXX]$CXX" - + echo "##vso[task.setvariable variable=AR]ar" displayName: Prep diff --git a/.azure-pipelines/steps/run-script.yml b/.azure-pipelines/steps/run-script.yml index 4ab3e2e06d36..cb8e8a629a7e 100644 --- a/.azure-pipelines/steps/run-script.yml +++ b/.azure-pipelines/steps/run-script.yml @@ -5,7 +5,7 @@ steps: date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true) displayName: Log time information (before) -- bash: | +- bash: | which sccache stamp sh -x -c "$RUN_SCRIPT" env: @@ -15,8 +15,8 @@ steps: # Explicitly decrypt secret variables # See https://docs.microsoft.com/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch#secret-variables - SCCACHE_AZURE_CONNECTION_STRING: $(SCCACHE_AZURE_CONNECTION_STRING_SECRET) - DOCKER_LAYER_CACHE_AZURE_STORAGE_ACCOUNT_KEY: $(DOCKER_LAYER_CACHE_AZURE_STORAGE_ACCOUNT_KEY_SECRET) + AWS_ACCESS_KEY_ID: $(SCCACHE_AWS_ACCESS_KEY_ID) + AWS_SECRET_ACCESS_KEY: $(SCCACHE_AWS_SECRET_ACCESS_KEY) displayName: Run script - bash: | diff --git a/.azure-pipelines/steps/windows.yml b/.azure-pipelines/steps/windows.yml index 5dcba664bee8..e3c06d543a97 100644 --- a/.azure-pipelines/steps/windows.yml +++ b/.azure-pipelines/steps/windows.yml @@ -106,7 +106,7 @@ steps: - script: | md sccache - powershell -Command "iwr -outf sccache\sccache.exe https://rustlangtools.blob.core.windows.net/public/stable-x86_64-pc-windows-msvc.sccache.exe" + powershell -Command "iwr -outf sccache\sccache.exe https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-26-sccache-x86_64-pc-windows-msvc" echo ##vso[task.prependpath]%CD%\sccache displayName: Download and install sccache @@ -155,6 +155,6 @@ steps: # explicitly decrypt secret variables # see https://docs.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch - SCCACHE_AZURE_CONNECTION_STRING: $(SCCACHE_AZURE_CONNECTION_STRING_SECRET) - DOCKER_LAYER_CACHE_AZURE_STORAGE_ACCOUNT_KEY: $(DOCKER_LAYER_CACHE_AZURE_STORAGE_ACCOUNT_KEY_SECRET) + AWS_ACCESS_KEY_ID: $(SCCACHE_AWS_ACCESS_KEY_ID) + AWS_SECRET_ACCESS_KEY: $(SCCACHE_AWS_SECRET_ACCESS_KEY) displayName: Run script diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index cd913e30d112..0e1485601e96 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -1,7 +1,5 @@ #!/usr/bin/env bash -# ignore-tidy-linelength - set -e export MSYS_NO_PATHCONV=1 @@ -43,21 +41,9 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then cksum=$(sha512sum $hash_key | \ awk '{print $1}') - if [ "$DOCKER_LAYER_CACHE_AZURE_STORAGE_ACCOUNT" != "" ]; then - # install azcopy - echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-xenial-prod/ xenial main" > azure.list - sudo cp ./azure.list /etc/apt/sources.list.d/ - sudo apt-key adv --keyserver packages.microsoft.com --recv-keys EB3E94ADBE1229CF - sudo apt-get update - sudo apt-get install azcopy - - url="https://$DOCKER_LAYER_CACHE_AZURE_STORAGE_ACCOUNT.blob.core.windows.net/$DOCKER_LAYER_CACHE_AZURE_STORAGE_CONTAINER/$cksum" - upload="azcopy --quiet --destination $url --dest-key $DOCKER_LAYER_CACHE_AZURE_STORAGE_ACCOUNT_KEY" - else - s3url="s3://$SCCACHE_BUCKET/docker/$cksum" - url="https://s3-us-west-1.amazonaws.com/$SCCACHE_BUCKET/docker/$cksum" - upload="aws s3 cp - $s3url" - fi + s3url="s3://$SCCACHE_BUCKET/docker/$cksum" + url="https://s3-us-west-1.amazonaws.com/$SCCACHE_BUCKET/docker/$cksum" + upload="aws s3 cp - $s3url" echo "Attempting to download $url" rm -f /tmp/rustci_docker_cache @@ -134,9 +120,6 @@ if [ "$SCCACHE_BUCKET" != "" ]; then args="$args --env SCCACHE_REGION" args="$args --env AWS_ACCESS_KEY_ID" args="$args --env AWS_SECRET_ACCESS_KEY" -elif [ "$SCCACHE_AZURE_CONNECTION_STRING" != "" ]; then - args="$args --env SCCACHE_AZURE_CONNECTION_STRING" - args="$args --env SCCACHE_AZURE_BLOB_CONTAINER" else mkdir -p $HOME/.cache/sccache args="$args --env SCCACHE_DIR=/sccache --volume $HOME/.cache/sccache:/sccache" diff --git a/src/ci/docker/scripts/sccache.sh b/src/ci/docker/scripts/sccache.sh index d6f2f4fadb2c..4c03419894e7 100644 --- a/src/ci/docker/scripts/sccache.sh +++ b/src/ci/docker/scripts/sccache.sh @@ -1,7 +1,6 @@ set -ex -echo Use sccache built with Azure Storage support curl -fo /usr/local/bin/sccache \ - https://rustlangtools.blob.core.windows.net/public/stable-x86_64-unknown-linux-musl.sccache + https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-02-sccache-x86_64-unknown-linux-musl chmod +x /usr/local/bin/sccache From 7dfd8ceb4fe5fceb426ab6868312cc0890e28837 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Sun, 12 May 2019 17:55:48 +0200 Subject: [PATCH 0079/3207] ci: remove fanout from the azure pipelines config --- .azure-pipelines/auto.fanout.yml | 521 ------------------------------- .azure-pipelines/auto.yml | 4 +- src/bootstrap/README.md | 3 +- src/bootstrap/mk/Makefile.in | 70 +---- src/bootstrap/native.rs | 9 +- src/ci/run.sh | 32 +- 6 files changed, 23 insertions(+), 616 deletions(-) delete mode 100644 .azure-pipelines/auto.fanout.yml diff --git a/.azure-pipelines/auto.fanout.yml b/.azure-pipelines/auto.fanout.yml deleted file mode 100644 index def19a87076d..000000000000 --- a/.azure-pipelines/auto.fanout.yml +++ /dev/null @@ -1,521 +0,0 @@ -# -# Azure Pipelines "auto" branch build for Rust on Linux, macOS, and Windows. -# -# Notes: -# To get sccache working, I (John Erickson) had to build it with the Azure feature enabled -# and with openssl statically-linked for Linux. -# Here's the build (with a backpointer to source) of where the bits came from: -# https://dev.azure.com/johnterickson/rust-lang/_build/results?buildId=275 - -name: fanout -pr: none -trigger: -- auto - -variables: -- group: caching - -jobs: -# WINDOWS JOBS -- job: Windows - timeoutInMinutes: 180 - variables: - TAR_COMMAND: tar - pool: - vmImage: 'vs2017-win2016' - steps: - - template: steps/windows.yml - strategy: - matrix: - # 32/64 bit MSVC tests - x86_64-msvc-1: - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler - SCRIPT: make ci-subset-1 - x86_64-msvc-2: - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler - SCRIPT: make ci-subset-2 - -- job: Windows_build - timeoutInMinutes: 180 - variables: - TAR_COMMAND: tar - pool: - vmImage: 'vs2017-win2016' - steps: - - template: steps/windows.yml - - script: | - echo on - echo "##vso[task.setvariable variable=TAR_PATH]%TEMP%\drop.tar" - - bash: | - set -x - $TAR_COMMAND --dereference --exclude=.git --exclude=citools $SUBMODULES_EXCLUDES -cf $TEMP/drop.tar . - $TAR_COMMAND --append --file=$TEMP/drop.tar citools - - task: PublishPipelineArtifact@0 - inputs: - artifactName: $(System.JobDisplayName) - targetPath: $(TAR_PATH) - strategy: - matrix: - # 32/64 bit MSVC tests - x86_64-msvc-build: - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler - SCRIPT: make ci-test-prepare - -- job: Windows_test - dependsOn: Windows_build - timeoutInMinutes: 180 - variables: - TAR_COMMAND: tar - SKIP_PREP: 1 - KEEP_STAGE: '--keep-stage 0 --keep-stage 1' - SKIP_LLVM_BUILD: 1 - pool: - vmImage: 'vs2017-win2016' - steps: - - checkout: self - fetchDepth: 2 - - script: | - set MSYS_PATH=%CD%\citools\msys64 - set PATH=%MSYS_PATH%\usr\bin;%PATH% - where rev - rev --help - where make - echo ##vso[task.prependpath]%MSYS_PATH%\usr\bin - displayName: Install msys2 - - # # If we need to download a custom MinGW, do so here and set the path - # # appropriately. - # # - # # Note that this *also* means that we're not using what is typically - # # /mingw32/bin/python2.7.exe, which is a "correct" python interpreter where - # # /usr/bin/python2.7.exe is not. To ensure we use the right interpreter we - # # move `C:\Python27` ahead in PATH and then also make sure the `python2.7.exe` - # # file exists in there (which it doesn't by default). - # - script: | - # powershell -Command "iwr -outf %MINGW_ARCHIVE% %MINGW_URL%/%MINGW_ARCHIVE%" - # 7z x -y %MINGW_ARCHIVE% > nul - # echo ##vso[task.prependpath]%CD%\%MINGW_DIR%\bin - # condition: and(succeeded(), ne(variables['MINGW_URL'],'')) - # displayName: Download custom MinGW - - # If we're compiling for MSVC then we, like most other distribution builders, - # switch to clang as the compiler. This'll allow us eventually to enable LTO - # amongst LLVM and rustc. Note that we only do this on MSVC as I don't think - # clang has an output mode compatible with MinGW that we need. If it does we - # should switch to clang for MinGW as well! - # - # Note that the LLVM installer is an NSIS installer - # - # Original downloaded here came from - # http://releases.llvm.org/7.0.0/LLVM-7.0.0-win64.exe - - script: | - # powershell -Command "iwr -outf LLVM-7.0.0-win64.exe https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/LLVM-7.0.0-win64.exe" - # .\LLVM-7.0.0-win64.exe /S /NCRC /D=C:\clang-rust - set CLANG_DIR=%CD%\citools\clang-rust - set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --set llvm.clang-cl=%CLANG_DIR%\bin\clang-cl.exe - echo ##vso[task.setvariable variable=RUST_CONFIGURE_ARGS]%RUST_CONFIGURE_ARGS% - condition: and(succeeded(), eq(variables['MINGW_URL'],'')) - displayName: Download clang - - # # Here we do a pretty heinous thing which is to mangle the MinGW installation - # # we just had above. Currently, as of this writing, we're using MinGW-w64 - # # builds of gcc, and that's currently at 6.3.0. We use 6.3.0 as it appears to - # # be the first version which contains a fix for #40546, builds randomly - # # failing during LLVM due to ar.exe/ranlib.exe failures. - # # - # # Unfortunately, though, 6.3.0 *also* is the first version of MinGW-w64 builds - # # to contain a regression in gdb (#40184). As a result if we were to use the - # # gdb provided (7.11.1) then we would fail all debuginfo tests. - # # - # # In order to fix spurious failures (pretty high priority) we use 6.3.0. To - # # avoid disabling gdb tests we download an *old* version of gdb, specifically - # # that found inside the 6.2.0 distribution. We then overwrite the 6.3.0 gdb - # # with the 6.2.0 gdb to get tests passing. - # # - # # Note that we don't literally overwrite the gdb.exe binary because it appears - # # to just use gdborig.exe, so that's the binary we deal with instead. - # - script: | - # echo ON - # powershell -Command "iwr -outf 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_URL%/2017-04-20-%MSYS_BITS%bit-gdborig.exe" - # mv 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_DIR%\bin\gdborig.exe - # condition: and(succeeded(), ne(variables['MINGW_URL'],'')) - # displayName: Override with 6.3.0 gdb with 6.2.0 gdb - - # Otherwise pull in the MinGW installed on appveyor - - script: | - echo Find mingw - set PATH | findstr /i msys - set PATH | findstr /i mingw - echo ##vso[task.prependpath]C:\msys64\mingw%MSYS_BITS%\bin - condition: and(succeeded(), eq(variables['MINGW_URL'],'')) - displayName: Add MinGW to path - - - script: | - copy C:\Python27amd64\python.exe C:\Python27amd64\python2.7.exe - echo ##vso[task.prependpath]C:\Python27amd64 - displayName: Prefer the "native" Python as LLVM has trouble building with MSYS sometimes - - - script: | - REM md sccache - REM powershell -Command "iwr -outf sccache\sccache.exe https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-26-sccache-x86_64-pc-windows-msvc" - echo ##vso[task.prependpath]%CD%\sccache - displayName: Download and install sccache - - # Note that this is originally from the github releases patch of Ninja - - script: | - REM md ninja - REM powershell -Command "iwr -outf 2017-03-15-ninja-win.zip https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-03-15-ninja-win.zip" - REM 7z x -oninja 2017-03-15-ninja-win.zip - REM del 2017-03-15-ninja-win.zip - set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --enable-ninja - echo ##vso[task.setvariable variable=RUST_CONFIGURE_ARGS]%RUST_CONFIGURE_ARGS% - echo ##vso[task.prependpath]%CD%\ninja - displayName: Download and install ninja - - - script: | - IF NOT "%DISABLE_DISK_SPACE_HACK%"=="1" ( - IF NOT EXIST build ( - mkdir c:\MORE_SPACE - mklink /J build c:\MORE_SPACE - ) - ) - - script: | - echo on - echo ##vso[task.setvariable variable=TAR_FOLDER_PATH]%TEMP% - - template: steps/show-environment-variables.yml - - task: DownloadPipelineArtifact@1 - inputs: - artifactName: $(ARTIFACT_NAME) - downloadPath: $(TAR_FOLDER_PATH) - # - task: DownloadPipelineArtifact@1 - # inputs: - # artifactName: $(ARTIFACT_NAME) - # downloadPath: $(TAR_FOLDER_PATH) - # buildType: specific - # project: rust - # pipeline: 8 - # buildVersionToDownload: specific - # buildId: 200 - # # https://dev.azure.com/rust-lang-azure/rust/_build/results?buildId=145 - - # - template: steps/macos.yml - - bash: $TAR_COMMAND -tvf $TEMP/drop.tar - - bash: $TAR_COMMAND --touch -xf $TEMP/drop.tar - - bash: rm $TEMP/drop.tar - - script: | - REM mkdir handle - REM powershell -Command "iwr -outf 2017-05-15-Handle.zip https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-05-15-Handle.zip" - REM 7z x -ohandle 2017-05-15-Handle.zip - REM del 2017-05-15-Handle.zip - set PATH=%PATH%;%CD%\handle - handle.exe -accepteula -help - echo ##vso[task.setvariable variable=PATH]%PATH% - displayName: Help debug handle issues - - script: | - REM echo force the specific VS version https://github.com/johnterickson/rust/issues/8 - IF "%VCVARS_BAT%" NEQ "" ( - CALL "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\%VCVARS_BAT%" - ) - - where sccache - where rev - set | findstr /v SCCACHE_AZURE_CONNECTION_STRING - - if not exist D:\cache\rustsrc\NUL mkdir D:\cache\rustsrc - - sh src/ci/run.sh - env: - CI: true - CI_JOB_NAME: $(System.JobDisplayName) - SRC: . - NO_CCACHE: 1 - - # explicitly decrypt secret variables - # see https://docs.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch - SCCACHE_AZURE_CONNECTION_STRING: $(SCCACHE_AZURE_CONNECTION_STRING_SECRET) - DOCKER_LAYER_CACHE_AZURE_STORAGE_ACCOUNT_KEY: $(DOCKER_LAYER_CACHE_AZURE_STORAGE_ACCOUNT_KEY_SECRET) - displayName: Run script - - strategy: - matrix: - # 32/64 bit MSVC tests - x86_64-msvc-A: - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler - ARTIFACT_NAME: x86_64-msvc-build - SCRIPT: make ci-resume-subset-A - x86_64-msvc-B: - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler - ARTIFACT_NAME: x86_64-msvc-build - SCRIPT: make ci-resume-subset-B - x86_64-msvc-C: - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler - ARTIFACT_NAME: x86_64-msvc-build - SCRIPT: make ci-resume-subset-C - x86_64-msvc-D: - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler - ARTIFACT_NAME: x86_64-msvc-build - SCRIPT: make ci-resume-subset-D - x86_64-msvc-E: - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler - ARTIFACT_NAME: x86_64-msvc-build - SCRIPT: make ci-resume-subset-E - x86_64-msvc-F: - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler - ARTIFACT_NAME: x86_64-msvc-build - SCRIPT: make ci-resume-subset-F - x86_64-msvc-G: - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler - ARTIFACT_NAME: x86_64-msvc-build - SCRIPT: make ci-resume-subset-G - x86_64-msvc-H: - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler - ARTIFACT_NAME: x86_64-msvc-build - SCRIPT: make ci-resume-subset-H - -# macOS JOBS -- job: macOS - timeoutInMinutes: 180 - variables: - TAR_COMMAND: gtar - pool: - vmImage: macos-10.13 - steps: - - checkout: self - fetchDepth: 2 - - template: steps/macos.yml - strategy: - matrix: - x86_64-apple: - RUST_CHECK_TARGET: check - RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.8 - MACOSX_STD_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - -- job: macOS_build - timeoutInMinutes: 180 - variables: - TAR_COMMAND: gtar - pool: - vmImage: macos-10.13 - steps: - - checkout: self - fetchDepth: 2 - - template: steps/macos.yml - - script: | - set -x - - git submodule - export SUBMODULES_EXCLUDES=$(git submodule | grep -Eow 'src/[^ ]+' | sed 's/\(.*\)/--exclude=\1\/\.git/') - echo $SUBMODULES_EXCLUDES - - $TAR_COMMAND --exclude=.git $SUBMODULES_EXCLUDES -cf /tmp/drop.tar . - - task: PublishPipelineArtifact@0 - inputs: - artifactName: $(System.JobDisplayName) - targetPath: '/tmp/drop.tar' - - strategy: - matrix: - # macOS builders. These are placed near the beginning because they are very - # slow to run. - - # OSX builders running tests, these run the full test suite. - # NO_DEBUG_ASSERTIONS=1 to make them go faster, but also do have some - # runners that run `//ignore-debug` tests. - # - # Note that the compiler is compiled to target 10.8 here because the Xcode - # version that we're using, 8.2, cannot compile LLVM for OSX 10.7. - x86_64-apple-build: - RUST_CHECK_TARGET: check - RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.8 - MACOSX_STD_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - SCRIPT: make ci-test-prepare - -- job: macOS_test - dependsOn: macOS_build - timeoutInMinutes: 180 - variables: - TAR_COMMAND: gtar - SKIP_PREP: 1 - KEEP_STAGE: '--keep-stage 0 --keep-stage 1' - SKIP_LLVM_BUILD: 1 - pool: - vmImage: macos-10.13 - steps: - - checkout: self - fetchDepth: 2 - - bash: brew install gnu-tar - displayName: install a tar that works well - - - template: steps/show-disk-usage.yml - - - task: DownloadPipelineArtifact@1 - inputs: - artifactName: $(ARTIFACT_NAME) - downloadPath: $(System.DefaultWorkingDirectory) - # - task: DownloadPipelineArtifact@1 - # inputs: - # artifactName: $(ARTIFACT_NAME) - # downloadPath: $(System.DefaultWorkingDirectory) - # buildType: specific - # project: rust - # pipeline: 8 - # buildVersionToDownload: specific - # buildId: 200 - - # - template: steps/macos.yml - - template: steps/show-disk-usage.yml - - bash: $TAR_COMMAND -tvf ./drop.tar - - bash: $TAR_COMMAND -xf ./drop.tar - - bash: rm ./drop.tar - - template: steps/show-disk-usage.yml - - bash: | - export PATH=$PATH:$HOME/.local/bin:$HOME/Library/Python/2.7/bin/ - mkdir -p $HOME/rustsrc - echo "##vso[task.setvariable variable=PATH;]$PATH" - - curl -fo /usr/local/bin/sccache https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-02-sccache-x86_64-apple-darwin - chmod +x /usr/local/bin/sccache - - curl -fo /usr/local/bin/stamp https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-03-17-stamp-x86_64-apple-darwin - chmod +x /usr/local/bin/stamp - - export CC=`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang - echo "##vso[task.setvariable variable=CC]$CC" - - export CXX=`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang++ - echo "##vso[task.setvariable variable=CXX]$CXX" - - echo "##vso[task.setvariable variable=AR]ar" - displayName: Prep - - - bash: brew install gnu-tar - displayName: install a tar that works well - - - bash: | - brew update - brew install xz - brew install swig - condition: and(succeeded(), eq(variables['RUST_CHECK_TARGET'],'dist')) - displayName: Install xz and swigw - - - bash: | - export RUN_SCRIPT="src/ci/run.sh" - echo "##vso[task.setvariable variable=RUN_SCRIPT]$RUN_SCRIPT" - displayName: Prepare run script (init and run) - - - template: steps/show-environment-variables.yml - - - template: steps/verify-publish-toolstate.yml - - - template: steps/run-script.yml - - strategy: - matrix: - # macOS builders. These are placed near the beginning because they are very - # slow to run. - - # OSX builders running tests, these run the full test suite. - # NO_DEBUG_ASSERTIONS=1 to make them go faster, but also do have some - # runners that run `//ignore-debug` tests. - # - # Note that the compiler is compiled to target 10.8 here because the Xcode - # version that we're using, 8.2, cannot compile LLVM for OSX 10.7. - x86_64-apple-A: - RUST_CHECK_TARGET: check - RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.8 - MACOSX_STD_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - ARTIFACT_NAME: x86_64-apple-build - SCRIPT: make ci-resume-subset-A - x86_64-apple-B: - RUST_CHECK_TARGET: check - RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.8 - MACOSX_STD_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - ARTIFACT_NAME: x86_64-apple-build - SCRIPT: make ci-resume-subset-B - x86_64-apple-C: - RUST_CHECK_TARGET: check - RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.8 - MACOSX_STD_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - ARTIFACT_NAME: x86_64-apple-build - SCRIPT: make ci-resume-subset-C - x86_64-apple-D: - RUST_CHECK_TARGET: check - RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.8 - MACOSX_STD_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - ARTIFACT_NAME: x86_64-apple-build - SCRIPT: make ci-resume-subset-D - x86_64-apple-E: - RUST_CHECK_TARGET: check - RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.8 - MACOSX_STD_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - ARTIFACT_NAME: x86_64-apple-build - SCRIPT: make ci-resume-subset-E - x86_64-apple-F: - RUST_CHECK_TARGET: check - RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.8 - MACOSX_STD_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - ARTIFACT_NAME: x86_64-apple-build - SCRIPT: make ci-resume-subset-F - x86_64-apple-G: - RUST_CHECK_TARGET: check - RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.8 - MACOSX_STD_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - ARTIFACT_NAME: x86_64-apple-build - SCRIPT: make ci-resume-subset-G - x86_64-apple-H: - RUST_CHECK_TARGET: check - RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.8 - MACOSX_STD_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - ARTIFACT_NAME: x86_64-apple-build - SCRIPT: make ci-resume-subset-H diff --git a/.azure-pipelines/auto.yml b/.azure-pipelines/auto.yml index 189536cff5f4..facc592422b8 100644 --- a/.azure-pipelines/auto.yml +++ b/.azure-pipelines/auto.yml @@ -3,8 +3,8 @@ # pr: none -# trigger: -# - auto + trigger: + - auto variables: - group: caching diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index c47c0f765f0f..1e01d68fb3a6 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -39,7 +39,8 @@ The script accepts commands, flags, and arguments to determine what to do: ``` If files are dirty that would normally be rebuilt from stage 0, that can be - overridden using `--keep-stage 0`. + overridden using `--keep-stage 0`. Using `--keep-stage n` will skip all steps + that belong to stage n or earlier: ``` # keep old build products for stage 0 and build stage 1 diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 29b0cdaef63f..ea05b30eceff 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -14,10 +14,9 @@ endif BOOTSTRAP := $(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap.py -build: +all: $(Q)$(BOOTSTRAP) build $(BOOTSTRAP_ARGS) - -all: build doc + $(Q)$(BOOTSTRAP) doc $(BOOTSTRAP_ARGS) help: $(Q)echo 'Welcome to the rustbuild build system!' @@ -81,75 +80,10 @@ TESTS_IN_2 := \ src/test/run-pass-fulldeps \ src/tools/linkchecker -MIN_TEST := \ - src/test/debuginfo - ci-subset-1: $(Q)$(BOOTSTRAP) test $(TESTS_IN_2:%=--exclude %) ci-subset-2: $(Q)$(BOOTSTRAP) test $(TESTS_IN_2) -ci-test-prepare: - $(Q)$(BOOTSTRAP) test $(MIN_TEST) - -ci-resume-subset-1: - $(Q)$(BOOTSTRAP) test $(TESTS_IN_2:%=--exclude %) -ci-resume-subset-2: - $(Q)$(BOOTSTRAP) test $(TESTS_IN_2) - -TESTS_IN_B := \ - src/tools/linkchecker - -TESTS_IN_C := \ - src/test/run-pass \ - src/test/run-pass-fulldeps - -TESTS_IN_D := \ - src/test/compile-fail \ - src/test/rustdoc \ - src/test/pretty - -TESTS_IN_E := \ - src/test/ui - -TESTS_IN_F := \ - src/test/run-fail \ - src/liballoc \ - src/libcore - -TESTS_IN_G := \ - src/tools/rustdoc \ - src/test/rustdoc-js-std \ - src/test/run-make-fulldeps \ - src/libstd - -TESTS_IN_H := \ - src/librustc_driver - -ci-resume-subset-A: - $(Q)$(BOOTSTRAP) test \ - $(KEEP_STAGE) \ - $(TESTS_IN_B:%=--exclude %) \ - $(TESTS_IN_C:%=--exclude %) \ - $(TESTS_IN_D:%=--exclude %) \ - $(TESTS_IN_E:%=--exclude %) \ - $(TESTS_IN_F:%=--exclude %) \ - $(TESTS_IN_G:%=--exclude %) \ - $(TESTS_IN_H:%=--exclude %) \ - $(MIN_TEST:%=--exclude %) -ci-resume-subset-B: - $(Q)$(BOOTSTRAP) test $(KEEP_STAGE) $(TESTS_IN_B) -ci-resume-subset-C: - $(Q)$(BOOTSTRAP) test $(KEEP_STAGE) $(TESTS_IN_C) -ci-resume-subset-D: - $(Q)$(BOOTSTRAP) test $(KEEP_STAGE) $(TESTS_IN_D) -ci-resume-subset-E: - $(Q)$(BOOTSTRAP) test $(KEEP_STAGE) $(TESTS_IN_E) -ci-resume-subset-F: - $(Q)$(BOOTSTRAP) test $(KEEP_STAGE) $(TESTS_IN_F) -ci-resume-subset-G: - $(Q)$(BOOTSTRAP) test $(KEEP_STAGE) $(TESTS_IN_G) -ci-resume-subset-H: - $(Q)$(BOOTSTRAP) test $(KEEP_STAGE) $(TESTS_IN_H) .PHONY: dist diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 62a8b7aad031..5777331b9bfd 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -81,13 +81,6 @@ impl Step for Llvm { (info, "src/llvm-project/llvm", builder.llvm_out(target), dir.join("bin")) }; - let build_llvm_config = llvm_config_ret_dir - .join(exe("llvm-config", &*builder.config.build)); - - if env::var_os("SKIP_LLVM_BUILD").is_some() { - return build_llvm_config - } - if !llvm_info.is_git() { println!( "git could not determine the LLVM submodule commit hash. \ @@ -95,6 +88,8 @@ impl Step for Llvm { ); } + let build_llvm_config = llvm_config_ret_dir + .join(exe("llvm-config", &*builder.config.build)); let done_stamp = out_dir.join("llvm-finished-building"); if let Some(llvm_commit) = llvm_info.sha() { diff --git a/src/ci/run.sh b/src/ci/run.sh index 08ede122d65c..a51c2da3cbdc 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -90,25 +90,23 @@ if [ "$RUN_CHECK_WITH_PARALLEL_QUERIES" != "" ]; then rm -rf build fi -if [ "$SKIP_PREP" != "1" ]; then - travis_fold start configure - travis_time_start - $SRC/configure $RUST_CONFIGURE_ARGS - travis_fold end configure - travis_time_finish +travis_fold start configure +travis_time_start +$SRC/configure $RUST_CONFIGURE_ARGS +travis_fold end configure +travis_time_finish - travis_fold start make-prepare - travis_time_start - retry make prepare - travis_fold end make-prepare - travis_time_finish +travis_fold start make-prepare +travis_time_start +retry make prepare +travis_fold end make-prepare +travis_time_finish - travis_fold start check-bootstrap - travis_time_start - make check-bootstrap - travis_fold end check-bootstrap - travis_time_finish -fi +travis_fold start check-bootstrap +travis_time_start +make check-bootstrap +travis_fold end check-bootstrap +travis_time_finish # Display the CPU and memory information. This helps us know why the CI timing # is fluctuating. From aab0bb47fa102b57a7e7c35af78c3f0cb79d05eb Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Sun, 12 May 2019 18:00:38 +0200 Subject: [PATCH 0080/3207] ci: merge the i1686-gnu images --- .azure-pipelines/auto.yml | 6 ++---- src/ci/docker/i686-gnu-2/Dockerfile | 21 ------------------- .../{i686-gnu-1 => i686-gnu}/Dockerfile | 9 ++++++-- 3 files changed, 9 insertions(+), 27 deletions(-) delete mode 100644 src/ci/docker/i686-gnu-2/Dockerfile rename src/ci/docker/{i686-gnu-1 => i686-gnu}/Dockerfile (54%) diff --git a/.azure-pipelines/auto.yml b/.azure-pipelines/auto.yml index facc592422b8..e8959e3f17c1 100644 --- a/.azure-pipelines/auto.yml +++ b/.azure-pipelines/auto.yml @@ -126,10 +126,8 @@ jobs: asmjs: IMAGE: asmjs - i686-gnu-1: - IMAGE: i686-gnu-1 - i686-gnu-2: - IMAGE: i686-gnu-2 + i686-gnu: + IMAGE: i686-gnu i686-gnu-nopt: IMAGE: i686-gnu-nopt test-various: diff --git a/src/ci/docker/i686-gnu-2/Dockerfile b/src/ci/docker/i686-gnu-2/Dockerfile deleted file mode 100644 index b1a0ea6f0e99..000000000000 --- a/src/ci/docker/i686-gnu-2/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM ubuntu:16.04 - -RUN apt-get update && apt-get install -y --no-install-recommends \ - g++-multilib \ - make \ - file \ - curl \ - ca-certificates \ - python2.7 \ - git \ - cmake \ - sudo \ - gdb \ - xz-utils - - -COPY scripts/sccache.sh /scripts/ -RUN sh /scripts/sccache.sh - -ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu -ENV SCRIPT make ci-subset-2 diff --git a/src/ci/docker/i686-gnu-1/Dockerfile b/src/ci/docker/i686-gnu/Dockerfile similarity index 54% rename from src/ci/docker/i686-gnu-1/Dockerfile rename to src/ci/docker/i686-gnu/Dockerfile index 1a04b8af4c17..17441ddb4546 100644 --- a/src/ci/docker/i686-gnu-1/Dockerfile +++ b/src/ci/docker/i686-gnu/Dockerfile @@ -18,5 +18,10 @@ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu -ENV SCRIPT make ci-subset-1 - +# Exclude some tests that are unlikely to be platform specific, to speed up +# this slow job. +ENV SCRIPT python2.7 ../x.py test \ + --exclude src/bootstrap \ + --exclude src/test/rustdoc-js \ + --exclude src/tools/error_index_generator \ + --exclude src/tools/linkchecker From 94f7660ab376c91c19eee67af7a9a41b268679b6 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Sun, 12 May 2019 18:16:42 +0200 Subject: [PATCH 0081/3207] ci: re-enable fds-are-cloexec test on macOS --- src/test/run-pass/fds-are-cloexec.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/run-pass/fds-are-cloexec.rs b/src/test/run-pass/fds-are-cloexec.rs index bcfc3245db30..3bc0ceb5cf2f 100644 --- a/src/test/run-pass/fds-are-cloexec.rs +++ b/src/test/run-pass/fds-are-cloexec.rs @@ -3,7 +3,6 @@ // ignore-cloudabi no processes // ignore-emscripten no processes // ignore-haiku -// ignore-macos #![feature(rustc_private)] From 06bc0da65c1ae7ef97945e05e19e7c6ca281e146 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Sun, 12 May 2019 18:17:42 +0200 Subject: [PATCH 0082/3207] ci: remove test configuration --- .azure-pipelines/test.yml | 131 -------------------------------------- 1 file changed, 131 deletions(-) delete mode 100644 .azure-pipelines/test.yml diff --git a/.azure-pipelines/test.yml b/.azure-pipelines/test.yml deleted file mode 100644 index 358806fe14c9..000000000000 --- a/.azure-pipelines/test.yml +++ /dev/null @@ -1,131 +0,0 @@ -# -# Azure Pipelines test build for Rust on Linux, macOS, and Windows. -# - -pr: none -trigger: none - -variables: -- group: caching - -jobs: -- job: Linux - timeoutInMinutes: 180 - pool: - vmImage: ubuntu-16.04 - steps: - - template: steps/linux.yml - strategy: - matrix: - x86_64-gnu-llvm-6.0: - RUST_BACKTRACE: 1 - - dist-x86_64-linux: - DEPLOY: 1 - - # "alternate" deployments, these are "nightlies" but have LLVM assertions - # turned on, they're deployed to a different location primarily for - # additional testing. - dist-x86_64-linux-alt: - IMAGE: dist-x86_64-linux - DEPLOY_ALT: 1 - - dist-various-1: - DEPLOY: 1 - - dist-android: - DEPLOY: 1 - - dist-x86_64-freebsd: - DEPLOY: 1 - - i686-gnu-nopt: {} - test-various: {} - x86_64-gnu-tools: {} - # FIXME if: branch = auto OR (type = pull_request AND commit_message =~ /(?i:^update.*\b(rls|rustfmt|clippy|miri|cargo)\b)/) - x86_64-gnu-nopt: {} - x86_64-gnu-distcheck: {} - mingw-check: {} - -- job: macOS - timeoutInMinutes: 180 - pool: - vmImage: macos-10.13 - steps: - - template: steps/macos.yml - strategy: - matrix: - dist-x86_64-apple-alt: - RUST_CHECK_TARGET: dist - RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --enable-lldb --set rust.jemalloc - DEPLOY_ALT: 1 - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - - # macOS builders. These are placed near the beginning because they are very - # slow to run. - - # OSX builders running tests, these run the full test suite. - # NO_DEBUG_ASSERTIONS=1 to make them go faster, but also do have some - # runners that run `//ignore-debug` tests. - # - # Note that the compiler is compiled to target 10.8 here because the Xcode - # version that we're using, 8.2, cannot compile LLVM for OSX 10.7. - x86_64-apple: - RUST_CHECK_TARGET: check - RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.8 - MACOSX_STD_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - -- job: Windows - timeoutInMinutes: 180 - pool: - vmImage: 'vs2017-win2016' - steps: - - template: steps/windows.yml - strategy: - matrix: - x86_64-msvc-tools: - MSYS_BITS: 64 - SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri - - # 32/64-bit MinGW builds. - # - # We are using MinGW with posix threads since LLVM does not compile with - # the win32 threads version due to missing support for C++'s std::thread. - # - # Instead of relying on the MinGW version installed on appveryor we download - # and install one ourselves so we won't be surprised by changes to appveyor's - # build image. - # - # Finally, note that the downloads below are all in the `rust-lang-ci` S3 - # bucket, but they cleraly didn't originate there! The downloads originally - # came from the mingw-w64 SourceForge download site. Unfortunately - # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. - i686-mingw-1: - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - SCRIPT: make ci-subset-1 - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z - MINGW_DIR: mingw32 - x86_64-mingw: - MSYS_BITS: 64 - SCRIPT: python x.py test - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z - MINGW_DIR: mingw64 - - # "alternate" deployment, see .travis.yml for more info - dist-x86_64-msvc-alt: - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler - SCRIPT: python x.py dist - DEPLOY_ALT: 1 From 5db55e6fe0a82d56819b46d58d6afb6d4686ef4f Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Sun, 12 May 2019 18:19:10 +0200 Subject: [PATCH 0083/3207] ci: disable toolstate commits on azure --- .azure-pipelines/master.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.azure-pipelines/master.yml b/.azure-pipelines/master.yml index e30c73c5e924..5e8f87759d8c 100644 --- a/.azure-pipelines/master.yml +++ b/.azure-pipelines/master.yml @@ -16,7 +16,9 @@ steps: - script: | export MESSAGE_FILE=$(mktemp -t msg.XXXXXX) . src/ci/docker/x86_64-gnu-tools/repo.sh - commit_toolstate_change "$MESSAGE_FILE" "$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" "$(git log --format=%s -n1 HEAD)" "$MESSAGE_FILE" "$TOOLSTATE_REPO_ACCESS_TOKEN" + # FIXME(pietro): committing is disabled until we switch to Azure Pipelines + # as the source of truth, or until we setup a separate test repo. + #commit_toolstate_change "$MESSAGE_FILE" "$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" "$(git log --format=%s -n1 HEAD)" "$MESSAGE_FILE" "$TOOLSTATE_REPO_ACCESS_TOKEN" displayName: Publish toolstate env: TOOLSTATE_REPO_ACCESS_TOKEN: $(TOOLSTATE_REPO_ACCESS_TOKEN_SECRET) From da949780f099f48066e77235d5ccff7f430b3323 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Mon, 13 May 2019 09:55:12 +0200 Subject: [PATCH 0084/3207] ci: remove trailing whitespaces from azure config --- .azure-pipelines/auto.yml | 8 ++++---- .azure-pipelines/master.yml | 4 ++-- .azure-pipelines/pr.yml | 4 ++-- .azure-pipelines/steps/linux.yml | 4 ++-- .azure-pipelines/steps/macos.yml | 4 ++-- .azure-pipelines/steps/windows.yml | 10 +++++----- .azure-pipelines/try.yml | 2 +- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.azure-pipelines/auto.yml b/.azure-pipelines/auto.yml index e8959e3f17c1..3ee52050e2c5 100644 --- a/.azure-pipelines/auto.yml +++ b/.azure-pipelines/auto.yml @@ -1,6 +1,6 @@ # # Azure Pipelines "auto" branch build for Rust on Linux, macOS, and Windows. -# +# pr: none trigger: @@ -33,7 +33,7 @@ jobs: IMAGE: dist-x86_64-linux DEPLOY_ALT: 1 - # Linux builders, remaining docker images + # Linux builders, remaining docker images arm-android: IMAGE: arm-android @@ -157,7 +157,7 @@ jobs: steps: - checkout: self fetchDepth: 2 - - template: steps/macos.yml + - template: steps/macos.yml strategy: matrix: # macOS builders. These are placed near the beginning because they are very @@ -200,7 +200,7 @@ jobs: # # temp disabled # # https://github.com/johnterickson/rust/issues/18 # i686-apple: - # RUST_CHECK_TARGET: check + # RUST_CHECK_TARGET: check # RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --set rust.jemalloc # RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 # MACOSX_DEPLOYMENT_TARGET: 10.8 diff --git a/.azure-pipelines/master.yml b/.azure-pipelines/master.yml index 5e8f87759d8c..624b5e8fab03 100644 --- a/.azure-pipelines/master.yml +++ b/.azure-pipelines/master.yml @@ -9,7 +9,7 @@ trigger: pool: vmImage: ubuntu-16.04 -steps: +steps: - checkout: self fetchDepth: 2 @@ -19,6 +19,6 @@ steps: # FIXME(pietro): committing is disabled until we switch to Azure Pipelines # as the source of truth, or until we setup a separate test repo. #commit_toolstate_change "$MESSAGE_FILE" "$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" "$(git log --format=%s -n1 HEAD)" "$MESSAGE_FILE" "$TOOLSTATE_REPO_ACCESS_TOKEN" - displayName: Publish toolstate + displayName: Publish toolstate env: TOOLSTATE_REPO_ACCESS_TOKEN: $(TOOLSTATE_REPO_ACCESS_TOKEN_SECRET) diff --git a/.azure-pipelines/pr.yml b/.azure-pipelines/pr.yml index ffdb4301e935..5161b8aafbf8 100644 --- a/.azure-pipelines/pr.yml +++ b/.azure-pipelines/pr.yml @@ -1,6 +1,6 @@ # # Azure Pipelines pull request build for Rust -# +# trigger: none pr: @@ -20,7 +20,7 @@ jobs: matrix: x86_64-gnu-llvm-6.0: RUST_BACKTRACE: 1 - + x86_64-gnu-tools: {} # if: branch = auto OR (type = pull_request AND commit_message =~ /(?i:^update.*\b(rls|rustfmt|clippy|miri|cargo)\b)/) mingw-check: {} diff --git a/.azure-pipelines/steps/linux.yml b/.azure-pipelines/steps/linux.yml index b347549ccb7d..3e83f0dcaaa8 100644 --- a/.azure-pipelines/steps/linux.yml +++ b/.azure-pipelines/steps/linux.yml @@ -7,10 +7,10 @@ steps: - bash: | sudo apt install gdb - + curl -fo $HOME/stamp https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-03-17-stamp-x86_64-unknown-linux-musl chmod +x $HOME/stamp - + export PATH=$PATH:$HOME/.local/bin:$HOME/Library/Python/2.7/bin/:$HOME echo "##vso[task.setvariable variable=PATH;]$PATH" diff --git a/.azure-pipelines/steps/macos.yml b/.azure-pipelines/steps/macos.yml index e88b5613e46d..d1adc3403921 100644 --- a/.azure-pipelines/steps/macos.yml +++ b/.azure-pipelines/steps/macos.yml @@ -25,9 +25,9 @@ steps: displayName: install a tar that works well - bash: | - curl -f http://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz | tar xJf - + curl -f http://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz | tar xJf - displayName: Download clang - + - bash: | brew update brew install xz diff --git a/.azure-pipelines/steps/windows.yml b/.azure-pipelines/steps/windows.yml index e3c06d543a97..cc11e7a08369 100644 --- a/.azure-pipelines/steps/windows.yml +++ b/.azure-pipelines/steps/windows.yml @@ -7,7 +7,7 @@ steps: git submodule export SUBMODULES_EXCLUDES=$(git submodule | grep -Eow 'src/[^ ]+' | sed 's/\(.*\)/--exclude=\1\/\.git/') echo "##vso[task.setvariable variable=SUBMODULES_EXCLUDES;]$SUBMODULES_EXCLUDES" - + - script: | REM echo hack as drive D is too small IF NOT "%DISABLE_DISK_SPACE_HACK%"=="1" ( @@ -19,7 +19,7 @@ steps: set MSYS_PATH=%CD%\citools\msys64 choco install msys2 --params="/InstallDir:%MSYS_PATH% /NoPath" -y set PATH=%MSYS_PATH%\usr\bin;%PATH% - pacman -S --noconfirm --needed base-devel ca-certificates make diffutils tar + pacman -S --noconfirm --needed base-devel ca-certificates make diffutils tar IF "%MINGW_URL%"=="" ( IF "%MSYS_BITS%"=="32" pacman -S --noconfirm --needed mingw-w64-i686-toolchain mingw-w64-i686-cmake mingw-w64-i686-gcc mingw-w64-i686-python2 IF "%MSYS_BITS%"=="64" pacman -S --noconfirm --needed mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake mingw-w64-x86_64-gcc mingw-w64-x86_64-python2 @@ -135,7 +135,7 @@ steps: - script: | REM echo force the specific VS version https://github.com/johnterickson/rust/issues/8 - IF "%VCVARS_BAT%" NEQ "" ( + IF "%VCVARS_BAT%" NEQ "" ( CALL "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\%VCVARS_BAT%" ) @@ -144,10 +144,10 @@ steps: set | findstr /v SCCACHE_AZURE_CONNECTION_STRING if not exist D:\cache\rustsrc\NUL mkdir D:\cache\rustsrc - + sh src/ci/init_repo.sh . /d/cache/rustsrc sh src/ci/run.sh - env: + env: CI: true CI_JOB_NAME: $(System.JobDisplayName) SRC: . diff --git a/.azure-pipelines/try.yml b/.azure-pipelines/try.yml index eaa50729b0d2..229927f4d34e 100644 --- a/.azure-pipelines/try.yml +++ b/.azure-pipelines/try.yml @@ -1,6 +1,6 @@ # # Azure Pipelines "try" branch build for Rust -# +# pr: none trigger: From 694ea7646af0003a8fc38cfb11cbeb9c3ffb9d38 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Mon, 13 May 2019 10:09:51 +0200 Subject: [PATCH 0085/3207] ci: remove links to johnterickson repo --- .azure-pipelines/auto.yml | 36 ++++++++++++++---------------- .azure-pipelines/steps/windows.yml | 2 +- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/.azure-pipelines/auto.yml b/.azure-pipelines/auto.yml index 3ee52050e2c5..748a6a9e7486 100644 --- a/.azure-pipelines/auto.yml +++ b/.azure-pipelines/auto.yml @@ -197,26 +197,24 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 - # # temp disabled - # # https://github.com/johnterickson/rust/issues/18 - # i686-apple: - # RUST_CHECK_TARGET: check - # RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --set rust.jemalloc - # RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - # MACOSX_DEPLOYMENT_TARGET: 10.8 - # MACOSX_STD_DEPLOYMENT_TARGET: 10.7 - # NO_LLVM_ASSERTIONS: 1 - # NO_DEBUG_ASSERTIONS: 1 + i686-apple: + RUST_CHECK_TARGET: check + RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 - # dist-i686-apple: - # RUST_CHECK_TARGET: dist - # RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb --set rust.jemalloc - # DEPLOY: 1 - # RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - # MACOSX_DEPLOYMENT_TARGET: 10.7 - # NO_LLVM_ASSERTIONS: 1 - # NO_DEBUG_ASSERTIONS: 1 - # DIST_REQUIRE_ALL_TOOLS: 1 + dist-i686-apple: + RUST_CHECK_TARGET: dist + RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb --set rust.jemalloc + DEPLOY: 1 + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + DIST_REQUIRE_ALL_TOOLS: 1 diff --git a/.azure-pipelines/steps/windows.yml b/.azure-pipelines/steps/windows.yml index cc11e7a08369..5fb1da2083f7 100644 --- a/.azure-pipelines/steps/windows.yml +++ b/.azure-pipelines/steps/windows.yml @@ -134,7 +134,7 @@ steps: - template: show-environment-variables.yml - script: | - REM echo force the specific VS version https://github.com/johnterickson/rust/issues/8 + REM echo force the specific VS version IF "%VCVARS_BAT%" NEQ "" ( CALL "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\%VCVARS_BAT%" ) From 807b7dd7863c4f662dbbd2091c34707664dc3d66 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Mon, 13 May 2019 10:13:23 +0200 Subject: [PATCH 0086/3207] ci: disable builders not useful during the evaluation --- .azure-pipelines/auto.yml | 516 ++++++++++++++++++------------------ .azure-pipelines/master.yml | 2 +- .azure-pipelines/pr.yml | 6 +- 3 files changed, 262 insertions(+), 262 deletions(-) diff --git a/.azure-pipelines/auto.yml b/.azure-pipelines/auto.yml index 748a6a9e7486..8202578b6701 100644 --- a/.azure-pipelines/auto.yml +++ b/.azure-pipelines/auto.yml @@ -33,120 +33,120 @@ jobs: IMAGE: dist-x86_64-linux DEPLOY_ALT: 1 - # Linux builders, remaining docker images - arm-android: - IMAGE: arm-android - - armhf-gnu: - IMAGE: armhf-gnu - - dist-various-1: - IMAGE: dist-various-1 - DEPLOY: 1 - - dist-various-2: - IMAGE: dist-various-2 - DEPLOY: 1 - - dist-aarch64-linux: - IMAGE: dist-aarch64-linux - DEPLOY: 1 - - dist-android: - IMAGE: dist-android - DEPLOY: 1 - - dist-arm-linux: - IMAGE: dist-arm-linux - DEPLOY: 1 - - dist-armhf-linux: - IMAGE: dist-armhf-linux - DEPLOY: 1 - - dist-armv7-linux: - IMAGE: dist-armv7-linux - DEPLOY: 1 - - dist-i586-gnu-i586-i686-musl: - IMAGE: dist-i586-gnu-i586-i686-musl - DEPLOY: 1 - - dist-i686-freebsd: - IMAGE: dist-i686-freebsd - DEPLOY: 1 - - dist-i686-linux: - IMAGE: dist-i686-linux - DEPLOY: 1 - - dist-mips-linux: - IMAGE: dist-mips-linux - DEPLOY: 1 - - dist-mips64-linux: - IMAGE: dist-mips64-linux - DEPLOY: 1 - - dist-mips64el-linux: - IMAGE: dist-mips64el-linux - DEPLOY: 1 - - dist-mipsel-linux: - IMAGE: dist-mipsel-linux - DEPLOY: 1 - - dist-powerpc-linux: - IMAGE: dist-powerpc-linux - DEPLOY: 1 - - dist-powerpc64-linux: - IMAGE: dist-powerpc64-linux - DEPLOY: 1 - - dist-powerpc64le-linux: - IMAGE: dist-powerpc64le-linux - DEPLOY: 1 - - dist-s390x-linux: - IMAGE: dist-s390x-linux - DEPLOY: 1 - - dist-x86_64-freebsd: - IMAGE: dist-x86_64-freebsd - DEPLOY: 1 - - dist-x86_64-musl: - IMAGE: dist-x86_64-musl - DEPLOY: 1 - - dist-x86_64-netbsd: - IMAGE: dist-x86_64-netbsd - DEPLOY: 1 - - asmjs: - IMAGE: asmjs - i686-gnu: - IMAGE: i686-gnu - i686-gnu-nopt: - IMAGE: i686-gnu-nopt - test-various: - IMAGE: test-various - x86_64-gnu: - IMAGE: x86_64-gnu - x86_64-gnu-full-bootstrap: - IMAGE: x86_64-gnu-full-bootstrap - x86_64-gnu-aux: - IMAGE: x86_64-gnu-aux - x86_64-gnu-tools: - IMAGE: x86_64-gnu-tools - # FIXME if: branch = auto OR (type = pull_request AND commit_message =~ /(?i:^update.*\b(rls|rustfmt|clippy|miri|cargo)\b)/) - x86_64-gnu-debug: - IMAGE: x86_64-gnu-debug - x86_64-gnu-nopt: - IMAGE: x86_64-gnu-nopt - x86_64-gnu-distcheck: - IMAGE: x86_64-gnu-distcheck +# # Linux builders, remaining docker images +# arm-android: +# IMAGE: arm-android +# +# armhf-gnu: +# IMAGE: armhf-gnu +# +# dist-various-1: +# IMAGE: dist-various-1 +# DEPLOY: 1 +# +# dist-various-2: +# IMAGE: dist-various-2 +# DEPLOY: 1 +# +# dist-aarch64-linux: +# IMAGE: dist-aarch64-linux +# DEPLOY: 1 +# +# dist-android: +# IMAGE: dist-android +# DEPLOY: 1 +# +# dist-arm-linux: +# IMAGE: dist-arm-linux +# DEPLOY: 1 +# +# dist-armhf-linux: +# IMAGE: dist-armhf-linux +# DEPLOY: 1 +# +# dist-armv7-linux: +# IMAGE: dist-armv7-linux +# DEPLOY: 1 +# +# dist-i586-gnu-i586-i686-musl: +# IMAGE: dist-i586-gnu-i586-i686-musl +# DEPLOY: 1 +# +# dist-i686-freebsd: +# IMAGE: dist-i686-freebsd +# DEPLOY: 1 +# +# dist-i686-linux: +# IMAGE: dist-i686-linux +# DEPLOY: 1 +# +# dist-mips-linux: +# IMAGE: dist-mips-linux +# DEPLOY: 1 +# +# dist-mips64-linux: +# IMAGE: dist-mips64-linux +# DEPLOY: 1 +# +# dist-mips64el-linux: +# IMAGE: dist-mips64el-linux +# DEPLOY: 1 +# +# dist-mipsel-linux: +# IMAGE: dist-mipsel-linux +# DEPLOY: 1 +# +# dist-powerpc-linux: +# IMAGE: dist-powerpc-linux +# DEPLOY: 1 +# +# dist-powerpc64-linux: +# IMAGE: dist-powerpc64-linux +# DEPLOY: 1 +# +# dist-powerpc64le-linux: +# IMAGE: dist-powerpc64le-linux +# DEPLOY: 1 +# +# dist-s390x-linux: +# IMAGE: dist-s390x-linux +# DEPLOY: 1 +# +# dist-x86_64-freebsd: +# IMAGE: dist-x86_64-freebsd +# DEPLOY: 1 +# +# dist-x86_64-musl: +# IMAGE: dist-x86_64-musl +# DEPLOY: 1 +# +# dist-x86_64-netbsd: +# IMAGE: dist-x86_64-netbsd +# DEPLOY: 1 +# +# asmjs: +# IMAGE: asmjs +# i686-gnu: +# IMAGE: i686-gnu +# i686-gnu-nopt: +# IMAGE: i686-gnu-nopt +# test-various: +# IMAGE: test-various +# x86_64-gnu: +# IMAGE: x86_64-gnu +# x86_64-gnu-full-bootstrap: +# IMAGE: x86_64-gnu-full-bootstrap +# x86_64-gnu-aux: +# IMAGE: x86_64-gnu-aux +# x86_64-gnu-tools: +# IMAGE: x86_64-gnu-tools +# # FIXME if: branch = auto OR (type = pull_request AND commit_message =~ /(?i:^update.*\b(rls|rustfmt|clippy|miri|cargo)\b)/) +# x86_64-gnu-debug: +# IMAGE: x86_64-gnu-debug +# x86_64-gnu-nopt: +# IMAGE: x86_64-gnu-nopt +# x86_64-gnu-distcheck: +# IMAGE: x86_64-gnu-distcheck mingw-check: IMAGE: mingw-check @@ -188,33 +188,33 @@ jobs: NO_DEBUG_ASSERTIONS: 1 DIST_REQUIRE_ALL_TOOLS: 1 - dist-x86_64-apple-alt: - RUST_CHECK_TARGET: dist - RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --enable-lldb --set rust.jemalloc - DEPLOY_ALT: 1 - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - - i686-apple: - RUST_CHECK_TARGET: check - RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.8 - MACOSX_STD_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - - dist-i686-apple: - RUST_CHECK_TARGET: dist - RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb --set rust.jemalloc - DEPLOY: 1 - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - DIST_REQUIRE_ALL_TOOLS: 1 +# dist-x86_64-apple-alt: +# RUST_CHECK_TARGET: dist +# RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --enable-lldb --set rust.jemalloc +# DEPLOY_ALT: 1 +# RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 +# MACOSX_DEPLOYMENT_TARGET: 10.7 +# NO_LLVM_ASSERTIONS: 1 +# NO_DEBUG_ASSERTIONS: 1 +# +# i686-apple: +# RUST_CHECK_TARGET: check +# RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --set rust.jemalloc +# RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 +# MACOSX_DEPLOYMENT_TARGET: 10.8 +# MACOSX_STD_DEPLOYMENT_TARGET: 10.7 +# NO_LLVM_ASSERTIONS: 1 +# NO_DEBUG_ASSERTIONS: 1 +# +# dist-i686-apple: +# RUST_CHECK_TARGET: dist +# RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb --set rust.jemalloc +# DEPLOY: 1 +# RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 +# MACOSX_DEPLOYMENT_TARGET: 10.7 +# NO_LLVM_ASSERTIONS: 1 +# NO_DEBUG_ASSERTIONS: 1 +# DIST_REQUIRE_ALL_TOOLS: 1 @@ -226,89 +226,89 @@ jobs: - template: steps/windows.yml strategy: matrix: - # 32/64 bit MSVC tests - x86_64-msvc-1: - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler - SCRIPT: make ci-subset-1 - # FIXME(#59637) - NO_DEBUG_ASSERTIONS: 1 - NO_LLVM_ASSERTIONS: 1 - x86_64-msvc-2: - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler - SCRIPT: make ci-subset-2 - i686-msvc-1: - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc - SCRIPT: make ci-subset-1 - i686-msvc-2: - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc - SCRIPT: make ci-subset-2 - # MSVC aux tests - x86_64-msvc-aux: - MSYS_BITS: 64 - RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc - x86_64-msvc-cargo: - MSYS_BITS: 64 - SCRIPT: python x.py test src/tools/cargotest src/tools/cargo - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc - VCVARS_BAT: vcvars64.bat - # MSVC tools tests - x86_64-msvc-tools: - MSYS_BITS: 64 - SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri - - # 32/64-bit MinGW builds. - # - # We are using MinGW with posix threads since LLVM does not compile with - # the win32 threads version due to missing support for C++'s std::thread. - # - # Instead of relying on the MinGW version installed on appveryor we download - # and install one ourselves so we won't be surprised by changes to appveyor's - # build image. - # - # Finally, note that the downloads below are all in the `rust-lang-ci` S3 - # bucket, but they cleraly didn't originate there! The downloads originally - # came from the mingw-w64 SourceForge download site. Unfortunately - # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. - i686-mingw-1: - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - SCRIPT: make ci-subset-1 - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z - MINGW_DIR: mingw32 - # FIXME(#59637) - NO_DEBUG_ASSERTIONS: 1 - NO_LLVM_ASSERTIONS: 1 - i686-mingw-2: - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - SCRIPT: make ci-subset-2 - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z - MINGW_DIR: mingw32 - x86_64-mingw-1: - MSYS_BITS: 64 - SCRIPT: make ci-subset-1 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z - MINGW_DIR: mingw64 - # FIXME(#59637) - NO_DEBUG_ASSERTIONS: 1 - NO_LLVM_ASSERTIONS: 1 - x86_64-mingw-2: - MSYS_BITS: 64 - SCRIPT: make ci-subset-2 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z - MINGW_DIR: mingw64 +# # 32/64 bit MSVC tests +# x86_64-msvc-1: +# MSYS_BITS: 64 +# RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler +# SCRIPT: make ci-subset-1 +# # FIXME(#59637) +# NO_DEBUG_ASSERTIONS: 1 +# NO_LLVM_ASSERTIONS: 1 +# x86_64-msvc-2: +# MSYS_BITS: 64 +# RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler +# SCRIPT: make ci-subset-2 +# i686-msvc-1: +# MSYS_BITS: 32 +# RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc +# SCRIPT: make ci-subset-1 +# i686-msvc-2: +# MSYS_BITS: 32 +# RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc +# SCRIPT: make ci-subset-2 +# # MSVC aux tests +# x86_64-msvc-aux: +# MSYS_BITS: 64 +# RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1 +# RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc +# x86_64-msvc-cargo: +# MSYS_BITS: 64 +# SCRIPT: python x.py test src/tools/cargotest src/tools/cargo +# RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc +# VCVARS_BAT: vcvars64.bat +# # MSVC tools tests +# x86_64-msvc-tools: +# MSYS_BITS: 64 +# SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows +# RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri +# +# # 32/64-bit MinGW builds. +# # +# # We are using MinGW with posix threads since LLVM does not compile with +# # the win32 threads version due to missing support for C++'s std::thread. +# # +# # Instead of relying on the MinGW version installed on appveryor we download +# # and install one ourselves so we won't be surprised by changes to appveyor's +# # build image. +# # +# # Finally, note that the downloads below are all in the `rust-lang-ci` S3 +# # bucket, but they cleraly didn't originate there! The downloads originally +# # came from the mingw-w64 SourceForge download site. Unfortunately +# # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. +# i686-mingw-1: +# MSYS_BITS: 32 +# RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu +# SCRIPT: make ci-subset-1 +# MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror +# MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z +# MINGW_DIR: mingw32 +# # FIXME(#59637) +# NO_DEBUG_ASSERTIONS: 1 +# NO_LLVM_ASSERTIONS: 1 +# i686-mingw-2: +# MSYS_BITS: 32 +# RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu +# SCRIPT: make ci-subset-2 +# MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror +# MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z +# MINGW_DIR: mingw32 +# x86_64-mingw-1: +# MSYS_BITS: 64 +# SCRIPT: make ci-subset-1 +# RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu +# MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror +# MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z +# MINGW_DIR: mingw64 +# # FIXME(#59637) +# NO_DEBUG_ASSERTIONS: 1 +# NO_LLVM_ASSERTIONS: 1 +# x86_64-mingw-2: +# MSYS_BITS: 64 +# SCRIPT: make ci-subset-2 +# RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu +# MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror +# MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z +# MINGW_DIR: mingw64 # 32/64 bit MSVC and GNU deployment dist-x86_64-msvc: @@ -320,37 +320,37 @@ jobs: SCRIPT: python x.py dist DIST_REQUIRE_ALL_TOOLS: 1 DEPLOY: 1 - dist-i686-msvc: - RUST_CONFIGURE_ARGS: > - --build=i686-pc-windows-msvc - --target=i586-pc-windows-msvc - --enable-full-tools - --enable-profiler - SCRIPT: python x.py dist - DIST_REQUIRE_ALL_TOOLS: 1 - DEPLOY: 1 - dist-i686-mingw: - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools - SCRIPT: python x.py dist - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z - MINGW_DIR: mingw32 - DIST_REQUIRE_ALL_TOOLS: 1 - DEPLOY: 1 - dist-x86_64-mingw: - MSYS_BITS: 64 - SCRIPT: python x.py dist - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z - MINGW_DIR: mingw64 - DIST_REQUIRE_ALL_TOOLS: 1 - DEPLOY: 1 - - # "alternate" deployment, see .travis.yml for more info - dist-x86_64-msvc-alt: - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler - SCRIPT: python x.py dist - DEPLOY_ALT: 1 +# dist-i686-msvc: +# RUST_CONFIGURE_ARGS: > +# --build=i686-pc-windows-msvc +# --target=i586-pc-windows-msvc +# --enable-full-tools +# --enable-profiler +# SCRIPT: python x.py dist +# DIST_REQUIRE_ALL_TOOLS: 1 +# DEPLOY: 1 +# dist-i686-mingw: +# MSYS_BITS: 32 +# RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools +# SCRIPT: python x.py dist +# MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror +# MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z +# MINGW_DIR: mingw32 +# DIST_REQUIRE_ALL_TOOLS: 1 +# DEPLOY: 1 +# dist-x86_64-mingw: +# MSYS_BITS: 64 +# SCRIPT: python x.py dist +# RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools +# MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror +# MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z +# MINGW_DIR: mingw64 +# DIST_REQUIRE_ALL_TOOLS: 1 +# DEPLOY: 1 +# +# # "alternate" deployment, see .travis.yml for more info +# dist-x86_64-msvc-alt: +# MSYS_BITS: 64 +# RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler +# SCRIPT: python x.py dist +# DEPLOY_ALT: 1 diff --git a/.azure-pipelines/master.yml b/.azure-pipelines/master.yml index 624b5e8fab03..3f3025ad65b6 100644 --- a/.azure-pipelines/master.yml +++ b/.azure-pipelines/master.yml @@ -4,7 +4,7 @@ pr: none trigger: -- master + - master pool: vmImage: ubuntu-16.04 diff --git a/.azure-pipelines/pr.yml b/.azure-pipelines/pr.yml index 5161b8aafbf8..ec9396e61e55 100644 --- a/.azure-pipelines/pr.yml +++ b/.azure-pipelines/pr.yml @@ -21,6 +21,6 @@ jobs: x86_64-gnu-llvm-6.0: RUST_BACKTRACE: 1 - x86_64-gnu-tools: {} - # if: branch = auto OR (type = pull_request AND commit_message =~ /(?i:^update.*\b(rls|rustfmt|clippy|miri|cargo)\b)/) - mingw-check: {} +# x86_64-gnu-tools: {} +# # if: branch = auto OR (type = pull_request AND commit_message =~ /(?i:^update.*\b(rls|rustfmt|clippy|miri|cargo)\b)/) +# mingw-check: {} From 4965ffdb7a0dd825e251bcd1cc83c20ee6c8e45d Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Mon, 13 May 2019 15:19:29 +0200 Subject: [PATCH 0087/3207] Update src/bootstrap/util.rs Co-Authored-By: Jake Goulding --- src/bootstrap/util.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index e79700d92d89..f22f0559265b 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -326,7 +326,7 @@ pub enum CiEnv { Travis, /// The AppVeyor environment, for Windows builds. AppVeyor, - /// The Azure Pipelines environment, for Linux (including Docker), Window, and macOS builds. + /// The Azure Pipelines environment, for Linux (including Docker), Windows, and macOS builds. AzurePipelines, } From 02a148dba261439626c5020a7cbb15e690521e87 Mon Sep 17 00:00:00 2001 From: "@amit.chandra" <@amit.chandra> Date: Fri, 26 Apr 2019 19:53:18 +0530 Subject: [PATCH 0088/3207] wip nth_back on chunks Signed-off-by: wizAmit --- src/libcore/slice/mod.rs | 16 ++++++++++++++++ src/libcore/tests/slice.rs | 13 +++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 8731f4867535..049d38c158ce 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4152,6 +4152,22 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { Some(snd) } } + + #[inline] + fn nth_back(&mut self, n: usize) { + let (end, overflow) = self.v.len().overflowing_sub(n); + if end < self.v.len() || overflow { + self.v = &[]; + None + } else { + let start = match end.checked_sub(self.chunk_size) { + Some(sum) => cmp::min(self.v.len(), sum), + None => self.v.len(), + }; + let nth = &self.v[start..end]; + self.v = &self.v[end..]; + } + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index acf6b03791f0..0233b96d3a72 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -134,6 +134,19 @@ fn test_chunks_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_chunks_nth_back() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5]; + let mut c = v.chunks(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next().unwrap(), &[4, 5]); + + let v2: &[i32] = &[0, 1, 2, 3, 4]; + let mut c2 = v2.chunks(3); + assert_eq!(c2.nth_back(1).unwrap(), &[0, 1]); + assert_eq!(c2.next(), None); +} + #[test] fn test_chunks_last() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; From aff83c80dd162b43a301e2bea73762cc4560f0f3 Mon Sep 17 00:00:00 2001 From: "@amit.chandra" <@amit.chandra> Date: Wed, 1 May 2019 23:34:07 +0530 Subject: [PATCH 0089/3207] hopefully working nth_back on chunks Signed-off-by: wizAmit --- src/libcore/slice/mod.rs | 17 +++++++++-------- src/libcore/tests/slice.rs | 9 ++++++++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 049d38c158ce..00dbe7104d1a 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4154,18 +4154,19 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { } #[inline] - fn nth_back(&mut self, n: usize) { - let (end, overflow) = self.v.len().overflowing_sub(n); - if end < self.v.len() || overflow { - self.v = &[]; + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.v.len().overflowing_sub(n * self.chunk_size); + if overflow { + self.v = &mut []; None } else { let start = match end.checked_sub(self.chunk_size) { - Some(sum) => cmp::min(self.v.len(), sum), - None => self.v.len(), + Some(res) => cmp::min(self.v.len(), res), + None => 0, }; - let nth = &self.v[start..end]; - self.v = &self.v[end..]; + let nth_back = &self.v[start..end]; + self.v = &self.v[..start]; + Some(nth_back) } } } diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 0233b96d3a72..edea405fad79 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -139,12 +139,19 @@ fn test_chunks_nth_back() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; let mut c = v.chunks(2); assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); - assert_eq!(c.next().unwrap(), &[4, 5]); + assert_eq!(c.next().unwrap(), &[0, 1]); + assert_eq!(c.next(), None); let v2: &[i32] = &[0, 1, 2, 3, 4]; let mut c2 = v2.chunks(3); assert_eq!(c2.nth_back(1).unwrap(), &[0, 1]); assert_eq!(c2.next(), None); + assert_eq!(c2.next_back(), None); + + let v3: &[i32] = &[0, 1, 2, 3, 4]; + let mut c3 = v3.chunks(10); + assert_eq!(c3.nth_back(0).unwrap(), &[0, 1, 2, 3, 4]); + assert_eq!(c3.next(), None); } #[test] From a7a05203f18eac663ebf2751b77621c453dc280c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Wiedenh=C3=B6ft?= Date: Mon, 29 Apr 2019 15:49:43 +0200 Subject: [PATCH 0090/3207] Mark core::alloc::Layout::from_size_align_unchecked const --- src/libcore/alloc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index c124457118cb..302a9d89e585 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -99,7 +99,7 @@ impl Layout { /// [`Layout::from_size_align`](#method.from_size_align). #[stable(feature = "alloc_layout", since = "1.28.0")] #[inline] - pub unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self { + pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self { Layout { size_: size, align_: NonZeroUsize::new_unchecked(align) } } From 07e8d844795628ce90415c1dec3536f3e75cc71c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Wiedenh=C3=B6ft?= Date: Tue, 30 Apr 2019 08:23:14 +0200 Subject: [PATCH 0091/3207] Add const_unchecked_layout test to libcore/tests --- src/libcore/tests/alloc.rs | 10 ++++++++++ src/libcore/tests/lib.rs | 2 ++ 2 files changed, 12 insertions(+) create mode 100644 src/libcore/tests/alloc.rs diff --git a/src/libcore/tests/alloc.rs b/src/libcore/tests/alloc.rs new file mode 100644 index 000000000000..63537ba23d84 --- /dev/null +++ b/src/libcore/tests/alloc.rs @@ -0,0 +1,10 @@ +use core::alloc::Layout; + +#[test] +fn const_unchecked_layout() { + const SIZE: usize = 0x2000; + const ALIGN: usize = 0x1000; + const LAYOUT: Layout = unsafe { Layout::from_size_align_unchecked(SIZE, ALIGN) }; + assert_eq!(LAYOUT.size(), SIZE); + assert_eq!(LAYOUT.align(), ALIGN); +} diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index b8075ef2942e..c617596aba80 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -31,10 +31,12 @@ #![feature(slice_partition_dedup)] #![feature(copy_within)] #![feature(int_error_matching)] +#![feature(const_fn)] #![warn(rust_2018_idioms)] extern crate test; +mod alloc; mod any; mod array; mod ascii; From c0b6d3c975915e740548f0ec7bcf5963e7a3b218 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20Wiedenh=C3=B6ft?= Date: Tue, 30 Apr 2019 12:56:38 +0200 Subject: [PATCH 0092/3207] Add ui test for const Layout::from_size_align_unchecked --- src/test/ui/consts/std/alloc.rs | 10 ++++++++++ src/test/ui/consts/std/alloc.stderr | 11 +++++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/test/ui/consts/std/alloc.rs create mode 100644 src/test/ui/consts/std/alloc.stderr diff --git a/src/test/ui/consts/std/alloc.rs b/src/test/ui/consts/std/alloc.rs new file mode 100644 index 000000000000..65ac7e44926d --- /dev/null +++ b/src/test/ui/consts/std/alloc.rs @@ -0,0 +1,10 @@ +use std::alloc::Layout; + +// ok +const LAYOUT_VALID: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x08) }; + +// not ok, since alignment needs to be non-zero. +const LAYOUT_INVALID: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; +//~^ ERROR it is undefined behavior to use this value + +fn main() {} diff --git a/src/test/ui/consts/std/alloc.stderr b/src/test/ui/consts/std/alloc.stderr new file mode 100644 index 000000000000..74a8f3daf6aa --- /dev/null +++ b/src/test/ui/consts/std/alloc.stderr @@ -0,0 +1,11 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/alloc.rs:7:1 + | +LL | const LAYOUT_INVALID: Layout = unsafe { Layout::from_size_align_unchecked(0x1000, 0x00) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0 at .align_, but expected something greater or equal to 1 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. From 16223e4bea1ecb087c60d2ac1aeb16c7b7033d52 Mon Sep 17 00:00:00 2001 From: wizAmit Date: Tue, 14 May 2019 13:28:43 +0530 Subject: [PATCH 0093/3207] new implementation for nth_back for chunks --- src/libcore/slice/mod.rs | 27 ++++++++++++++++++++++----- src/libcore/tests/slice.rs | 6 +++++- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 00dbe7104d1a..72a54c5ce82d 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4155,15 +4155,32 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { #[inline] fn nth_back(&mut self, n: usize) -> Option { - let (end, overflow) = self.v.len().overflowing_sub(n * self.chunk_size); + let remainder = match self.v.len().checked_rem(self.chunk_size) { + Some(res) => res, + None => 0, + }; + + let sub_chunk_size = if remainder != 0 { remainder } else { self.chunk_size }; + + let safe_sub = match n.checked_mul(sub_chunk_size) { + Some(res) => res, + None => 0, + }; + + let (end, overflow) = self.v.len().overflowing_sub(safe_sub); if overflow { - self.v = &mut []; + self.v= &[]; None } else { - let start = match end.checked_sub(self.chunk_size) { - Some(res) => cmp::min(self.v.len(), res), - None => 0, + let start = if n == 0 { + self.v.len() - sub_chunk_size + } else { + match end.checked_sub(self.chunk_size) { + Some(res) => res, + None => 0, + } }; + let nth_back = &self.v[start..end]; self.v = &self.v[..start]; Some(nth_back) diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index edea405fad79..cf2602f3210f 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -144,7 +144,7 @@ fn test_chunks_nth_back() { let v2: &[i32] = &[0, 1, 2, 3, 4]; let mut c2 = v2.chunks(3); - assert_eq!(c2.nth_back(1).unwrap(), &[0, 1]); + assert_eq!(c2.nth_back(1).unwrap(), &[0, 1, 2]); assert_eq!(c2.next(), None); assert_eq!(c2.next_back(), None); @@ -152,6 +152,10 @@ fn test_chunks_nth_back() { let mut c3 = v3.chunks(10); assert_eq!(c3.nth_back(0).unwrap(), &[0, 1, 2, 3, 4]); assert_eq!(c3.next(), None); + + let v4: &[i32] = &[0, 1, 2]; + let mut c4 = v4.chunks(10); + assert_eq!(c4.nth_back(1_000_000_000usize), None); } #[test] From 2adc6da7aa4f3f8cb646b8f7b7759e73c98ade12 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 14 May 2019 14:19:46 +0200 Subject: [PATCH 0094/3207] Fix incremental compilation of cdylib emitting spurious unused_attributes lint --- src/libsyntax/feature_gate.rs | 2 +- src/test/incremental/no_mangle.rs | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 src/test/incremental/no_mangle.rs diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 8a066f3f4a09..5b1a9bb739ff 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -998,7 +998,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ (sym::repr, Normal, template!(List: "C, packed, ..."), Ungated), (sym::path, Normal, template!(NameValueStr: "file"), Ungated), (sym::automatically_derived, Normal, template!(Word), Ungated), - (sym::no_mangle, Normal, template!(Word), Ungated), + (sym::no_mangle, Whitelisted, template!(Word), Ungated), (sym::no_link, Normal, template!(Word), Ungated), (sym::derive, Normal, template!(List: "Trait1, Trait2, ..."), Ungated), ( diff --git a/src/test/incremental/no_mangle.rs b/src/test/incremental/no_mangle.rs new file mode 100644 index 000000000000..1b17886a4f9b --- /dev/null +++ b/src/test/incremental/no_mangle.rs @@ -0,0 +1,10 @@ +// revisions:rpass1 rpass2 +// compile-flags: --crate-type cdylib +// skip-codegen + +#![deny(unused_attributes)] + +#[no_mangle] +pub extern "C" fn rust_no_mangle() -> i32 { + 42 +} From e92d13ea2e84586ce17790946ae4241777a9778f Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 14 May 2019 15:46:43 +0200 Subject: [PATCH 0095/3207] Update ui tests --- .../ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs | 2 +- .../feature-gate/issue-43106-gating-of-builtin-attrs.stderr | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs index 0129a3f72b24..ca0a432d3396 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs @@ -52,7 +52,7 @@ //~^ WARN unused attribute #![path = "3800"] //~ WARN unused attribute #![automatically_derived] //~ WARN unused attribute -#![no_mangle] //~ WARN unused attribute +#![no_mangle] #![no_link] //~ WARN unused attribute // see issue-43106-gating-of-derive.rs #![should_panic] //~ WARN unused attribute diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr index dcbe13a749f6..c7081205e148 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr @@ -1152,12 +1152,6 @@ warning: unused attribute LL | #![automatically_derived] | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:55:1 - | -LL | #![no_mangle] - | ^^^^^^^^^^^^^ - warning: unused attribute --> $DIR/issue-43106-gating-of-builtin-attrs.rs:56:1 | From b5febe72bbe10e3a327fa983b06d64354a0954e0 Mon Sep 17 00:00:00 2001 From: chandde Date: Tue, 14 May 2019 17:00:48 -0700 Subject: [PATCH 0096/3207] Update lib.rs --- src/libtest/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 26612964c308..765ee12a1d67 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -37,12 +37,12 @@ extern crate libc; use term; // FIXME(#54291): rustc and/or LLVM don't yet support building with panic-unwind -// on aarch64-pc-windows-msvc, so we don't link libtest against +// on aarch64-pc-windows-msvc, or thumbv7a-pc-windows-msvc, so we don't link libtest against // libunwind (for the time being), even though it means that -// libtest won't be fully functional on this platform. +// libtest won't be fully functional on these platforms. // // See also: https://github.com/rust-lang/rust/issues/54190#issuecomment-422904437 -#[cfg(not(all(windows, target_arch = "aarch64")))] +#[cfg(not(any(all(windows, target_arch = "aarch64"), all(windows, target_arch = "arm"))))] extern crate panic_unwind; pub use self::ColorConfig::*; From b789017403beb28c7f73cdd994e7fbd982a311f0 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Tue, 14 May 2019 17:43:37 -0700 Subject: [PATCH 0097/3207] Emit StorageDead for all locals in generators --- src/librustc_mir/build/mod.rs | 11 +- src/librustc_mir/build/scope.rs | 114 ++++++++++++++------- src/test/mir-opt/generator-drop-cleanup.rs | 1 + 3 files changed, 85 insertions(+), 41 deletions(-) diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 16ab233bd2e3..e46c51535552 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -343,6 +343,7 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { fn_span: Span, arg_count: usize, + is_generator: bool, /// The current set of scopes, updated as we traverse; /// see the `scope` module for more details. @@ -689,7 +690,8 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, return_ty, return_ty_span, upvar_debuginfo, - upvar_mutbls); + upvar_mutbls, + body.is_generator); let call_site_scope = region::Scope { id: body.value.hir_id.local_id, @@ -759,6 +761,7 @@ fn construct_const<'a, 'gcx, 'tcx>( const_ty_span, vec![], vec![], + false, ); let mut block = START_BLOCK; @@ -788,7 +791,7 @@ fn construct_error<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>, let owner_id = hir.tcx().hir().body_owner(body_id); let span = hir.tcx().hir().span(owner_id); let ty = hir.tcx().types.err; - let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, span, vec![], vec![]); + let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, span, vec![], vec![], false); let source_info = builder.source_info(span); builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable); builder.finish(None) @@ -802,7 +805,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { return_ty: Ty<'tcx>, return_span: Span, __upvar_debuginfo_codegen_only_do_not_use: Vec, - upvar_mutbls: Vec) + upvar_mutbls: Vec, + is_generator: bool) -> Builder<'a, 'gcx, 'tcx> { let lint_level = LintLevel::Explicit(hir.root_lint_level); let mut builder = Builder { @@ -810,6 +814,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { cfg: CFG { basic_blocks: IndexVec::new() }, fn_span: span, arg_count, + is_generator, scopes: vec![], block_context: BlockContext::new(), source_scopes: IndexVec::new(), diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 4aa463b37ab7..3b11e335fb87 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -83,9 +83,10 @@ use rustc::middle::region; use rustc::ty::Ty; use rustc::hir; use rustc::mir::*; -use syntax_pos::{Span}; +use syntax_pos::{Span, DUMMY_SP}; use rustc_data_structures::fx::FxHashMap; use std::collections::hash_map::Entry; +use std::mem; #[derive(Debug)] pub struct Scope<'tcx> { @@ -107,6 +108,8 @@ pub struct Scope<'tcx> { /// * polluting the cleanup MIR with StorageDead creates /// landing pads even though there's no actual destructors /// * freeing up stack space has no effect during unwinding + /// Note that for generators we do emit StorageDeads, for the + /// use of optimizations in the MIR generator transform. needs_cleanup: bool, /// set of places to drop when exiting this scope. This starts @@ -466,10 +469,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// This path terminates in GeneratorDrop. Returns the start of the path. /// None indicates there’s no cleanup to do at this point. pub fn generator_drop_cleanup(&mut self) -> Option { - if !self.scopes.iter().any(|scope| scope.needs_cleanup) { - return None; - } - // Fill in the cache for unwinds self.diverge_cleanup_gen(true); @@ -480,7 +479,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let result = block; while let Some(scope) = scopes.next() { - if !scope.needs_cleanup { + if !scope.needs_cleanup && !self.is_generator { continue; } @@ -802,7 +801,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { for scope in self.scopes[first_uncached..].iter_mut() { target = build_diverge_scope(&mut self.cfg, scope.region_scope_span, - scope, target, generator_drop); + scope, target, generator_drop, self.is_generator); } target @@ -900,12 +899,6 @@ fn build_scope_drops<'tcx>( // drops panic (panicking while unwinding will abort, so there's no need for // another set of arrows). The drops for the unwind path should have already // been generated by `diverge_cleanup_gen`. - // - // The code in this function reads from right to left. - // Storage dead drops have to be done left to right (since we can only push - // to the end of a Vec). So, we find the next drop and then call - // push_storage_deads which will iterate backwards through them so that - // they are added in the correct order. let mut unwind_blocks = scope.drops.iter().rev().filter_map(|drop_data| { if let DropKind::Value { cached_block } = drop_data.kind { @@ -936,11 +929,6 @@ fn build_scope_drops<'tcx>( block = next; } DropKind::Storage => { - // We do not need to emit StorageDead for generator drops - if generator_drop { - continue - } - // Drop the storage for both value and storage drops. // Only temps and vars need their storage dead. match drop_data.location { @@ -962,7 +950,8 @@ fn build_diverge_scope<'tcx>(cfg: &mut CFG<'tcx>, span: Span, scope: &mut Scope<'tcx>, mut target: BasicBlock, - generator_drop: bool) + generator_drop: bool, + is_generator: bool) -> BasicBlock { // Build up the drops in **reverse** order. The end result will @@ -981,41 +970,90 @@ fn build_diverge_scope<'tcx>(cfg: &mut CFG<'tcx>, scope: source_scope }; - // Next, build up the drops. Here we iterate the vector in + // We keep track of StorageDead statements to prepend to our current block + // and store them here, in reverse order. + let mut storage_deads = vec![]; + + let mut target_built_by_us = false; + + // Build up the drops. Here we iterate the vector in // *forward* order, so that we generate drops[0] first (right to // left in diagram above). for (j, drop_data) in scope.drops.iter_mut().enumerate() { debug!("build_diverge_scope drop_data[{}]: {:?}", j, drop_data); // Only full value drops are emitted in the diverging path, - // not StorageDead. + // not StorageDead, except in the case of generators. // // Note: This may not actually be what we desire (are we // "freeing" stack storage as we unwind, or merely observing a // frozen stack)? In particular, the intent may have been to // match the behavior of clang, but on inspection eddyb says // this is not what clang does. - let cached_block = match drop_data.kind { - DropKind::Value { ref mut cached_block } => cached_block.ref_mut(generator_drop), - DropKind::Storage => continue - }; - target = if let Some(cached_block) = *cached_block { - cached_block - } else { - let block = cfg.start_new_cleanup_block(); - cfg.terminate(block, source_info(drop_data.span), - TerminatorKind::Drop { - location: drop_data.location.clone(), - target, - unwind: None - }); - *cached_block = Some(block); - block + match drop_data.kind { + DropKind::Storage if is_generator => { + // Only temps and vars need their storage dead. + match drop_data.location { + Place::Base(PlaceBase::Local(index)) => { + storage_deads.push(Statement { + source_info: source_info(drop_data.span), + kind: StatementKind::StorageDead(index) + }); + } + _ => unreachable!(), + }; + } + DropKind::Storage => {} + DropKind::Value { ref mut cached_block } => { + let cached_block = cached_block.ref_mut(generator_drop); + target = if let Some(cached_block) = *cached_block { + storage_deads.clear(); + target_built_by_us = false; + cached_block + } else { + push_storage_deads( + cfg, &mut target, &mut storage_deads, target_built_by_us, source_scope); + let block = cfg.start_new_cleanup_block(); + cfg.terminate(block, source_info(drop_data.span), + TerminatorKind::Drop { + location: drop_data.location.clone(), + target, + unwind: None + }); + *cached_block = Some(block); + target_built_by_us = true; + block + }; + } }; } - + push_storage_deads(cfg, &mut target, &mut storage_deads, target_built_by_us, source_scope); *scope.cached_unwind.ref_mut(generator_drop) = Some(target); + assert!(storage_deads.is_empty()); debug!("build_diverge_scope({:?}, {:?}) = {:?}", scope, span, target); target } + +fn push_storage_deads(cfg: &mut CFG<'tcx>, + target: &mut BasicBlock, + storage_deads: &mut Vec>, + target_built_by_us: bool, + source_scope: SourceScope) { + if storage_deads.is_empty() { return; } + if !target_built_by_us { + // We cannot add statements to an existing block, so we create a new + // block for our StorageDead statements. + let block = cfg.start_new_cleanup_block(); + let source_info = SourceInfo { span: DUMMY_SP, scope: source_scope }; + cfg.terminate(block, source_info, TerminatorKind::Goto { target: *target }); + *target = block; + } + let statements = &mut cfg.block_data_mut(*target).statements; + storage_deads.reverse(); + debug!("push_storage_deads({:?}), storage_deads={:?}, statements={:?}", + *target, storage_deads, statements); + storage_deads.append(statements); + mem::swap(statements, storage_deads); + assert!(storage_deads.is_empty()); +} diff --git a/src/test/mir-opt/generator-drop-cleanup.rs b/src/test/mir-opt/generator-drop-cleanup.rs index 9cc4272fafab..30f6d0deb918 100644 --- a/src/test/mir-opt/generator-drop-cleanup.rs +++ b/src/test/mir-opt/generator-drop-cleanup.rs @@ -17,6 +17,7 @@ fn main() { // switchInt(move _5) -> [0u32: bb4, 3u32: bb7, otherwise: bb8]; // } // bb1: { +// StorageDead(_3); // goto -> bb5; // } // bb2: { From dd2eabc49d415dd30cea0953df5d7659d4d9440f Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Tue, 14 May 2019 14:08:31 -0700 Subject: [PATCH 0098/3207] Make MaybeStorageLive drop-aware --- src/librustc_mir/dataflow/impls/storage_liveness.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs index 6b8eb6f17f6c..3bf11c57379c 100644 --- a/src/librustc_mir/dataflow/impls/storage_liveness.rs +++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs @@ -43,9 +43,14 @@ impl<'a, 'tcx> BitDenotation<'tcx> for MaybeStorageLive<'a, 'tcx> { } fn terminator_effect(&self, - _sets: &mut BlockSets<'_, Local>, - _loc: Location) { - // Terminators have no effect + sets: &mut BlockSets<'_, Local>, + loc: Location) { + match &self.mir[loc.block].terminator().kind { + TerminatorKind::Drop { location, .. } => if let Some(l) = location.local() { + sets.kill(l); + } + _ => (), + } } fn propagate_call_return( From e2cde9119bf59a15973065a9b594c860be1520a5 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Tue, 14 May 2019 17:44:46 -0700 Subject: [PATCH 0099/3207] Remove separation between generator_drop and unwind paths --- src/librustc_mir/build/scope.rs | 81 ++++++++++++--------------------- 1 file changed, 28 insertions(+), 53 deletions(-) diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 3b11e335fb87..e6cebd72f19d 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -124,7 +124,10 @@ pub struct Scope<'tcx> { /// The cache for drop chain on "generator drop" exit. cached_generator_drop: Option, - /// The cache for drop chain on "unwind" exit. + /// The cache for drop chain on "unwind" exit. This block + /// contains code to run the current drop and all the preceding + /// drops (i.e., those having lower index in Drop’s Scope drop + /// array) cached_unwind: CachedBlock, } @@ -141,21 +144,7 @@ struct DropData<'tcx> { } #[derive(Debug, Default, Clone, Copy)] -pub(crate) struct CachedBlock { - /// The cached block for the cleanups-on-diverge path. This block - /// contains code to run the current drop and all the preceding - /// drops (i.e., those having lower index in Drop’s Scope drop - /// array) - unwind: Option, - - /// The cached block for unwinds during cleanups-on-generator-drop path - /// - /// This is split from the standard unwind path here to prevent drop - /// elaboration from creating drop flags that would have to be captured - /// by the generator. I'm not sure how important this optimization is, - /// but it is here. - generator_drop: Option, -} +pub(crate) struct CachedBlock(Option); #[derive(Debug)] pub(crate) enum DropKind { @@ -181,24 +170,15 @@ pub struct BreakableScope<'tcx> { impl CachedBlock { fn invalidate(&mut self) { - self.generator_drop = None; - self.unwind = None; + self.0 = None; } - fn get(&self, generator_drop: bool) -> Option { - if generator_drop { - self.generator_drop - } else { - self.unwind - } + fn get(&self) -> Option { + self.0 } - fn ref_mut(&mut self, generator_drop: bool) -> &mut Option { - if generator_drop { - &mut self.generator_drop - } else { - &mut self.unwind - } + fn ref_mut(&mut self) -> &mut Option { + &mut self.0 } } @@ -378,7 +358,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { assert_eq!(scope.region_scope, region_scope.0); let unwind_to = self.scopes.last().and_then(|next_scope| { - next_scope.cached_unwind.get(false) + next_scope.cached_unwind.get() }).unwrap_or_else(|| self.resume_block()); unpack!(block = build_scope_drops( @@ -387,7 +367,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { block, unwind_to, self.arg_count, - false, )); block.unit() @@ -442,7 +421,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } }; - let unwind_to = next_scope.cached_unwind.get(false).unwrap_or_else(|| { + let unwind_to = next_scope.cached_unwind.get().unwrap_or_else(|| { debug_assert!(!may_panic, "cached block not present?"); START_BLOCK }); @@ -453,7 +432,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { block, unwind_to, self.arg_count, - false, )); scope = next_scope; @@ -470,7 +448,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// None indicates there’s no cleanup to do at this point. pub fn generator_drop_cleanup(&mut self) -> Option { // Fill in the cache for unwinds - self.diverge_cleanup_gen(true); + self.diverge_cleanup_gen(); let src_info = self.scopes[0].source_info(self.fn_span); let resume_block = self.resume_block(); @@ -496,7 +474,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }; let unwind_to = scopes.peek().as_ref().map(|scope| { - scope.cached_unwind.get(true).unwrap_or_else(|| { + scope.cached_unwind.get().unwrap_or_else(|| { span_bug!(src_info.span, "cached block not present?") }) }).unwrap_or(resume_block); @@ -507,7 +485,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { block, unwind_to, self.arg_count, - true, )); } @@ -760,7 +737,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// This path terminates in Resume. Returns the start of the path. /// See module comment for more details. pub fn diverge_cleanup(&mut self) -> BasicBlock { - self.diverge_cleanup_gen(false) + self.diverge_cleanup_gen() } fn resume_block(&mut self) -> BasicBlock { @@ -779,7 +756,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } - fn diverge_cleanup_gen(&mut self, generator_drop: bool) -> BasicBlock { + fn diverge_cleanup_gen(&mut self) -> BasicBlock { // Build up the drops in **reverse** order. The end result will // look like: // @@ -793,15 +770,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Find the last cached block let (mut target, first_uncached) = if let Some(cached_index) = self.scopes.iter() - .rposition(|scope| scope.cached_unwind.get(generator_drop).is_some()) { - (self.scopes[cached_index].cached_unwind.get(generator_drop).unwrap(), cached_index + 1) + .rposition(|scope| scope.cached_unwind.get().is_some()) { + (self.scopes[cached_index].cached_unwind.get().unwrap(), cached_index + 1) } else { (self.resume_block(), 0) }; for scope in self.scopes[first_uncached..].iter_mut() { target = build_diverge_scope(&mut self.cfg, scope.region_scope_span, - scope, target, generator_drop, self.is_generator); + scope, target, self.is_generator); } target @@ -881,7 +858,6 @@ fn build_scope_drops<'tcx>( mut block: BasicBlock, last_unwind_to: BasicBlock, arg_count: usize, - generator_drop: bool, ) -> BlockAnd<()> { debug!("build_scope_drops({:?} -> {:?}", block, scope); @@ -902,7 +878,7 @@ fn build_scope_drops<'tcx>( let mut unwind_blocks = scope.drops.iter().rev().filter_map(|drop_data| { if let DropKind::Value { cached_block } = drop_data.kind { - Some(cached_block.get(generator_drop).unwrap_or_else(|| { + Some(cached_block.get().unwrap_or_else(|| { span_bug!(drop_data.span, "cached block not present?") })) } else { @@ -946,13 +922,12 @@ fn build_scope_drops<'tcx>( block.unit() } -fn build_diverge_scope<'tcx>(cfg: &mut CFG<'tcx>, - span: Span, - scope: &mut Scope<'tcx>, - mut target: BasicBlock, - generator_drop: bool, - is_generator: bool) - -> BasicBlock +fn build_diverge_scope(cfg: &mut CFG<'tcx>, + span: Span, + scope: &mut Scope<'tcx>, + mut target: BasicBlock, + is_generator: bool) + -> BasicBlock { // Build up the drops in **reverse** order. The end result will // look like: @@ -1004,7 +979,7 @@ fn build_diverge_scope<'tcx>(cfg: &mut CFG<'tcx>, } DropKind::Storage => {} DropKind::Value { ref mut cached_block } => { - let cached_block = cached_block.ref_mut(generator_drop); + let cached_block = cached_block.ref_mut(); target = if let Some(cached_block) = *cached_block { storage_deads.clear(); target_built_by_us = false; @@ -1027,7 +1002,7 @@ fn build_diverge_scope<'tcx>(cfg: &mut CFG<'tcx>, }; } push_storage_deads(cfg, &mut target, &mut storage_deads, target_built_by_us, source_scope); - *scope.cached_unwind.ref_mut(generator_drop) = Some(target); + *scope.cached_unwind.ref_mut() = Some(target); assert!(storage_deads.is_empty()); debug!("build_diverge_scope({:?}, {:?}) = {:?}", scope, span, target); From 26c37d7b168781d8be0236fdcdcb502b6c2b8ee2 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Tue, 14 May 2019 18:33:04 -0700 Subject: [PATCH 0100/3207] Revert "Remove separation between generator_drop and unwind paths" This reverts commit 26a7228f0fd5929f2134ac36180eb1e8ff5e16e3. --- src/librustc_mir/build/scope.rs | 81 +++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 28 deletions(-) diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index e6cebd72f19d..3b11e335fb87 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -124,10 +124,7 @@ pub struct Scope<'tcx> { /// The cache for drop chain on "generator drop" exit. cached_generator_drop: Option, - /// The cache for drop chain on "unwind" exit. This block - /// contains code to run the current drop and all the preceding - /// drops (i.e., those having lower index in Drop’s Scope drop - /// array) + /// The cache for drop chain on "unwind" exit. cached_unwind: CachedBlock, } @@ -144,7 +141,21 @@ struct DropData<'tcx> { } #[derive(Debug, Default, Clone, Copy)] -pub(crate) struct CachedBlock(Option); +pub(crate) struct CachedBlock { + /// The cached block for the cleanups-on-diverge path. This block + /// contains code to run the current drop and all the preceding + /// drops (i.e., those having lower index in Drop’s Scope drop + /// array) + unwind: Option, + + /// The cached block for unwinds during cleanups-on-generator-drop path + /// + /// This is split from the standard unwind path here to prevent drop + /// elaboration from creating drop flags that would have to be captured + /// by the generator. I'm not sure how important this optimization is, + /// but it is here. + generator_drop: Option, +} #[derive(Debug)] pub(crate) enum DropKind { @@ -170,15 +181,24 @@ pub struct BreakableScope<'tcx> { impl CachedBlock { fn invalidate(&mut self) { - self.0 = None; + self.generator_drop = None; + self.unwind = None; } - fn get(&self) -> Option { - self.0 + fn get(&self, generator_drop: bool) -> Option { + if generator_drop { + self.generator_drop + } else { + self.unwind + } } - fn ref_mut(&mut self) -> &mut Option { - &mut self.0 + fn ref_mut(&mut self, generator_drop: bool) -> &mut Option { + if generator_drop { + &mut self.generator_drop + } else { + &mut self.unwind + } } } @@ -358,7 +378,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { assert_eq!(scope.region_scope, region_scope.0); let unwind_to = self.scopes.last().and_then(|next_scope| { - next_scope.cached_unwind.get() + next_scope.cached_unwind.get(false) }).unwrap_or_else(|| self.resume_block()); unpack!(block = build_scope_drops( @@ -367,6 +387,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { block, unwind_to, self.arg_count, + false, )); block.unit() @@ -421,7 +442,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } }; - let unwind_to = next_scope.cached_unwind.get().unwrap_or_else(|| { + let unwind_to = next_scope.cached_unwind.get(false).unwrap_or_else(|| { debug_assert!(!may_panic, "cached block not present?"); START_BLOCK }); @@ -432,6 +453,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { block, unwind_to, self.arg_count, + false, )); scope = next_scope; @@ -448,7 +470,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// None indicates there’s no cleanup to do at this point. pub fn generator_drop_cleanup(&mut self) -> Option { // Fill in the cache for unwinds - self.diverge_cleanup_gen(); + self.diverge_cleanup_gen(true); let src_info = self.scopes[0].source_info(self.fn_span); let resume_block = self.resume_block(); @@ -474,7 +496,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }; let unwind_to = scopes.peek().as_ref().map(|scope| { - scope.cached_unwind.get().unwrap_or_else(|| { + scope.cached_unwind.get(true).unwrap_or_else(|| { span_bug!(src_info.span, "cached block not present?") }) }).unwrap_or(resume_block); @@ -485,6 +507,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { block, unwind_to, self.arg_count, + true, )); } @@ -737,7 +760,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// This path terminates in Resume. Returns the start of the path. /// See module comment for more details. pub fn diverge_cleanup(&mut self) -> BasicBlock { - self.diverge_cleanup_gen() + self.diverge_cleanup_gen(false) } fn resume_block(&mut self) -> BasicBlock { @@ -756,7 +779,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } - fn diverge_cleanup_gen(&mut self) -> BasicBlock { + fn diverge_cleanup_gen(&mut self, generator_drop: bool) -> BasicBlock { // Build up the drops in **reverse** order. The end result will // look like: // @@ -770,15 +793,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Find the last cached block let (mut target, first_uncached) = if let Some(cached_index) = self.scopes.iter() - .rposition(|scope| scope.cached_unwind.get().is_some()) { - (self.scopes[cached_index].cached_unwind.get().unwrap(), cached_index + 1) + .rposition(|scope| scope.cached_unwind.get(generator_drop).is_some()) { + (self.scopes[cached_index].cached_unwind.get(generator_drop).unwrap(), cached_index + 1) } else { (self.resume_block(), 0) }; for scope in self.scopes[first_uncached..].iter_mut() { target = build_diverge_scope(&mut self.cfg, scope.region_scope_span, - scope, target, self.is_generator); + scope, target, generator_drop, self.is_generator); } target @@ -858,6 +881,7 @@ fn build_scope_drops<'tcx>( mut block: BasicBlock, last_unwind_to: BasicBlock, arg_count: usize, + generator_drop: bool, ) -> BlockAnd<()> { debug!("build_scope_drops({:?} -> {:?}", block, scope); @@ -878,7 +902,7 @@ fn build_scope_drops<'tcx>( let mut unwind_blocks = scope.drops.iter().rev().filter_map(|drop_data| { if let DropKind::Value { cached_block } = drop_data.kind { - Some(cached_block.get().unwrap_or_else(|| { + Some(cached_block.get(generator_drop).unwrap_or_else(|| { span_bug!(drop_data.span, "cached block not present?") })) } else { @@ -922,12 +946,13 @@ fn build_scope_drops<'tcx>( block.unit() } -fn build_diverge_scope(cfg: &mut CFG<'tcx>, - span: Span, - scope: &mut Scope<'tcx>, - mut target: BasicBlock, - is_generator: bool) - -> BasicBlock +fn build_diverge_scope<'tcx>(cfg: &mut CFG<'tcx>, + span: Span, + scope: &mut Scope<'tcx>, + mut target: BasicBlock, + generator_drop: bool, + is_generator: bool) + -> BasicBlock { // Build up the drops in **reverse** order. The end result will // look like: @@ -979,7 +1004,7 @@ fn build_diverge_scope(cfg: &mut CFG<'tcx>, } DropKind::Storage => {} DropKind::Value { ref mut cached_block } => { - let cached_block = cached_block.ref_mut(); + let cached_block = cached_block.ref_mut(generator_drop); target = if let Some(cached_block) = *cached_block { storage_deads.clear(); target_built_by_us = false; @@ -1002,7 +1027,7 @@ fn build_diverge_scope(cfg: &mut CFG<'tcx>, }; } push_storage_deads(cfg, &mut target, &mut storage_deads, target_built_by_us, source_scope); - *scope.cached_unwind.ref_mut() = Some(target); + *scope.cached_unwind.ref_mut(generator_drop) = Some(target); assert!(storage_deads.is_empty()); debug!("build_diverge_scope({:?}, {:?}) = {:?}", scope, span, target); From 9fd4d48b5e12494926041bb1a053d5891e661bc4 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 15 May 2019 11:54:16 +0200 Subject: [PATCH 0101/3207] Stabilize RefCell::try_borrow_unguarded Servo has been using this since https://github.com/servo/servo/pull/23196 to add a runtime check to some unsafe code, as discussed in PR https://github.com/rust-lang/rust/pull/59211. Stabilizing would help do more of the same in libraries that also have users on Stable. --- src/doc/unstable-book/src/library-features/borrow-state.md | 7 ------- src/libcore/cell.rs | 3 +-- 2 files changed, 1 insertion(+), 9 deletions(-) delete mode 100644 src/doc/unstable-book/src/library-features/borrow-state.md diff --git a/src/doc/unstable-book/src/library-features/borrow-state.md b/src/doc/unstable-book/src/library-features/borrow-state.md deleted file mode 100644 index 304b8dffe986..000000000000 --- a/src/doc/unstable-book/src/library-features/borrow-state.md +++ /dev/null @@ -1,7 +0,0 @@ -# `borrow_state` - -The tracking issue for this feature is: [#27733] - -[#27733]: https://github.com/rust-lang/rust/issues/27733 - ------------------------- diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index fcfd80d92660..5fc819f8efcb 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -969,7 +969,6 @@ impl RefCell { /// # Examples /// /// ``` - /// #![feature(borrow_state)] /// use std::cell::RefCell; /// /// let c = RefCell::new(5); @@ -984,7 +983,7 @@ impl RefCell { /// assert!(unsafe { c.try_borrow_unguarded() }.is_ok()); /// } /// ``` - #[unstable(feature = "borrow_state", issue = "27733")] + #[stable(feature = "borrow_state", since = "1.37.0")] #[inline] pub unsafe fn try_borrow_unguarded(&self) -> Result<&T, BorrowError> { if !is_writing(self.borrow.get()) { From 48e3da6d5910d119d4afefd7d06340390db6968d Mon Sep 17 00:00:00 2001 From: tyler Date: Sat, 27 Apr 2019 07:23:31 -0700 Subject: [PATCH 0102/3207] remove dead code: requires_move_before_drop --- src/libstd/sys/redox/fast_thread_local.rs | 4 ---- src/libstd/sys/unix/fast_thread_local.rs | 4 ---- src/libstd/sys/windows/fast_thread_local.rs | 4 ---- src/libstd/thread/local.rs | 15 +++------------ 4 files changed, 3 insertions(+), 24 deletions(-) diff --git a/src/libstd/sys/redox/fast_thread_local.rs b/src/libstd/sys/redox/fast_thread_local.rs index 1202708a4769..fd278bfe39ac 100644 --- a/src/libstd/sys/redox/fast_thread_local.rs +++ b/src/libstd/sys/redox/fast_thread_local.rs @@ -105,7 +105,3 @@ pub unsafe extern fn destroy_value(ptr: *mut u8) { ptr::drop_in_place((*ptr).inner.get()); } } - -pub fn requires_move_before_drop() -> bool { - false -} diff --git a/src/libstd/sys/unix/fast_thread_local.rs b/src/libstd/sys/unix/fast_thread_local.rs index 17478dce4fe5..c34c2e6e786e 100644 --- a/src/libstd/sys/unix/fast_thread_local.rs +++ b/src/libstd/sys/unix/fast_thread_local.rs @@ -82,7 +82,3 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { } } } - -pub fn requires_move_before_drop() -> bool { - false -} diff --git a/src/libstd/sys/windows/fast_thread_local.rs b/src/libstd/sys/windows/fast_thread_local.rs index 0ccc67e3fd54..31d0bd1e72ed 100644 --- a/src/libstd/sys/windows/fast_thread_local.rs +++ b/src/libstd/sys/windows/fast_thread_local.rs @@ -2,7 +2,3 @@ #![cfg(target_thread_local)] pub use crate::sys_common::thread_local::register_dtor_fallback as register_dtor; - -pub fn requires_move_before_drop() -> bool { - false -} diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index bfc1deddf7bd..0d5e1f2af38a 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -344,7 +344,7 @@ pub mod fast { use crate::fmt; use crate::mem; use crate::ptr; - use crate::sys::fast_thread_local::{register_dtor, requires_move_before_drop}; + use crate::sys::fast_thread_local::register_dtor; pub struct Key { inner: UnsafeCell>, @@ -395,17 +395,8 @@ pub mod fast { // destructor as running for this thread so calls to `get` will return // `None`. (*ptr).dtor_running.set(true); - - // Some implementations may require us to move the value before we drop - // it as it could get re-initialized in-place during destruction. - // - // Hence, we use `ptr::read` on those platforms (to move to a "safe" - // location) instead of drop_in_place. - if requires_move_before_drop() { - ptr::read((*ptr).inner.get()); - } else { - ptr::drop_in_place((*ptr).inner.get()); - } + + ptr::drop_in_place((*ptr).inner.get()); } } From ae4be16e407061828fe604b1ccbd61181b14a3f1 Mon Sep 17 00:00:00 2001 From: tyler Date: Sat, 27 Apr 2019 07:38:01 -0700 Subject: [PATCH 0103/3207] redox had a copy of fast thread local (oversight?) --- src/libstd/sys/redox/fast_thread_local.rs | 105 +--------------------- 1 file changed, 1 insertion(+), 104 deletions(-) diff --git a/src/libstd/sys/redox/fast_thread_local.rs b/src/libstd/sys/redox/fast_thread_local.rs index fd278bfe39ac..67b92d490b23 100644 --- a/src/libstd/sys/redox/fast_thread_local.rs +++ b/src/libstd/sys/redox/fast_thread_local.rs @@ -1,107 +1,4 @@ #![cfg(target_thread_local)] #![unstable(feature = "thread_local_internals", issue = "0")] -use crate::cell::{Cell, UnsafeCell}; -use crate::mem; -use crate::ptr; - - -pub struct Key { - inner: UnsafeCell>, - - // Metadata to keep track of the state of the destructor. Remember that - // these variables are thread-local, not global. - dtor_registered: Cell, - dtor_running: Cell, -} - -unsafe impl Sync for Key { } - -impl Key { - pub const fn new() -> Key { - Key { - inner: UnsafeCell::new(None), - dtor_registered: Cell::new(false), - dtor_running: Cell::new(false) - } - } - - pub fn get(&'static self) -> Option<&'static UnsafeCell>> { - unsafe { - if mem::needs_drop::() && self.dtor_running.get() { - return None - } - self.register_dtor(); - } - Some(&self.inner) - } - - unsafe fn register_dtor(&self) { - if !mem::needs_drop::() || self.dtor_registered.get() { - return - } - - register_dtor(self as *const _ as *mut u8, - destroy_value::); - self.dtor_registered.set(true); - } -} - -pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { - // The fallback implementation uses a vanilla OS-based TLS key to track - // the list of destructors that need to be run for this thread. The key - // then has its own destructor which runs all the other destructors. - // - // The destructor for DTORS is a little special in that it has a `while` - // loop to continuously drain the list of registered destructors. It - // *should* be the case that this loop always terminates because we - // provide the guarantee that a TLS key cannot be set after it is - // flagged for destruction. - use crate::sys_common::thread_local as os; - - static DTORS: os::StaticKey = os::StaticKey::new(Some(run_dtors)); - type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>; - if DTORS.get().is_null() { - let v: Box = box Vec::new(); - DTORS.set(Box::into_raw(v) as *mut u8); - } - let list: &mut List = &mut *(DTORS.get() as *mut List); - list.push((t, dtor)); - - unsafe extern fn run_dtors(mut ptr: *mut u8) { - while !ptr.is_null() { - let list: Box = Box::from_raw(ptr as *mut List); - for (ptr, dtor) in list.into_iter() { - dtor(ptr); - } - ptr = DTORS.get(); - DTORS.set(ptr::null_mut()); - } - } -} - -pub unsafe extern fn destroy_value(ptr: *mut u8) { - let ptr = ptr as *mut Key; - // Right before we run the user destructor be sure to flag the - // destructor as running for this thread so calls to `get` will return - // `None`. - (*ptr).dtor_running.set(true); - - // The macOS implementation of TLS apparently had an odd aspect to it - // where the pointer we have may be overwritten while this destructor - // is running. Specifically if a TLS destructor re-accesses TLS it may - // trigger a re-initialization of all TLS variables, paving over at - // least some destroyed ones with initial values. - // - // This means that if we drop a TLS value in place on macOS that we could - // revert the value to its original state halfway through the - // destructor, which would be bad! - // - // Hence, we use `ptr::read` on macOS (to move to a "safe" location) - // instead of drop_in_place. - if cfg!(target_os = "macos") { - ptr::read((*ptr).inner.get()); - } else { - ptr::drop_in_place((*ptr).inner.get()); - } -} +pub use crate::sys_common::thread_local::register_dtor_fallback as register_dtor; \ No newline at end of file From 430a091cd80c0e4b6bf44f6a19463a832e566f97 Mon Sep 17 00:00:00 2001 From: tyler Date: Sat, 27 Apr 2019 08:01:32 -0700 Subject: [PATCH 0104/3207] ensure fast thread local lookups occur once per access on macos --- src/libstd/sys/redox/fast_thread_local.rs | 6 +++++- src/libstd/sys/unix/fast_thread_local.rs | 17 +++++++++++++++++ src/libstd/sys/windows/fast_thread_local.rs | 4 ++++ src/libstd/thread/local.rs | 11 ++++++----- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/libstd/sys/redox/fast_thread_local.rs b/src/libstd/sys/redox/fast_thread_local.rs index 67b92d490b23..c34cd575db70 100644 --- a/src/libstd/sys/redox/fast_thread_local.rs +++ b/src/libstd/sys/redox/fast_thread_local.rs @@ -1,4 +1,8 @@ #![cfg(target_thread_local)] #![unstable(feature = "thread_local_internals", issue = "0")] -pub use crate::sys_common::thread_local::register_dtor_fallback as register_dtor; \ No newline at end of file +pub use crate::sys_common::thread_local::register_dtor_fallback as register_dtor; + +pub unsafe fn lookup_once(ptr: *const &T) -> &T { + *ptr +} diff --git a/src/libstd/sys/unix/fast_thread_local.rs b/src/libstd/sys/unix/fast_thread_local.rs index c34c2e6e786e..28fb98005410 100644 --- a/src/libstd/sys/unix/fast_thread_local.rs +++ b/src/libstd/sys/unix/fast_thread_local.rs @@ -82,3 +82,20 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { } } } + +#[cfg(not(target_os = "macos"))] +pub unsafe fn lookup_once(ptr: *const &T) -> &T { + *ptr +} + +#[cfg(target_os = "macos")] +pub unsafe fn lookup_once(ptr: *const &T) -> &T { + // On macos, thread_local lookups can result in terrible code due to + // aggressive rerunning of the macos equivalent of `__tls_get_addr` - four + // lookups per actual reference in user code. + // + // Using a read_volatile on a value holding fast Key's address tricks the + // optimizer into only calling the macos get_addr equivalent once per time + // requested by the user. + crate::ptr::read_volatile(ptr) +} diff --git a/src/libstd/sys/windows/fast_thread_local.rs b/src/libstd/sys/windows/fast_thread_local.rs index 31d0bd1e72ed..566d5524fd7c 100644 --- a/src/libstd/sys/windows/fast_thread_local.rs +++ b/src/libstd/sys/windows/fast_thread_local.rs @@ -2,3 +2,7 @@ #![cfg(target_thread_local)] pub use crate::sys_common::thread_local::register_dtor_fallback as register_dtor; + +pub unsafe fn lookup_once(ptr: *const &T) -> &T { + *ptr +} diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 0d5e1f2af38a..9ce2fcf23522 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -344,7 +344,7 @@ pub mod fast { use crate::fmt; use crate::mem; use crate::ptr; - use crate::sys::fast_thread_local::register_dtor; + use crate::sys::fast_thread_local::{lookup_once, register_dtor}; pub struct Key { inner: UnsafeCell>, @@ -371,11 +371,12 @@ pub mod fast { } pub unsafe fn get(&self) -> Option<&'static UnsafeCell>> { - if mem::needs_drop::() && self.dtor_running.get() { + let this = lookup_once(&self); + if mem::needs_drop::() && this.dtor_running.get() { return None } - self.register_dtor(); - Some(&*(&self.inner as *const _)) + this.register_dtor(); + Some(&*(&this.inner as *const _)) } unsafe fn register_dtor(&self) { @@ -395,7 +396,7 @@ pub mod fast { // destructor as running for this thread so calls to `get` will return // `None`. (*ptr).dtor_running.set(true); - + ptr::drop_in_place((*ptr).inner.get()); } } From 7acfb99adc013d4b77c611cfc51bade551205f5a Mon Sep 17 00:00:00 2001 From: tyler Date: Tue, 30 Apr 2019 18:24:38 -0700 Subject: [PATCH 0105/3207] Revert "ensure fast thread local lookups occur once per access on macos" This reverts commit d252f3b77f3b7d4cd59620588f9d026633c05816. --- src/libstd/sys/redox/fast_thread_local.rs | 6 +----- src/libstd/sys/unix/fast_thread_local.rs | 17 ----------------- src/libstd/sys/windows/fast_thread_local.rs | 4 ---- src/libstd/thread/local.rs | 11 +++++------ 4 files changed, 6 insertions(+), 32 deletions(-) diff --git a/src/libstd/sys/redox/fast_thread_local.rs b/src/libstd/sys/redox/fast_thread_local.rs index c34cd575db70..67b92d490b23 100644 --- a/src/libstd/sys/redox/fast_thread_local.rs +++ b/src/libstd/sys/redox/fast_thread_local.rs @@ -1,8 +1,4 @@ #![cfg(target_thread_local)] #![unstable(feature = "thread_local_internals", issue = "0")] -pub use crate::sys_common::thread_local::register_dtor_fallback as register_dtor; - -pub unsafe fn lookup_once(ptr: *const &T) -> &T { - *ptr -} +pub use crate::sys_common::thread_local::register_dtor_fallback as register_dtor; \ No newline at end of file diff --git a/src/libstd/sys/unix/fast_thread_local.rs b/src/libstd/sys/unix/fast_thread_local.rs index 28fb98005410..c34c2e6e786e 100644 --- a/src/libstd/sys/unix/fast_thread_local.rs +++ b/src/libstd/sys/unix/fast_thread_local.rs @@ -82,20 +82,3 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { } } } - -#[cfg(not(target_os = "macos"))] -pub unsafe fn lookup_once(ptr: *const &T) -> &T { - *ptr -} - -#[cfg(target_os = "macos")] -pub unsafe fn lookup_once(ptr: *const &T) -> &T { - // On macos, thread_local lookups can result in terrible code due to - // aggressive rerunning of the macos equivalent of `__tls_get_addr` - four - // lookups per actual reference in user code. - // - // Using a read_volatile on a value holding fast Key's address tricks the - // optimizer into only calling the macos get_addr equivalent once per time - // requested by the user. - crate::ptr::read_volatile(ptr) -} diff --git a/src/libstd/sys/windows/fast_thread_local.rs b/src/libstd/sys/windows/fast_thread_local.rs index 566d5524fd7c..31d0bd1e72ed 100644 --- a/src/libstd/sys/windows/fast_thread_local.rs +++ b/src/libstd/sys/windows/fast_thread_local.rs @@ -2,7 +2,3 @@ #![cfg(target_thread_local)] pub use crate::sys_common::thread_local::register_dtor_fallback as register_dtor; - -pub unsafe fn lookup_once(ptr: *const &T) -> &T { - *ptr -} diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 9ce2fcf23522..0d5e1f2af38a 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -344,7 +344,7 @@ pub mod fast { use crate::fmt; use crate::mem; use crate::ptr; - use crate::sys::fast_thread_local::{lookup_once, register_dtor}; + use crate::sys::fast_thread_local::register_dtor; pub struct Key { inner: UnsafeCell>, @@ -371,12 +371,11 @@ pub mod fast { } pub unsafe fn get(&self) -> Option<&'static UnsafeCell>> { - let this = lookup_once(&self); - if mem::needs_drop::() && this.dtor_running.get() { + if mem::needs_drop::() && self.dtor_running.get() { return None } - this.register_dtor(); - Some(&*(&this.inner as *const _)) + self.register_dtor(); + Some(&*(&self.inner as *const _)) } unsafe fn register_dtor(&self) { @@ -396,7 +395,7 @@ pub mod fast { // destructor as running for this thread so calls to `get` will return // `None`. (*ptr).dtor_running.set(true); - + ptr::drop_in_place((*ptr).inner.get()); } } From dfe51a7249e04431526cf3b4779316aabef53cca Mon Sep 17 00:00:00 2001 From: tyler Date: Thu, 2 May 2019 22:40:52 -0700 Subject: [PATCH 0106/3207] restructure thread_local! for better codegen (especially on macos) --- src/libstd/sys/redox/fast_thread_local.rs | 2 +- src/libstd/thread/local.rs | 285 ++++++++++++++-------- src/test/ui/issues/issue-43733.rs | 6 +- src/test/ui/issues/issue-43733.stderr | 8 +- 4 files changed, 195 insertions(+), 106 deletions(-) diff --git a/src/libstd/sys/redox/fast_thread_local.rs b/src/libstd/sys/redox/fast_thread_local.rs index 67b92d490b23..05464787a05d 100644 --- a/src/libstd/sys/redox/fast_thread_local.rs +++ b/src/libstd/sys/redox/fast_thread_local.rs @@ -1,4 +1,4 @@ #![cfg(target_thread_local)] #![unstable(feature = "thread_local_internals", issue = "0")] -pub use crate::sys_common::thread_local::register_dtor_fallback as register_dtor; \ No newline at end of file +pub use crate::sys_common::thread_local::register_dtor_fallback as register_dtor; diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 0d5e1f2af38a..7ff81bd9a173 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -2,10 +2,7 @@ #![unstable(feature = "thread_local_internals", issue = "0")] -use crate::cell::UnsafeCell; use crate::fmt; -use crate::hint; -use crate::mem; /// A thread local storage key which owns its contents. /// @@ -92,10 +89,7 @@ pub struct LocalKey { // trivially devirtualizable by LLVM because the value of `inner` never // changes and the constant should be readonly within a crate. This mainly // only runs into problems when TLS statics are exported across crates. - inner: unsafe fn() -> Option<&'static UnsafeCell>>, - - // initialization routine to invoke to create a value - init: fn() -> T, + inner: unsafe fn() -> Option<&'static T>, } #[stable(feature = "std_debug", since = "1.16.0")] @@ -159,10 +153,7 @@ macro_rules! __thread_local_inner { #[inline] fn __init() -> $t { $init } - unsafe fn __getit() -> $crate::option::Option< - &'static $crate::cell::UnsafeCell< - $crate::option::Option<$t>>> - { + unsafe fn __getit() -> $crate::option::Option<&'static $t> { #[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))] static __KEY: $crate::thread::__StaticLocalKeyInner<$t> = $crate::thread::__StaticLocalKeyInner::new(); @@ -182,11 +173,11 @@ macro_rules! __thread_local_inner { static __KEY: $crate::thread::__OsLocalKeyInner<$t> = $crate::thread::__OsLocalKeyInner::new(); - __KEY.get() + __KEY.get(__init) } unsafe { - $crate::thread::LocalKey::new(__getit, __init) + $crate::thread::LocalKey::new(__getit) } } }; @@ -221,11 +212,9 @@ impl LocalKey { #[unstable(feature = "thread_local_internals", reason = "recently added to create a key", issue = "0")] - pub const unsafe fn new(inner: unsafe fn() -> Option<&'static UnsafeCell>>, - init: fn() -> T) -> LocalKey { + pub const unsafe fn new(inner: unsafe fn() -> Option<&'static T>) -> LocalKey { LocalKey { inner, - init, } } @@ -246,37 +235,6 @@ impl LocalKey { after it is destroyed") } - unsafe fn init(&self, slot: &UnsafeCell>) -> &T { - // Execute the initialization up front, *then* move it into our slot, - // just in case initialization fails. - let value = (self.init)(); - let ptr = slot.get(); - - // note that this can in theory just be `*ptr = Some(value)`, but due to - // the compiler will currently codegen that pattern with something like: - // - // ptr::drop_in_place(ptr) - // ptr::write(ptr, Some(value)) - // - // Due to this pattern it's possible for the destructor of the value in - // `ptr` (e.g., if this is being recursively initialized) to re-access - // TLS, in which case there will be a `&` and `&mut` pointer to the same - // value (an aliasing violation). To avoid setting the "I'm running a - // destructor" flag we just use `mem::replace` which should sequence the - // operations a little differently and make this safe to call. - mem::replace(&mut *ptr, Some(value)); - - // After storing `Some` we want to get a reference to the contents of - // what we just stored. While we could use `unwrap` here and it should - // always work it empirically doesn't seem to always get optimized away, - // which means that using something like `try_with` can pull in - // panicking code and cause a large size bloat. - match *ptr { - Some(ref x) => x, - None => hint::unreachable_unchecked(), - } - } - /// Acquires a reference to the value in this TLS key. /// /// This will lazily initialize the value if this thread has not referenced @@ -293,13 +251,68 @@ impl LocalKey { F: FnOnce(&T) -> R, { unsafe { - let slot = (self.inner)().ok_or(AccessError { + let thread_local = (self.inner)().ok_or(AccessError { _private: (), })?; - Ok(f(match *slot.get() { - Some(ref inner) => inner, - None => self.init(slot), - })) + Ok(f(thread_local)) + } + } +} + +mod lazy { + use crate::cell::UnsafeCell; + use crate::mem; + use crate::hint; + + pub struct LazyKeyInner { + inner: UnsafeCell>, + } + + impl LazyKeyInner { + pub const fn new() -> LazyKeyInner { + LazyKeyInner { + inner: UnsafeCell::new(None), + } + } + + #[inline] + pub unsafe fn get(&self) -> Option<&'static T> { + (*self.inner.get()).as_ref() + } + + pub unsafe fn initialize T>(&self, init: F) -> &'static T { + // Execute the initialization up front, *then* move it into our slot, + // just in case initialization fails. + let value = init(); + let ptr = self.inner.get(); + + // note that this can in theory just be `*ptr = Some(value)`, but due to + // the compiler will currently codegen that pattern with something like: + // + // ptr::drop_in_place(ptr) + // ptr::write(ptr, Some(value)) + // + // Due to this pattern it's possible for the destructor of the value in + // `ptr` (e.g., if this is being recursively initialized) to re-access + // TLS, in which case there will be a `&` and `&mut` pointer to the same + // value (an aliasing violation). To avoid setting the "I'm running a + // destructor" flag we just use `mem::replace` which should sequence the + // operations a little differently and make this safe to call. + mem::replace(&mut *ptr, Some(value)); + + // After storing `Some` we want to get a reference to the contents of + // what we just stored. While we could use `unwrap` here and it should + // always work it empirically doesn't seem to always get optimized away, + // which means that using something like `try_with` can pull in + // panicking code and cause a large size bloat. + match *ptr { + Some(ref x) => x, + None => hint::unreachable_unchecked(), + } + } + + pub unsafe fn take(&mut self) -> Option { + (*self.inner.get()).take() } } } @@ -309,11 +322,12 @@ impl LocalKey { #[doc(hidden)] #[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))] pub mod statik { + use super::lazy::LazyKeyInner; use crate::cell::UnsafeCell; use crate::fmt; pub struct Key { - inner: UnsafeCell>, + inner: LazyKeyInner, } unsafe impl Sync for Key { } @@ -327,12 +341,17 @@ pub mod statik { impl Key { pub const fn new() -> Key { Key { - inner: UnsafeCell::new(None), + inner: LazyKeyInner::new(), } } - pub unsafe fn get(&self) -> Option<&'static UnsafeCell>> { - Some(&*(&self.inner as *const _)) + #[inline] + pub unsafe fn get(&self, init: fn() -> T) -> Option<&'static T> { + let value = match self.inner.get() { + Some(ref value) => value, + None => self.inner.initialize(init), + }; + Some(value) } } } @@ -340,19 +359,33 @@ pub mod statik { #[doc(hidden)] #[cfg(target_thread_local)] pub mod fast { - use crate::cell::{Cell, UnsafeCell}; + use super::lazy::LazyKeyInner; + use crate::cell::Cell; use crate::fmt; use crate::mem; - use crate::ptr; use crate::sys::fast_thread_local::register_dtor; + #[derive(Copy, Clone)] + enum DtorState { + Unregistered, + Registered, + RunningOrHasRun, + } + pub struct Key { - inner: UnsafeCell>, + // If `LazyKeyInner::get` returns `None`, that indicates either: + // * The value has never been initialized + // * The value is being recursively initialized + // * The value has already been destroyed or is being destroyed + // To determine which kind of `None`, check `dtor_state`. + // + // This is very optimizer friendly for the fast path - initialized but + // not yet dropped. + inner: LazyKeyInner, // Metadata to keep track of the state of the destructor. Remember that - // these variables are thread-local, not global. - dtor_registered: Cell, - dtor_running: Cell, + // this variable is thread-local, not global. + dtor_state: Cell, } impl fmt::Debug for Key { @@ -364,45 +397,84 @@ pub mod fast { impl Key { pub const fn new() -> Key { Key { - inner: UnsafeCell::new(None), - dtor_registered: Cell::new(false), - dtor_running: Cell::new(false) + inner: LazyKeyInner::new(), + dtor_state: Cell::new(DtorState::Unregistered), } } - pub unsafe fn get(&self) -> Option<&'static UnsafeCell>> { - if mem::needs_drop::() && self.dtor_running.get() { - return None + #[inline] + pub unsafe fn get T>(&self, init: F) -> Option<&'static T> { + match self.inner.get() { + Some(val) => Some(val), + None => { + if mem::needs_drop::() { + self.try_initialize_drop(init) + } else { + Some(self.try_initialize_nodrop(init)) + } + } } - self.register_dtor(); - Some(&*(&self.inner as *const _)) } - unsafe fn register_dtor(&self) { - if !mem::needs_drop::() || self.dtor_registered.get() { - return + // `try_initialize_nodrop` is only called once per fast thread local + // variable, except in corner cases where it is being recursively + // initialized. + // + // Macos: Inlining this function causes two `tlv_get_addr` calls to be + // performed for every call to `Key::get`. + // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722 + #[inline(never)] + #[cold] + unsafe fn try_initialize_nodrop T>(&self, init: F) -> &'static T { + self.inner.initialize(init) + } + + // `try_initialize_drop` is only called once per fast thread local + // variable, except in corner cases where thread_local dtors reference + // other thread_local's, or it is being recursively initialized. + #[inline(never)] + #[cold] + unsafe fn try_initialize_drop T>(&self, init: F) -> Option<&'static T> { + // We don't put a `needs_drop` check around this and call it a day + // because this function is not inlined. Unwrapping code gets + // generated for callers of `LocalKey::with` even if we always + // return `Some` here. + match self.dtor_state.get() { + DtorState::Unregistered => { + // dtor registration happens before initialization. + register_dtor(self as *const _ as *mut u8, + destroy_value::); + self.dtor_state.set(DtorState::Registered); + } + DtorState::Registered => { + // recursively initialized + } + DtorState::RunningOrHasRun => { + return None + } } - register_dtor(self as *const _ as *mut u8, - destroy_value::); - self.dtor_registered.set(true); + Some(self.inner.initialize(init)) } } unsafe extern fn destroy_value(ptr: *mut u8) { let ptr = ptr as *mut Key; - // Right before we run the user destructor be sure to flag the - // destructor as running for this thread so calls to `get` will return - // `None`. - (*ptr).dtor_running.set(true); - - ptr::drop_in_place((*ptr).inner.get()); + + // Right before we run the user destructor be sure to set the + // `Option` to `None`, and `dtor_state` to `RunningOrHasRun`. This + // causes future calls to `get` to run `try_initialize_drop` again, + // which will now fail, and return `None`. + let value = (*ptr).inner.take(); + (*ptr).dtor_state.set(DtorState::RunningOrHasRun); + drop(value); } } #[doc(hidden)] pub mod os { - use crate::cell::{Cell, UnsafeCell}; + use super::lazy::LazyKeyInner; + use crate::cell::Cell; use crate::fmt; use crate::marker; use crate::ptr; @@ -423,8 +495,8 @@ pub mod os { unsafe impl Sync for Key { } struct Value { + inner: LazyKeyInner, key: &'static Key, - value: UnsafeCell>, } impl Key { @@ -435,24 +507,43 @@ pub mod os { } } - pub unsafe fn get(&'static self) -> Option<&'static UnsafeCell>> { + pub unsafe fn get(&'static self, init: fn() -> T) -> Option<&'static T> { let ptr = self.os.get() as *mut Value; - if !ptr.is_null() { - if ptr as usize == 1 { - return None + if ptr as usize > 1 { + match (*ptr).inner.get() { + Some(ref value) => return Some(value), + None => {}, } - return Some(&(*ptr).value); + } + self.try_initialize(init) + } + + // `try_initialize` is only called once per os thread local variable, + // except in corner cases where thread_local dtors reference other + // thread_local's, or it is being recursively initialized. + unsafe fn try_initialize(&'static self, init: fn() -> T) -> Option<&'static T> { + let ptr = self.os.get() as *mut Value; + if ptr as usize == 1 { + // destructor is running + return None } - // If the lookup returned null, we haven't initialized our own - // local copy, so do that now. - let ptr: Box> = box Value { - key: self, - value: UnsafeCell::new(None), + let ptr = if ptr.is_null() { + // If the lookup returned null, we haven't initialized our own + // local copy, so do that now. + let ptr: Box> = box Value { + inner: LazyKeyInner::new(), + key: self, + }; + let ptr = Box::into_raw(ptr); + self.os.set(ptr as *mut u8); + ptr + } else { + // recursive initialization + ptr }; - let ptr = Box::into_raw(ptr); - self.os.set(ptr as *mut u8); - Some(&(*ptr).value) + + Some((*ptr).inner.initialize(init)) } } diff --git a/src/test/ui/issues/issue-43733.rs b/src/test/ui/issues/issue-43733.rs index 91192e3360c2..ba599ff7ce4d 100644 --- a/src/test/ui/issues/issue-43733.rs +++ b/src/test/ui/issues/issue-43733.rs @@ -13,11 +13,9 @@ static __KEY: std::thread::__FastLocalKeyInner = static __KEY: std::thread::__OsLocalKeyInner = std::thread::__OsLocalKeyInner::new(); -fn __getit() -> std::option::Option< - &'static std::cell::UnsafeCell< - std::option::Option>> +fn __getit(init: fn() -> Foo) -> std::option::Option<&'static Foo> { - __KEY.get() //~ ERROR call to unsafe function is unsafe + __KEY.get(init) //~ ERROR call to unsafe function is unsafe } static FOO: std::thread::LocalKey = diff --git a/src/test/ui/issues/issue-43733.stderr b/src/test/ui/issues/issue-43733.stderr index c48f9baf2719..0ea931d7fb6e 100644 --- a/src/test/ui/issues/issue-43733.stderr +++ b/src/test/ui/issues/issue-43733.stderr @@ -1,13 +1,13 @@ error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/issue-43733.rs:20:5 + --> $DIR/issue-43733.rs:18:5 | -LL | __KEY.get() - | ^^^^^^^^^^^ call to unsafe function +LL | __KEY.get(init) + | ^^^^^^^^^^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/issue-43733.rs:24:5 + --> $DIR/issue-43733.rs:22:5 | LL | std::thread::LocalKey::new(__getit, Default::default); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function From b266ba7850d3996b0f19f66d7a28478acfdcdbaf Mon Sep 17 00:00:00 2001 From: tyler Date: Thu, 2 May 2019 23:27:03 -0700 Subject: [PATCH 0107/3207] update test to match new doc(hidden) thread_local api --- src/test/ui/issues/issue-43733.rs | 6 +++--- src/test/ui/issues/issue-43733.stderr | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/test/ui/issues/issue-43733.rs b/src/test/ui/issues/issue-43733.rs index ba599ff7ce4d..a602d7667c48 100644 --- a/src/test/ui/issues/issue-43733.rs +++ b/src/test/ui/issues/issue-43733.rs @@ -13,13 +13,13 @@ static __KEY: std::thread::__FastLocalKeyInner = static __KEY: std::thread::__OsLocalKeyInner = std::thread::__OsLocalKeyInner::new(); -fn __getit(init: fn() -> Foo) -> std::option::Option<&'static Foo> +fn __getit() -> std::option::Option<&'static Foo> { - __KEY.get(init) //~ ERROR call to unsafe function is unsafe + __KEY.get(Default::default) //~ ERROR call to unsafe function is unsafe } static FOO: std::thread::LocalKey = - std::thread::LocalKey::new(__getit, Default::default); + std::thread::LocalKey::new(__getit); //~^ ERROR call to unsafe function is unsafe fn main() { diff --git a/src/test/ui/issues/issue-43733.stderr b/src/test/ui/issues/issue-43733.stderr index 0ea931d7fb6e..ee6a3b065d6e 100644 --- a/src/test/ui/issues/issue-43733.stderr +++ b/src/test/ui/issues/issue-43733.stderr @@ -1,16 +1,16 @@ error[E0133]: call to unsafe function is unsafe and requires unsafe function or block --> $DIR/issue-43733.rs:18:5 | -LL | __KEY.get(init) - | ^^^^^^^^^^^^^^^ call to unsafe function +LL | __KEY.get(Default::default) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function is unsafe and requires unsafe function or block --> $DIR/issue-43733.rs:22:5 | -LL | std::thread::LocalKey::new(__getit, Default::default); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function +LL | std::thread::LocalKey::new(__getit); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior From 516c03d5102d0ffb5cc1b86451d837c26d2a0f6a Mon Sep 17 00:00:00 2001 From: tyler Date: Fri, 3 May 2019 09:46:16 -0700 Subject: [PATCH 0108/3207] fix another test --- src/test/compile-fail/issue-43733-2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/compile-fail/issue-43733-2.rs b/src/test/compile-fail/issue-43733-2.rs index 2943089674d5..8e3c93ac251e 100644 --- a/src/test/compile-fail/issue-43733-2.rs +++ b/src/test/compile-fail/issue-43733-2.rs @@ -23,6 +23,6 @@ use std::thread::__FastLocalKeyInner as Key; static __KEY: Key<()> = Key::new(); //~^ ERROR `std::cell::UnsafeCell>` cannot be shared between threads -//~| ERROR `std::cell::Cell` cannot be shared between threads safely [E0277] +//~| ERROR `std::cell::Cell` cannot be shared between threads safely [E0277] fn main() {} From f5e56eeff6e0ed186410a358db565ab959648aba Mon Sep 17 00:00:00 2001 From: tyler Date: Fri, 3 May 2019 16:26:54 -0700 Subject: [PATCH 0109/3207] clang tidy fixes --- src/test/compile-fail/issue-43733-2.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/compile-fail/issue-43733-2.rs b/src/test/compile-fail/issue-43733-2.rs index 8e3c93ac251e..c14592187ab7 100644 --- a/src/test/compile-fail/issue-43733-2.rs +++ b/src/test/compile-fail/issue-43733-2.rs @@ -23,6 +23,7 @@ use std::thread::__FastLocalKeyInner as Key; static __KEY: Key<()> = Key::new(); //~^ ERROR `std::cell::UnsafeCell>` cannot be shared between threads -//~| ERROR `std::cell::Cell` cannot be shared between threads safely [E0277] +//~| ERROR `std::cell::Cell` cannot be shared between threads +// safely [E0277] fn main() {} From 060d8bb6b014f9e9c8b697c5ecd6d86159f122b9 Mon Sep 17 00:00:00 2001 From: tyler Date: Fri, 3 May 2019 17:01:53 -0700 Subject: [PATCH 0110/3207] add #[allow(unused)] --- src/libstd/thread/local.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 7ff81bd9a173..a56a34deba22 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -311,6 +311,7 @@ mod lazy { } } + #[allow(unused)] pub unsafe fn take(&mut self) -> Option { (*self.inner.get()).take() } From 1a7f774914d8d3c2a16e40332ad43270c461ec71 Mon Sep 17 00:00:00 2001 From: tyler Date: Fri, 10 May 2019 17:29:43 -0700 Subject: [PATCH 0111/3207] - remove unnecessary inlines - add comment explaining that the fast::Key data structure was carefully constructed for fast access on OSX - remove inline(never) from the initializer for types where `needs_drop::()` is false --- src/libstd/thread/local.rs | 39 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index a56a34deba22..e6f096a8da53 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -275,7 +275,6 @@ mod lazy { } } - #[inline] pub unsafe fn get(&self) -> Option<&'static T> { (*self.inner.get()).as_ref() } @@ -346,7 +345,6 @@ pub mod statik { } } - #[inline] pub unsafe fn get(&self, init: fn() -> T) -> Option<&'static T> { let value = match self.inner.get() { Some(ref value) => value, @@ -373,6 +371,11 @@ pub mod fast { RunningOrHasRun, } + // This data structure has been carefully constructed so that the fast path + // only contains one branch on x86. That optimization is necessary to avoid + // duplicated tls lookups on OSX. + // + // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722 pub struct Key { // If `LazyKeyInner::get` returns `None`, that indicates either: // * The value has never been initialized @@ -403,38 +406,32 @@ pub mod fast { } } - #[inline] pub unsafe fn get T>(&self, init: F) -> Option<&'static T> { match self.inner.get() { Some(val) => Some(val), - None => { - if mem::needs_drop::() { - self.try_initialize_drop(init) - } else { - Some(self.try_initialize_nodrop(init)) - } - } + None => self.try_initialize(init), } } - // `try_initialize_nodrop` is only called once per fast thread local - // variable, except in corner cases where it is being recursively - // initialized. - // - // Macos: Inlining this function causes two `tlv_get_addr` calls to be - // performed for every call to `Key::get`. - // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722 - #[inline(never)] + // `try_initialize` is only called once per fast thread local variable, + // except in corner cases where it is being recursively initialized. #[cold] - unsafe fn try_initialize_nodrop T>(&self, init: F) -> &'static T { - self.inner.initialize(init) + unsafe fn try_initialize T>(&self, init: F) -> Option<&'static T> { + if mem::needs_drop::() { + self.try_initialize_drop(init) + } else { + Some(self.inner.initialize(init)) + } } // `try_initialize_drop` is only called once per fast thread local // variable, except in corner cases where thread_local dtors reference // other thread_local's, or it is being recursively initialized. + // + // Macos: Inlining this function causes two `tlv_get_addr` calls to be + // performed for every call to `Key::get`. + // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722 #[inline(never)] - #[cold] unsafe fn try_initialize_drop T>(&self, init: F) -> Option<&'static T> { // We don't put a `needs_drop` check around this and call it a day // because this function is not inlined. Unwrapping code gets From c3241d0ba03ff1e90ffdb4cd434660f81194b438 Mon Sep 17 00:00:00 2001 From: tyler Date: Sat, 11 May 2019 10:14:40 -0700 Subject: [PATCH 0112/3207] cold was necessary on try_initialize_nodrop to get more straight line asm --- src/libstd/thread/local.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index e6f096a8da53..998d9dcc6833 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -432,6 +432,7 @@ pub mod fast { // performed for every call to `Key::get`. // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722 #[inline(never)] + #[cold] unsafe fn try_initialize_drop T>(&self, init: F) -> Option<&'static T> { // We don't put a `needs_drop` check around this and call it a day // because this function is not inlined. Unwrapping code gets From 2b3642b95b04b4078405f4bc20ba537ce5512c00 Mon Sep 17 00:00:00 2001 From: tyler Date: Sat, 11 May 2019 10:42:44 -0700 Subject: [PATCH 0113/3207] remove trailing whitespace --- src/libstd/thread/local.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 998d9dcc6833..1a12457646a1 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -374,7 +374,7 @@ pub mod fast { // This data structure has been carefully constructed so that the fast path // only contains one branch on x86. That optimization is necessary to avoid // duplicated tls lookups on OSX. - // + // // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722 pub struct Key { // If `LazyKeyInner::get` returns `None`, that indicates either: From 9289d03c9d263ac32a9dd0a5c581779fe1def7d3 Mon Sep 17 00:00:00 2001 From: tyler Date: Wed, 15 May 2019 07:18:24 -0700 Subject: [PATCH 0114/3207] llvm makes good inlining choices with only the #[cold] attribute --- src/libstd/thread/local.rs | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 1a12457646a1..733c772a1f5f 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -414,46 +414,42 @@ pub mod fast { } // `try_initialize` is only called once per fast thread local variable, - // except in corner cases where it is being recursively initialized. + // except in corner cases where thread_local dtors reference other + // thread_local's, or it is being recursively initialized. + // + // Macos: Inlining this function can cause two `tlv_get_addr` calls to + // be performed for every call to `Key::get`. The #[cold] hint makes + // that less likely. + // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722 #[cold] unsafe fn try_initialize T>(&self, init: F) -> Option<&'static T> { - if mem::needs_drop::() { - self.try_initialize_drop(init) - } else { + if !mem::needs_drop::() || self.try_register_dtor() { Some(self.inner.initialize(init)) + } else { + None } } - // `try_initialize_drop` is only called once per fast thread local + // `try_register_dtor` is only called once per fast thread local // variable, except in corner cases where thread_local dtors reference // other thread_local's, or it is being recursively initialized. - // - // Macos: Inlining this function causes two `tlv_get_addr` calls to be - // performed for every call to `Key::get`. - // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722 - #[inline(never)] - #[cold] - unsafe fn try_initialize_drop T>(&self, init: F) -> Option<&'static T> { - // We don't put a `needs_drop` check around this and call it a day - // because this function is not inlined. Unwrapping code gets - // generated for callers of `LocalKey::with` even if we always - // return `Some` here. + unsafe fn try_register_dtor(&self) -> bool { match self.dtor_state.get() { DtorState::Unregistered => { // dtor registration happens before initialization. register_dtor(self as *const _ as *mut u8, destroy_value::); self.dtor_state.set(DtorState::Registered); + true } DtorState::Registered => { // recursively initialized + true } DtorState::RunningOrHasRun => { - return None + false } } - - Some(self.inner.initialize(init)) } } From 92bf1e6661b76e2431132f370f5452fc0ad3448a Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 15 May 2019 14:44:25 +0200 Subject: [PATCH 0115/3207] ci: update azure variable groups --- .azure-pipelines/auto.yml | 2 +- .azure-pipelines/pr.yml | 3 --- .azure-pipelines/try.yml | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.azure-pipelines/auto.yml b/.azure-pipelines/auto.yml index 8202578b6701..2d240f8191a0 100644 --- a/.azure-pipelines/auto.yml +++ b/.azure-pipelines/auto.yml @@ -7,7 +7,7 @@ pr: none - auto variables: -- group: caching +- group: prod-credentials jobs: - job: Linux diff --git a/.azure-pipelines/pr.yml b/.azure-pipelines/pr.yml index ec9396e61e55..fe20e35e344a 100644 --- a/.azure-pipelines/pr.yml +++ b/.azure-pipelines/pr.yml @@ -6,9 +6,6 @@ trigger: none pr: - master # FIXME: really just want any branch, but want an explicit "pr" property set so it's clear -variables: -- group: caching-pr - jobs: - job: Linux timeoutInMinutes: 180 diff --git a/.azure-pipelines/try.yml b/.azure-pipelines/try.yml index 229927f4d34e..8a4f48830296 100644 --- a/.azure-pipelines/try.yml +++ b/.azure-pipelines/try.yml @@ -7,7 +7,7 @@ trigger: - try variables: -- group: caching +- group: prod-credentials jobs: - job: Linux From 30b008f5337332e0a1f941113d14f90fa876315e Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 15 May 2019 19:37:02 +0200 Subject: [PATCH 0116/3207] ci: remove stray echo --- 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 c7e64cd8c3e7..af0198705a2f 100755 --- a/src/ci/docker/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/x86_64-gnu-tools/checktools.sh @@ -6,7 +6,7 @@ X_PY="$1" TOOLSTATE_FILE="$(realpath $2)" OS="$3" COMMIT="$(git rev-parse HEAD)" -CHANGED_FILES="$(git diff --name-status HEAD HEAD^ || echo)" +CHANGED_FILES="$(git diff --name-status HEAD HEAD^)" SIX_WEEK_CYCLE="$(( ($(date +%s) / 86400 - 20) % 42 ))" # ^ Number of days after the last promotion of beta. # Its value is 41 on the Tuesday where "Promote master to beta (T-2)" happens. From bf639a1c34f6cee0cfb3b2ae5264b5f1261eb9c9 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 15 May 2019 19:38:26 +0200 Subject: [PATCH 0117/3207] ci: remove outdated comment --- .azure-pipelines/steps/linux.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.azure-pipelines/steps/linux.yml b/.azure-pipelines/steps/linux.yml index 3e83f0dcaaa8..238fd1d5ea78 100644 --- a/.azure-pipelines/steps/linux.yml +++ b/.azure-pipelines/steps/linux.yml @@ -17,7 +17,6 @@ steps: mkdir -p $HOME/rustsrc displayName: Prep -# FIXME: using the job display name feels brittle. Is there a better variable that represents the current matrix key? - bash: | export RUN_SCRIPT="$BUILD_SOURCESDIRECTORY/src/ci/init_repo.sh . $HOME/rustsrc && src/ci/docker/run.sh $IMAGE" echo "##vso[task.setvariable variable=IMAGE]$IMAGE" From 2c3796172ba2d41f15294e116cd8d993f026b7c2 Mon Sep 17 00:00:00 2001 From: tyler Date: Wed, 15 May 2019 14:35:24 -0700 Subject: [PATCH 0118/3207] fix wasm unused import in thread local implementation --- src/libstd/thread/local.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 733c772a1f5f..9b355aa2023f 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -323,7 +323,6 @@ mod lazy { #[cfg(all(target_arch = "wasm32", not(target_feature = "atomics")))] pub mod statik { use super::lazy::LazyKeyInner; - use crate::cell::UnsafeCell; use crate::fmt; pub struct Key { From c95be3d033a72880749813ae0bfc7067437f9c19 Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Thu, 16 May 2019 14:32:28 -0400 Subject: [PATCH 0119/3207] strip synstructure consts from compiler docs --- Cargo.lock | 8 ++++---- src/bootstrap/doc.rs | 2 +- src/librustc_macros/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4417c25abcb4..6efce4297dcd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -835,7 +835,7 @@ dependencies = [ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2849,7 +2849,7 @@ dependencies = [ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3385,7 +3385,7 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4306,7 +4306,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" -"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" +"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" "checksum tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "a303ba60a099fcd2aaa646b14d2724591a96a75283e4b7ed3d1a1658909d9ae2" "checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2" "checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508" diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 9c3a17bff6b7..5605ec34083b 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -728,7 +728,7 @@ impl Step for Rustc { // Build cargo command. let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "doc"); - cargo.env("RUSTDOCFLAGS", "--document-private-items"); + cargo.env("RUSTDOCFLAGS", "--document-private-items --passes strip-hidden"); compile::rustc_cargo(builder, &mut cargo); // Only include compiler crates, no dependencies of those, such as `libc`. diff --git a/src/librustc_macros/Cargo.toml b/src/librustc_macros/Cargo.toml index 6e32a53c364a..f989ebc6dfd8 100644 --- a/src/librustc_macros/Cargo.toml +++ b/src/librustc_macros/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" proc-macro = true [dependencies] -synstructure = "0.10.1" +synstructure = "0.10.2" syn = { version = "0.15.22", features = ["full"] } proc-macro2 = "0.4.24" quote = "0.6.10" From ba3785ec0a959b074450686dca7bb16182cf8d1a Mon Sep 17 00:00:00 2001 From: Chandler Deng Date: Thu, 16 May 2019 15:05:56 -0700 Subject: [PATCH 0120/3207] add targetarch for CodegenContext --- src/librustc_codegen_llvm/back/write.rs | 4 ++-- src/librustc_codegen_ssa/back/write.rs | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index cb59cf41a3ca..66ba95810a62 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -795,10 +795,10 @@ fn create_msvc_imps( return } // The x86 ABI seems to require that leading underscores are added to symbol - // names, so we need an extra underscore on 32-bit. There's also a leading + // names, so we need an extra underscore on x86. There's also a leading // '\x01' here which disables LLVM's symbol mangling (e.g., no extra // underscores added in front). - let prefix = if cgcx.target_pointer_width == "32" { + let prefix = if cgcx.target_arch == "x86" { "\x01__imp__" } else { "\x01__imp_" diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 6320d8a671dd..1c793996c83d 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -248,6 +248,7 @@ pub struct CodegenContext { pub tm_factory: TargetMachineFactory, pub msvc_imps_needed: bool, pub target_pointer_width: String, + pub target_arch: String, pub debuginfo: config::DebugInfo, // Number of cgus excluding the allocator/metadata modules @@ -1103,6 +1104,7 @@ fn start_executing_work( total_cgus, msvc_imps_needed: msvc_imps_needed(tcx), target_pointer_width: tcx.sess.target.target.target_pointer_width.clone(), + target_arch: tcx.sess.target.target.arch.clone(), debuginfo: tcx.sess.opts.debuginfo, assembler_cmd, }; From d2d89b10de394b4a1d5e2491dfffd3d65d1741b3 Mon Sep 17 00:00:00 2001 From: Sean McArthur Date: Thu, 16 May 2019 17:09:04 -0700 Subject: [PATCH 0121/3207] error: remove StringError from Debug output Seeing `StringError("something something")` in debug output can cause someone to think there was an error dealing with `String`s, not that the error type is just a string. So, remove that noise. --- src/libstd/error.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 7cb830e751a7..9424e059a14f 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -300,7 +300,6 @@ impl From for Box { /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) /// ``` fn from(err: String) -> Box { - #[derive(Debug)] struct StringError(String); impl Error for StringError { @@ -313,6 +312,13 @@ impl From for Box { } } + // Purposefully skip printing "StringError(..)" + impl Debug for StringError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Debug::fmt(&self.0, f) + } + } + Box::new(StringError(err)) } } From eed1e1ecd265071dc45abcd331272e6bb1b919d7 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 17 May 2019 15:27:08 +0200 Subject: [PATCH 0122/3207] Remove unused field from StableHasher. --- src/librustc_data_structures/stable_hasher.rs | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index fa573907d4c7..13e245d3c01e 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -15,7 +15,6 @@ use crate::bit_set; /// extended to 64 bits if needed. pub struct StableHasher { state: SipHasher128, - bytes_hashed: u64, width: PhantomData, } @@ -33,7 +32,6 @@ impl StableHasher { pub fn new() -> Self { StableHasher { state: SipHasher128::new_with_keys(0, 0), - bytes_hashed: 0, width: PhantomData, } } @@ -61,11 +59,6 @@ impl StableHasher { pub fn finalize(self) -> (u64, u64) { self.state.finish128() } - - #[inline] - pub fn bytes_hashed(&self) -> u64 { - self.bytes_hashed - } } impl Hasher for StableHasher { @@ -76,37 +69,31 @@ impl Hasher for StableHasher { #[inline] fn write(&mut self, bytes: &[u8]) { self.state.write(bytes); - self.bytes_hashed += bytes.len() as u64; } #[inline] fn write_u8(&mut self, i: u8) { self.state.write_u8(i); - self.bytes_hashed += 1; } #[inline] fn write_u16(&mut self, i: u16) { self.state.write_u16(i.to_le()); - self.bytes_hashed += 2; } #[inline] fn write_u32(&mut self, i: u32) { self.state.write_u32(i.to_le()); - self.bytes_hashed += 4; } #[inline] fn write_u64(&mut self, i: u64) { self.state.write_u64(i.to_le()); - self.bytes_hashed += 8; } #[inline] fn write_u128(&mut self, i: u128) { self.state.write_u128(i.to_le()); - self.bytes_hashed += 16; } #[inline] @@ -115,37 +102,31 @@ impl Hasher for StableHasher { // platforms. This is important for symbol hashes when cross compiling, // for example. self.state.write_u64((i as u64).to_le()); - self.bytes_hashed += 8; } #[inline] fn write_i8(&mut self, i: i8) { self.state.write_i8(i); - self.bytes_hashed += 1; } #[inline] fn write_i16(&mut self, i: i16) { self.state.write_i16(i.to_le()); - self.bytes_hashed += 2; } #[inline] fn write_i32(&mut self, i: i32) { self.state.write_i32(i.to_le()); - self.bytes_hashed += 4; } #[inline] fn write_i64(&mut self, i: i64) { self.state.write_i64(i.to_le()); - self.bytes_hashed += 8; } #[inline] fn write_i128(&mut self, i: i128) { self.state.write_i128(i.to_le()); - self.bytes_hashed += 16; } #[inline] @@ -154,7 +135,6 @@ impl Hasher for StableHasher { // platforms. This is important for symbol hashes when cross compiling, // for example. self.state.write_i64((i as i64).to_le()); - self.bytes_hashed += 8; } } From f950193d74d13628537a04728eef25cec642e41b Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 17 May 2019 11:36:25 -0700 Subject: [PATCH 0123/3207] Remove the unstable and deprecated mpsc_select This removes macro `select!` and `std::sync::mpsc::{Handle, Select}`, which were all unstable and have been deprecated since 1.32. --- src/libstd/macros.rs | 55 --- src/libstd/sync/mpsc/mod.rs | 85 +--- src/libstd/sync/mpsc/oneshot.rs | 72 --- src/libstd/sync/mpsc/select.rs | 352 --------------- src/libstd/sync/mpsc/select_tests.rs | 413 ------------------ src/libstd/sync/mpsc/shared.rs | 35 +- src/libstd/sync/mpsc/stream.rs | 53 --- src/libstd/sync/mpsc/sync.rs | 37 -- src/test/run-pass/issues/issue-13494.rs | 35 -- .../run-pass/macros/macro-comma-support.rs | 2 - 10 files changed, 9 insertions(+), 1130 deletions(-) delete mode 100644 src/libstd/sync/mpsc/select.rs delete mode 100644 src/libstd/sync/mpsc/select_tests.rs delete mode 100644 src/test/run-pass/issues/issue-13494.rs diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 03aebeda47c4..9af7bba97aa5 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -357,61 +357,6 @@ macro_rules! dbg { }; } -/// Selects the first successful receive event from a number of receivers. -/// -/// This macro is used to wait for the first event to occur on a number of -/// receivers. It places no restrictions on the types of receivers given to -/// this macro, this can be viewed as a heterogeneous select. -/// -/// # Examples -/// -/// ``` -/// #![feature(mpsc_select)] -/// -/// use std::thread; -/// use std::sync::mpsc; -/// -/// // two placeholder functions for now -/// fn long_running_thread() {} -/// fn calculate_the_answer() -> u32 { 42 } -/// -/// let (tx1, rx1) = mpsc::channel(); -/// let (tx2, rx2) = mpsc::channel(); -/// -/// thread::spawn(move|| { long_running_thread(); tx1.send(()).unwrap(); }); -/// thread::spawn(move|| { tx2.send(calculate_the_answer()).unwrap(); }); -/// -/// select! { -/// _ = rx1.recv() => println!("the long running thread finished first"), -/// answer = rx2.recv() => { -/// println!("the answer was: {}", answer.unwrap()); -/// } -/// } -/// # drop(rx1.recv()); -/// # drop(rx2.recv()); -/// ``` -/// -/// For more information about select, see the `std::sync::mpsc::Select` structure. -#[macro_export] -#[unstable(feature = "mpsc_select", issue = "27800")] -#[rustc_deprecated(since = "1.32.0", - reason = "channel selection will be removed in a future release")] -macro_rules! select { - ( - $($name:pat = $rx:ident.$meth:ident() => $code:expr),+ - ) => ({ - use $crate::sync::mpsc::Select; - let sel = Select::new(); - $( let mut $rx = sel.handle(&$rx); )+ - unsafe { - $( $rx.add(); )+ - } - let ret = sel.wait(); - $( if ret == $rx.id() { let $name = $rx.$meth(); $code } else )+ - { unreachable!() } - }) -} - #[cfg(test)] macro_rules! assert_approx_eq { ($a:expr, $b:expr) => ({ diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 04353fde1b4d..69ecd201063b 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -116,7 +116,6 @@ //! ``` #![stable(feature = "rust1", since = "1.0.0")] -#![allow(deprecated)] // for mpsc_select // A description of how Rust's channel implementation works // @@ -263,6 +262,8 @@ // believe that there is anything fundamental that needs to change about these // channels, however, in order to support a more efficient select(). // +// FIXME: Select is now removed, so these factors are ready to be cleaned up! +// // # Conclusion // // And now that you've seen all the races that I found and attempted to fix, @@ -275,18 +276,8 @@ use crate::mem; use crate::cell::UnsafeCell; use crate::time::{Duration, Instant}; -#[unstable(feature = "mpsc_select", issue = "27800")] -pub use self::select::{Select, Handle}; -use self::select::StartResult; -use self::select::StartResult::*; -use self::blocking::SignalToken; - -#[cfg(all(test, not(target_os = "emscripten")))] -mod select_tests; - mod blocking; mod oneshot; -mod select; mod shared; mod stream; mod sync; @@ -1514,78 +1505,6 @@ impl Receiver { } -impl select::Packet for Receiver { - fn can_recv(&self) -> bool { - loop { - let new_port = match *unsafe { self.inner() } { - Flavor::Oneshot(ref p) => { - match p.can_recv() { - Ok(ret) => return ret, - Err(upgrade) => upgrade, - } - } - Flavor::Stream(ref p) => { - match p.can_recv() { - Ok(ret) => return ret, - Err(upgrade) => upgrade, - } - } - Flavor::Shared(ref p) => return p.can_recv(), - Flavor::Sync(ref p) => return p.can_recv(), - }; - unsafe { - mem::swap(self.inner_mut(), - new_port.inner_mut()); - } - } - } - - fn start_selection(&self, mut token: SignalToken) -> StartResult { - loop { - let (t, new_port) = match *unsafe { self.inner() } { - Flavor::Oneshot(ref p) => { - match p.start_selection(token) { - oneshot::SelSuccess => return Installed, - oneshot::SelCanceled => return Abort, - oneshot::SelUpgraded(t, rx) => (t, rx), - } - } - Flavor::Stream(ref p) => { - match p.start_selection(token) { - stream::SelSuccess => return Installed, - stream::SelCanceled => return Abort, - stream::SelUpgraded(t, rx) => (t, rx), - } - } - Flavor::Shared(ref p) => return p.start_selection(token), - Flavor::Sync(ref p) => return p.start_selection(token), - }; - token = t; - unsafe { - mem::swap(self.inner_mut(), new_port.inner_mut()); - } - } - } - - fn abort_selection(&self) -> bool { - let mut was_upgrade = false; - loop { - let result = match *unsafe { self.inner() } { - Flavor::Oneshot(ref p) => p.abort_selection(), - Flavor::Stream(ref p) => p.abort_selection(was_upgrade), - Flavor::Shared(ref p) => return p.abort_selection(was_upgrade), - Flavor::Sync(ref p) => return p.abort_selection(), - }; - let new_port = match result { Ok(b) => return b, Err(p) => p }; - was_upgrade = true; - unsafe { - mem::swap(self.inner_mut(), - new_port.inner_mut()); - } - } - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Iterator for Iter<'a, T> { type Item = T; diff --git a/src/libstd/sync/mpsc/oneshot.rs b/src/libstd/sync/mpsc/oneshot.rs index 5c516d5de0f1..e7a5cc46b31a 100644 --- a/src/libstd/sync/mpsc/oneshot.rs +++ b/src/libstd/sync/mpsc/oneshot.rs @@ -24,7 +24,6 @@ pub use self::Failure::*; pub use self::UpgradeResult::*; -pub use self::SelectionResult::*; use self::MyUpgrade::*; use crate::sync::mpsc::Receiver; @@ -66,12 +65,6 @@ pub enum UpgradeResult { UpWoke(SignalToken), } -pub enum SelectionResult { - SelCanceled, - SelUpgraded(SignalToken, Receiver), - SelSuccess, -} - enum MyUpgrade { NothingSent, SendUsed, @@ -264,71 +257,6 @@ impl Packet { // select implementation //////////////////////////////////////////////////////////////////////////// - // If Ok, the value is whether this port has data, if Err, then the upgraded - // port needs to be checked instead of this one. - pub fn can_recv(&self) -> Result> { - unsafe { - match self.state.load(Ordering::SeqCst) { - EMPTY => Ok(false), // Welp, we tried - DATA => Ok(true), // we have some un-acquired data - DISCONNECTED if (*self.data.get()).is_some() => Ok(true), // we have data - DISCONNECTED => { - match ptr::replace(self.upgrade.get(), SendUsed) { - // The other end sent us an upgrade, so we need to - // propagate upwards whether the upgrade can receive - // data - GoUp(upgrade) => Err(upgrade), - - // If the other end disconnected without sending an - // upgrade, then we have data to receive (the channel is - // disconnected). - up => { ptr::write(self.upgrade.get(), up); Ok(true) } - } - } - _ => unreachable!(), // we're the "one blocker" - } - } - } - - // Attempts to start selection on this port. This can either succeed, fail - // because there is data, or fail because there is an upgrade pending. - pub fn start_selection(&self, token: SignalToken) -> SelectionResult { - unsafe { - let ptr = token.cast_to_usize(); - match self.state.compare_and_swap(EMPTY, ptr, Ordering::SeqCst) { - EMPTY => SelSuccess, - DATA => { - drop(SignalToken::cast_from_usize(ptr)); - SelCanceled - } - DISCONNECTED if (*self.data.get()).is_some() => { - drop(SignalToken::cast_from_usize(ptr)); - SelCanceled - } - DISCONNECTED => { - match ptr::replace(self.upgrade.get(), SendUsed) { - // The other end sent us an upgrade, so we need to - // propagate upwards whether the upgrade can receive - // data - GoUp(upgrade) => { - SelUpgraded(SignalToken::cast_from_usize(ptr), upgrade) - } - - // If the other end disconnected without sending an - // upgrade, then we have data to receive (the channel is - // disconnected). - up => { - ptr::write(self.upgrade.get(), up); - drop(SignalToken::cast_from_usize(ptr)); - SelCanceled - } - } - } - _ => unreachable!(), // we're the "one blocker" - } - } - } - // Remove a previous selecting thread from this port. This ensures that the // blocked thread will no longer be visible to any other threads. // diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs deleted file mode 100644 index d1b5f2deccc1..000000000000 --- a/src/libstd/sync/mpsc/select.rs +++ /dev/null @@ -1,352 +0,0 @@ -//! Selection over an array of receivers -//! -//! This module contains the implementation machinery necessary for selecting -//! over a number of receivers. One large goal of this module is to provide an -//! efficient interface to selecting over any receiver of any type. -//! -//! This is achieved through an architecture of a "receiver set" in which -//! receivers are added to a set and then the entire set is waited on at once. -//! The set can be waited on multiple times to prevent re-adding each receiver -//! to the set. -//! -//! Usage of this module is currently encouraged to go through the use of the -//! `select!` macro. This macro allows naturally binding of variables to the -//! received values of receivers in a much more natural syntax then usage of the -//! `Select` structure directly. -//! -//! # Examples -//! -//! ```rust -//! #![feature(mpsc_select)] -//! -//! use std::sync::mpsc::channel; -//! -//! let (tx1, rx1) = channel(); -//! let (tx2, rx2) = channel(); -//! -//! tx1.send(1).unwrap(); -//! tx2.send(2).unwrap(); -//! -//! select! { -//! val = rx1.recv() => { -//! assert_eq!(val.unwrap(), 1); -//! }, -//! val = rx2.recv() => { -//! assert_eq!(val.unwrap(), 2); -//! } -//! } -//! ``` - -#![allow(dead_code)] -#![unstable(feature = "mpsc_select", - reason = "This implementation, while likely sufficient, is unsafe and \ - likely to be error prone. At some point in the future this \ - module will be removed.", - issue = "27800")] -#![rustc_deprecated(since = "1.32.0", - reason = "channel selection will be removed in a future release")] - -use core::cell::{Cell, UnsafeCell}; -use core::marker; -use core::ptr; -use core::usize; - -use crate::fmt; -use crate::sync::mpsc::{Receiver, RecvError}; -use crate::sync::mpsc::blocking::{self, SignalToken}; - -/// The "receiver set" of the select interface. This structure is used to manage -/// a set of receivers which are being selected over. -pub struct Select { - inner: UnsafeCell, - next_id: Cell, -} - -struct SelectInner { - head: *mut Handle<'static, ()>, - tail: *mut Handle<'static, ()>, -} - -impl !marker::Send for Select {} - -/// A handle to a receiver which is currently a member of a `Select` set of -/// receivers. This handle is used to keep the receiver in the set as well as -/// interact with the underlying receiver. -pub struct Handle<'rx, T:Send+'rx> { - /// The ID of this handle, used to compare against the return value of - /// `Select::wait()`. - id: usize, - selector: *mut SelectInner, - next: *mut Handle<'static, ()>, - prev: *mut Handle<'static, ()>, - added: bool, - packet: &'rx (dyn Packet+'rx), - - // due to our fun transmutes, we be sure to place this at the end. (nothing - // previous relies on T) - rx: &'rx Receiver, -} - -struct Packets { cur: *mut Handle<'static, ()> } - -#[doc(hidden)] -#[derive(PartialEq, Eq)] -pub enum StartResult { - Installed, - Abort, -} - -#[doc(hidden)] -pub trait Packet { - fn can_recv(&self) -> bool; - fn start_selection(&self, token: SignalToken) -> StartResult; - fn abort_selection(&self) -> bool; -} - -impl Select { - /// Creates a new selection structure. This set is initially empty. - /// - /// Usage of this struct directly can sometimes be burdensome, and usage is much easier through - /// the `select!` macro. - /// - /// # Examples - /// - /// ``` - /// #![feature(mpsc_select)] - /// - /// use std::sync::mpsc::Select; - /// - /// let select = Select::new(); - /// ``` - pub fn new() -> Select { - Select { - inner: UnsafeCell::new(SelectInner { - head: ptr::null_mut(), - tail: ptr::null_mut(), - }), - next_id: Cell::new(1), - } - } - - /// Creates a new handle into this receiver set for a new receiver. Note - /// that this does *not* add the receiver to the receiver set, for that you - /// must call the `add` method on the handle itself. - pub fn handle<'a, T: Send>(&'a self, rx: &'a Receiver) -> Handle<'a, T> { - let id = self.next_id.get(); - self.next_id.set(id + 1); - Handle { - id, - selector: self.inner.get(), - next: ptr::null_mut(), - prev: ptr::null_mut(), - added: false, - rx, - packet: rx, - } - } - - /// Waits for an event on this receiver set. The returned value is *not* an - /// index, but rather an ID. This ID can be queried against any active - /// `Handle` structures (each one has an `id` method). The handle with - /// the matching `id` will have some sort of event available on it. The - /// event could either be that data is available or the corresponding - /// channel has been closed. - pub fn wait(&self) -> usize { - self.wait2(true) - } - - /// Helper method for skipping the preflight checks during testing - pub(super) fn wait2(&self, do_preflight_checks: bool) -> usize { - // Note that this is currently an inefficient implementation. We in - // theory have knowledge about all receivers in the set ahead of time, - // so this method shouldn't really have to iterate over all of them yet - // again. The idea with this "receiver set" interface is to get the - // interface right this time around, and later this implementation can - // be optimized. - // - // This implementation can be summarized by: - // - // fn select(receivers) { - // if any receiver ready { return ready index } - // deschedule { - // block on all receivers - // } - // unblock on all receivers - // return ready index - // } - // - // Most notably, the iterations over all of the receivers shouldn't be - // necessary. - unsafe { - // Stage 1: preflight checks. Look for any packets ready to receive - if do_preflight_checks { - for handle in self.iter() { - if (*handle).packet.can_recv() { - return (*handle).id(); - } - } - } - - // Stage 2: begin the blocking process - // - // Create a number of signal tokens, and install each one - // sequentially until one fails. If one fails, then abort the - // selection on the already-installed tokens. - let (wait_token, signal_token) = blocking::tokens(); - for (i, handle) in self.iter().enumerate() { - match (*handle).packet.start_selection(signal_token.clone()) { - StartResult::Installed => {} - StartResult::Abort => { - // Go back and abort the already-begun selections - for handle in self.iter().take(i) { - (*handle).packet.abort_selection(); - } - return (*handle).id; - } - } - } - - // Stage 3: no messages available, actually block - wait_token.wait(); - - // Stage 4: there *must* be message available; find it. - // - // Abort the selection process on each receiver. If the abort - // process returns `true`, then that means that the receiver is - // ready to receive some data. Note that this also means that the - // receiver may have yet to have fully read the `to_wake` field and - // woken us up (although the wakeup is guaranteed to fail). - // - // This situation happens in the window of where a sender invokes - // increment(), sees -1, and then decides to wake up the thread. After - // all this is done, the sending thread will set `selecting` to - // `false`. Until this is done, we cannot return. If we were to - // return, then a sender could wake up a receiver which has gone - // back to sleep after this call to `select`. - // - // Note that it is a "fairly small window" in which an increment() - // views that it should wake a thread up until the `selecting` bit - // is set to false. For now, the implementation currently just spins - // in a yield loop. This is very distasteful, but this - // implementation is already nowhere near what it should ideally be. - // A rewrite should focus on avoiding a yield loop, and for now this - // implementation is tying us over to a more efficient "don't - // iterate over everything every time" implementation. - let mut ready_id = usize::MAX; - for handle in self.iter() { - if (*handle).packet.abort_selection() { - ready_id = (*handle).id; - } - } - - // We must have found a ready receiver - assert!(ready_id != usize::MAX); - return ready_id; - } - } - - fn iter(&self) -> Packets { Packets { cur: unsafe { &*self.inner.get() }.head } } -} - -impl<'rx, T: Send> Handle<'rx, T> { - /// Retrieves the ID of this handle. - #[inline] - pub fn id(&self) -> usize { self.id } - - /// Blocks to receive a value on the underlying receiver, returning `Some` on - /// success or `None` if the channel disconnects. This function has the same - /// semantics as `Receiver.recv` - pub fn recv(&mut self) -> Result { self.rx.recv() } - - /// Adds this handle to the receiver set that the handle was created from. This - /// method can be called multiple times, but it has no effect if `add` was - /// called previously. - /// - /// This method is unsafe because it requires that the `Handle` is not moved - /// while it is added to the `Select` set. - pub unsafe fn add(&mut self) { - if self.added { return } - let selector = &mut *self.selector; - let me = self as *mut Handle<'rx, T> as *mut Handle<'static, ()>; - - if selector.head.is_null() { - selector.head = me; - selector.tail = me; - } else { - (*me).prev = selector.tail; - assert!((*me).next.is_null()); - (*selector.tail).next = me; - selector.tail = me; - } - self.added = true; - } - - /// Removes this handle from the `Select` set. This method is unsafe because - /// it has no guarantee that the `Handle` was not moved since `add` was - /// called. - pub unsafe fn remove(&mut self) { - if !self.added { return } - - let selector = &mut *self.selector; - let me = self as *mut Handle<'rx, T> as *mut Handle<'static, ()>; - - if self.prev.is_null() { - assert_eq!(selector.head, me); - selector.head = self.next; - } else { - (*self.prev).next = self.next; - } - if self.next.is_null() { - assert_eq!(selector.tail, me); - selector.tail = self.prev; - } else { - (*self.next).prev = self.prev; - } - - self.next = ptr::null_mut(); - self.prev = ptr::null_mut(); - - self.added = false; - } -} - -impl Drop for Select { - fn drop(&mut self) { - unsafe { - assert!((&*self.inner.get()).head.is_null()); - assert!((&*self.inner.get()).tail.is_null()); - } - } -} - -impl Drop for Handle<'_, T> { - fn drop(&mut self) { - unsafe { self.remove() } - } -} - -impl Iterator for Packets { - type Item = *mut Handle<'static, ()>; - - fn next(&mut self) -> Option<*mut Handle<'static, ()>> { - if self.cur.is_null() { - None - } else { - let ret = Some(self.cur); - unsafe { self.cur = (*self.cur).next; } - ret - } - } -} - -impl fmt::Debug for Select { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Select").finish() - } -} - -impl fmt::Debug for Handle<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Handle").finish() - } -} diff --git a/src/libstd/sync/mpsc/select_tests.rs b/src/libstd/sync/mpsc/select_tests.rs deleted file mode 100644 index 18d93462c78d..000000000000 --- a/src/libstd/sync/mpsc/select_tests.rs +++ /dev/null @@ -1,413 +0,0 @@ -#![allow(unused_imports)] - -/// This file exists to hack around https://github.com/rust-lang/rust/issues/47238 - -use crate::thread; -use crate::sync::mpsc::*; - -// Don't use the libstd version so we can pull in the right Select structure -// (std::comm points at the wrong one) -macro_rules! select { - ( - $($name:pat = $rx:ident.$meth:ident() => $code:expr),+ - ) => ({ - let sel = Select::new(); - $( let mut $rx = sel.handle(&$rx); )+ - unsafe { - $( $rx.add(); )+ - } - let ret = sel.wait(); - $( if ret == $rx.id() { let $name = $rx.$meth(); $code } else )+ - { unreachable!() } - }) -} - -#[test] -fn smoke() { - let (tx1, rx1) = channel::(); - let (tx2, rx2) = channel::(); - tx1.send(1).unwrap(); - select! { - foo = rx1.recv() => { assert_eq!(foo.unwrap(), 1); }, - _bar = rx2.recv() => { panic!() } - } - tx2.send(2).unwrap(); - select! { - _foo = rx1.recv() => { panic!() }, - bar = rx2.recv() => { assert_eq!(bar.unwrap(), 2) } - } - drop(tx1); - select! { - foo = rx1.recv() => { assert!(foo.is_err()); }, - _bar = rx2.recv() => { panic!() } - } - drop(tx2); - select! { - bar = rx2.recv() => { assert!(bar.is_err()); } - } -} - -#[test] -fn smoke2() { - let (_tx1, rx1) = channel::(); - let (_tx2, rx2) = channel::(); - let (_tx3, rx3) = channel::(); - let (_tx4, rx4) = channel::(); - let (tx5, rx5) = channel::(); - tx5.send(4).unwrap(); - select! { - _foo = rx1.recv() => { panic!("1") }, - _foo = rx2.recv() => { panic!("2") }, - _foo = rx3.recv() => { panic!("3") }, - _foo = rx4.recv() => { panic!("4") }, - foo = rx5.recv() => { assert_eq!(foo.unwrap(), 4); } - } -} - -#[test] -fn closed() { - let (_tx1, rx1) = channel::(); - let (tx2, rx2) = channel::(); - drop(tx2); - - select! { - _a1 = rx1.recv() => { panic!() }, - a2 = rx2.recv() => { assert!(a2.is_err()); } - } -} - -#[test] -fn unblocks() { - let (tx1, rx1) = channel::(); - let (_tx2, rx2) = channel::(); - let (tx3, rx3) = channel::(); - - let _t = thread::spawn(move|| { - for _ in 0..20 { thread::yield_now(); } - tx1.send(1).unwrap(); - rx3.recv().unwrap(); - for _ in 0..20 { thread::yield_now(); } - }); - - select! { - a = rx1.recv() => { assert_eq!(a.unwrap(), 1); }, - _b = rx2.recv() => { panic!() } - } - tx3.send(1).unwrap(); - select! { - a = rx1.recv() => { assert!(a.is_err()) }, - _b = rx2.recv() => { panic!() } - } -} - -#[test] -fn both_ready() { - let (tx1, rx1) = channel::(); - let (tx2, rx2) = channel::(); - let (tx3, rx3) = channel::<()>(); - - let _t = thread::spawn(move|| { - for _ in 0..20 { thread::yield_now(); } - tx1.send(1).unwrap(); - tx2.send(2).unwrap(); - rx3.recv().unwrap(); - }); - - select! { - a = rx1.recv() => { assert_eq!(a.unwrap(), 1); }, - a = rx2.recv() => { assert_eq!(a.unwrap(), 2); } - } - select! { - a = rx1.recv() => { assert_eq!(a.unwrap(), 1); }, - a = rx2.recv() => { assert_eq!(a.unwrap(), 2); } - } - assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty)); - assert_eq!(rx2.try_recv(), Err(TryRecvError::Empty)); - tx3.send(()).unwrap(); -} - -#[test] -fn stress() { - const AMT: i32 = 10000; - let (tx1, rx1) = channel::(); - let (tx2, rx2) = channel::(); - let (tx3, rx3) = channel::<()>(); - - let _t = thread::spawn(move|| { - for i in 0..AMT { - if i % 2 == 0 { - tx1.send(i).unwrap(); - } else { - tx2.send(i).unwrap(); - } - rx3.recv().unwrap(); - } - }); - - for i in 0..AMT { - select! { - i1 = rx1.recv() => { assert!(i % 2 == 0 && i == i1.unwrap()); }, - i2 = rx2.recv() => { assert!(i % 2 == 1 && i == i2.unwrap()); } - } - tx3.send(()).unwrap(); - } -} - -#[allow(unused_must_use)] -#[test] -fn cloning() { - let (tx1, rx1) = channel::(); - let (_tx2, rx2) = channel::(); - let (tx3, rx3) = channel::<()>(); - - let _t = thread::spawn(move|| { - rx3.recv().unwrap(); - tx1.clone(); - assert_eq!(rx3.try_recv(), Err(TryRecvError::Empty)); - tx1.send(2).unwrap(); - rx3.recv().unwrap(); - }); - - tx3.send(()).unwrap(); - select! { - _i1 = rx1.recv() => {}, - _i2 = rx2.recv() => panic!() - } - tx3.send(()).unwrap(); -} - -#[allow(unused_must_use)] -#[test] -fn cloning2() { - let (tx1, rx1) = channel::(); - let (_tx2, rx2) = channel::(); - let (tx3, rx3) = channel::<()>(); - - let _t = thread::spawn(move|| { - rx3.recv().unwrap(); - tx1.clone(); - assert_eq!(rx3.try_recv(), Err(TryRecvError::Empty)); - tx1.send(2).unwrap(); - rx3.recv().unwrap(); - }); - - tx3.send(()).unwrap(); - select! { - _i1 = rx1.recv() => {}, - _i2 = rx2.recv() => panic!() - } - tx3.send(()).unwrap(); -} - -#[test] -fn cloning3() { - let (tx1, rx1) = channel::<()>(); - let (tx2, rx2) = channel::<()>(); - let (tx3, rx3) = channel::<()>(); - let _t = thread::spawn(move|| { - let s = Select::new(); - let mut h1 = s.handle(&rx1); - let mut h2 = s.handle(&rx2); - unsafe { h2.add(); } - unsafe { h1.add(); } - assert_eq!(s.wait(), h2.id()); - tx3.send(()).unwrap(); - }); - - for _ in 0..1000 { thread::yield_now(); } - drop(tx1.clone()); - tx2.send(()).unwrap(); - rx3.recv().unwrap(); -} - -#[test] -fn preflight1() { - let (tx, rx) = channel(); - tx.send(()).unwrap(); - select! { - _n = rx.recv() => {} - } -} - -#[test] -fn preflight2() { - let (tx, rx) = channel(); - tx.send(()).unwrap(); - tx.send(()).unwrap(); - select! { - _n = rx.recv() => {} - } -} - -#[test] -fn preflight3() { - let (tx, rx) = channel(); - drop(tx.clone()); - tx.send(()).unwrap(); - select! { - _n = rx.recv() => {} - } -} - -#[test] -fn preflight4() { - let (tx, rx) = channel(); - tx.send(()).unwrap(); - let s = Select::new(); - let mut h = s.handle(&rx); - unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id()); -} - -#[test] -fn preflight5() { - let (tx, rx) = channel(); - tx.send(()).unwrap(); - tx.send(()).unwrap(); - let s = Select::new(); - let mut h = s.handle(&rx); - unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id()); -} - -#[test] -fn preflight6() { - let (tx, rx) = channel(); - drop(tx.clone()); - tx.send(()).unwrap(); - let s = Select::new(); - let mut h = s.handle(&rx); - unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id()); -} - -#[test] -fn preflight7() { - let (tx, rx) = channel::<()>(); - drop(tx); - let s = Select::new(); - let mut h = s.handle(&rx); - unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id()); -} - -#[test] -fn preflight8() { - let (tx, rx) = channel(); - tx.send(()).unwrap(); - drop(tx); - rx.recv().unwrap(); - let s = Select::new(); - let mut h = s.handle(&rx); - unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id()); -} - -#[test] -fn preflight9() { - let (tx, rx) = channel(); - drop(tx.clone()); - tx.send(()).unwrap(); - drop(tx); - rx.recv().unwrap(); - let s = Select::new(); - let mut h = s.handle(&rx); - unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id()); -} - -#[test] -fn oneshot_data_waiting() { - let (tx1, rx1) = channel(); - let (tx2, rx2) = channel(); - let _t = thread::spawn(move|| { - select! { - _n = rx1.recv() => {} - } - tx2.send(()).unwrap(); - }); - - for _ in 0..100 { thread::yield_now() } - tx1.send(()).unwrap(); - rx2.recv().unwrap(); -} - -#[test] -fn stream_data_waiting() { - let (tx1, rx1) = channel(); - let (tx2, rx2) = channel(); - tx1.send(()).unwrap(); - tx1.send(()).unwrap(); - rx1.recv().unwrap(); - rx1.recv().unwrap(); - let _t = thread::spawn(move|| { - select! { - _n = rx1.recv() => {} - } - tx2.send(()).unwrap(); - }); - - for _ in 0..100 { thread::yield_now() } - tx1.send(()).unwrap(); - rx2.recv().unwrap(); -} - -#[test] -fn shared_data_waiting() { - let (tx1, rx1) = channel(); - let (tx2, rx2) = channel(); - drop(tx1.clone()); - tx1.send(()).unwrap(); - rx1.recv().unwrap(); - let _t = thread::spawn(move|| { - select! { - _n = rx1.recv() => {} - } - tx2.send(()).unwrap(); - }); - - for _ in 0..100 { thread::yield_now() } - tx1.send(()).unwrap(); - rx2.recv().unwrap(); -} - -#[test] -fn sync1() { - let (tx, rx) = sync_channel::(1); - tx.send(1).unwrap(); - select! { - n = rx.recv() => { assert_eq!(n.unwrap(), 1); } - } -} - -#[test] -fn sync2() { - let (tx, rx) = sync_channel::(0); - let _t = thread::spawn(move|| { - for _ in 0..100 { thread::yield_now() } - tx.send(1).unwrap(); - }); - select! { - n = rx.recv() => { assert_eq!(n.unwrap(), 1); } - } -} - -#[test] -fn sync3() { - let (tx1, rx1) = sync_channel::(0); - let (tx2, rx2): (Sender, Receiver) = channel(); - let _t = thread::spawn(move|| { tx1.send(1).unwrap(); }); - let _t = thread::spawn(move|| { tx2.send(2).unwrap(); }); - select! { - n = rx1.recv() => { - let n = n.unwrap(); - assert_eq!(n, 1); - assert_eq!(rx2.recv().unwrap(), 2); - }, - n = rx2.recv() => { - let n = n.unwrap(); - assert_eq!(n, 2); - assert_eq!(rx1.recv().unwrap(), 1); - } - } -} diff --git a/src/libstd/sync/mpsc/shared.rs b/src/libstd/sync/mpsc/shared.rs index cc70a6203659..dbcdcdac9326 100644 --- a/src/libstd/sync/mpsc/shared.rs +++ b/src/libstd/sync/mpsc/shared.rs @@ -9,6 +9,7 @@ /// channels are quite similar, and this is no coincidence! pub use self::Failure::*; +use self::StartResult::*; use core::cmp; use core::intrinsics::abort; @@ -19,8 +20,6 @@ use crate::ptr; use crate::sync::atomic::{AtomicUsize, AtomicIsize, AtomicBool, Ordering}; use crate::sync::mpsc::blocking::{self, SignalToken}; use crate::sync::mpsc::mpsc_queue as mpsc; -use crate::sync::mpsc::select::StartResult::*; -use crate::sync::mpsc::select::StartResult; use crate::sync::{Mutex, MutexGuard}; use crate::thread; use crate::time::Instant; @@ -57,6 +56,12 @@ pub enum Failure { Disconnected, } +#[derive(PartialEq, Eq)] +enum StartResult { + Installed, + Abort, +} + impl Packet { // Creation of a packet *must* be followed by a call to postinit_lock // and later by inherit_blocker @@ -394,16 +399,6 @@ impl Packet { // select implementation //////////////////////////////////////////////////////////////////////////// - // Helper function for select, tests whether this port can receive without - // blocking (obviously not an atomic decision). - // - // This is different than the stream version because there's no need to peek - // at the queue, we can just look at the local count. - pub fn can_recv(&self) -> bool { - let cnt = self.cnt.load(Ordering::SeqCst); - cnt == DISCONNECTED || cnt - unsafe { *self.steals.get() } > 0 - } - // increment the count on the channel (used for selection) fn bump(&self, amt: isize) -> isize { match self.cnt.fetch_add(amt, Ordering::SeqCst) { @@ -415,22 +410,6 @@ impl Packet { } } - // Inserts the signal token for selection on this port, returning true if - // blocking should proceed. - // - // The code here is the same as in stream.rs, except that it doesn't need to - // peek at the channel to see if an upgrade is pending. - pub fn start_selection(&self, token: SignalToken) -> StartResult { - match self.decrement(token) { - Installed => Installed, - Abort => { - let prev = self.bump(1); - assert!(prev == DISCONNECTED || prev >= 0); - Abort - } - } - } - // Cancels a previous thread waiting on this port, returning whether there's // data on the port. // diff --git a/src/libstd/sync/mpsc/stream.rs b/src/libstd/sync/mpsc/stream.rs index 7ae6f68b5145..408772827617 100644 --- a/src/libstd/sync/mpsc/stream.rs +++ b/src/libstd/sync/mpsc/stream.rs @@ -9,7 +9,6 @@ pub use self::Failure::*; pub use self::UpgradeResult::*; -pub use self::SelectionResult::*; use self::Message::*; use core::cmp; @@ -60,12 +59,6 @@ pub enum UpgradeResult { UpWoke(SignalToken), } -pub enum SelectionResult { - SelSuccess, - SelCanceled, - SelUpgraded(SignalToken, Receiver), -} - // Any message could contain an "upgrade request" to a new shared port, so the // internal queue it's a queue of T, but rather Message enum Message { @@ -338,27 +331,6 @@ impl Packet { // select implementation //////////////////////////////////////////////////////////////////////////// - // Tests to see whether this port can receive without blocking. If Ok is - // returned, then that's the answer. If Err is returned, then the returned - // port needs to be queried instead (an upgrade happened) - pub fn can_recv(&self) -> Result> { - // We peek at the queue to see if there's anything on it, and we use - // this return value to determine if we should pop from the queue and - // upgrade this channel immediately. If it looks like we've got an - // upgrade pending, then go through the whole recv rigamarole to update - // the internal state. - match self.queue.peek() { - Some(&mut GoUp(..)) => { - match self.recv(None) { - Err(Upgraded(port)) => Err(port), - _ => unreachable!(), - } - } - Some(..) => Ok(true), - None => Ok(false) - } - } - // increment the count on the channel (used for selection) fn bump(&self, amt: isize) -> isize { match self.queue.producer_addition().cnt.fetch_add(amt, Ordering::SeqCst) { @@ -370,31 +342,6 @@ impl Packet { } } - // Attempts to start selecting on this port. Like a oneshot, this can fail - // immediately because of an upgrade. - pub fn start_selection(&self, token: SignalToken) -> SelectionResult { - match self.decrement(token) { - Ok(()) => SelSuccess, - Err(token) => { - let ret = match self.queue.peek() { - Some(&mut GoUp(..)) => { - match self.queue.pop() { - Some(GoUp(port)) => SelUpgraded(token, port), - _ => unreachable!(), - } - } - Some(..) => SelCanceled, - None => SelCanceled, - }; - // Undo our decrement above, and we should be guaranteed that the - // previous value is positive because we're not going to sleep - let prev = self.bump(1); - assert!(prev == DISCONNECTED || prev >= 0); - ret - } - } - } - // Removes a previous thread from being blocked in this port pub fn abort_selection(&self, was_upgrade: bool) -> Result> { diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs index b2d9f4c6491e..3c4f8e077c92 100644 --- a/src/libstd/sync/mpsc/sync.rs +++ b/src/libstd/sync/mpsc/sync.rs @@ -33,7 +33,6 @@ use core::ptr; use crate::sync::atomic::{Ordering, AtomicUsize}; use crate::sync::mpsc::blocking::{self, WaitToken, SignalToken}; -use crate::sync::mpsc::select::StartResult::{self, Installed, Abort}; use crate::sync::{Mutex, MutexGuard}; use crate::time::Instant; @@ -406,42 +405,6 @@ impl Packet { while let Some(token) = queue.dequeue() { token.signal(); } waiter.map(|t| t.signal()); } - - //////////////////////////////////////////////////////////////////////////// - // select implementation - //////////////////////////////////////////////////////////////////////////// - - // If Ok, the value is whether this port has data, if Err, then the upgraded - // port needs to be checked instead of this one. - pub fn can_recv(&self) -> bool { - let guard = self.lock.lock().unwrap(); - guard.disconnected || guard.buf.size() > 0 - } - - // Attempts to start selection on this port. This can either succeed or fail - // because there is data waiting. - pub fn start_selection(&self, token: SignalToken) -> StartResult { - let mut guard = self.lock.lock().unwrap(); - if guard.disconnected || guard.buf.size() > 0 { - Abort - } else { - match mem::replace(&mut guard.blocker, BlockedReceiver(token)) { - NoneBlocked => {} - BlockedSender(..) => unreachable!(), - BlockedReceiver(..) => unreachable!(), - } - Installed - } - } - - // Remove a previous selecting thread from this port. This ensures that the - // blocked thread will no longer be visible to any other threads. - // - // The return value indicates whether there's data on this port. - pub fn abort_selection(&self) -> bool { - let mut guard = self.lock.lock().unwrap(); - abort_selection(&mut guard) - } } impl Drop for Packet { diff --git a/src/test/run-pass/issues/issue-13494.rs b/src/test/run-pass/issues/issue-13494.rs deleted file mode 100644 index 12be97702a9f..000000000000 --- a/src/test/run-pass/issues/issue-13494.rs +++ /dev/null @@ -1,35 +0,0 @@ -// run-pass -#![allow(unused_must_use)] -// ignore-emscripten no threads support - -// This test may not always fail, but it can be flaky if the race it used to -// expose is still present. - -#![feature(mpsc_select)] -#![allow(deprecated)] - -use std::sync::mpsc::{channel, Sender, Receiver}; -use std::thread; - -fn helper(rx: Receiver>) { - for tx in rx.iter() { - let _ = tx.send(()); - } -} - -fn main() { - let (tx, rx) = channel(); - let t = thread::spawn(move|| { helper(rx) }); - let (snd, rcv) = channel::(); - for _ in 1..100000 { - snd.send(1).unwrap(); - let (tx2, rx2) = channel(); - tx.send(tx2).unwrap(); - select! { - _ = rx2.recv() => (), - _ = rcv.recv() => () - } - } - drop(tx); - t.join(); -} diff --git a/src/test/run-pass/macros/macro-comma-support.rs b/src/test/run-pass/macros/macro-comma-support.rs index 904f2e2c7fd7..12a612c153ad 100644 --- a/src/test/run-pass/macros/macro-comma-support.rs +++ b/src/test/run-pass/macros/macro-comma-support.rs @@ -233,8 +233,6 @@ fn println() { println!("hello {}", "world",); } -// select! is too troublesome and unlikely to be stabilized - // stringify! is N/A #[cfg(std)] From 65b731908abee2bb8b0af50d18567eb4abaa4ac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 17 May 2019 12:18:56 -0700 Subject: [PATCH 0124/3207] Explain that ? converts the error type using From --- src/librustc/traits/error_reporting.rs | 9 ++++++--- src/test/ui/issues/issue-32709.stderr | 1 + src/test/ui/try-block/try-block-bad-type.stderr | 1 + src/test/ui/try-on-option.stderr | 1 + 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index df2688397102..9019c4a0575d 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -643,13 +643,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .map(|s| &s == "?") .unwrap_or(false); let is_from = format!("{}", trait_ref).starts_with("std::convert::From<"); - let message = if is_try && is_from { - Some(format!( + let (message, note) = if is_try && is_from { + (Some(format!( "`?` couldn't convert the error to `{}`", trait_ref.self_ty(), + )), Some( + "the question mark operation (`?`) implicitly performs a \ + conversion on the error value using the `From` trait".to_owned() )) } else { - message + (message, note) }; let mut err = struct_span_err!( diff --git a/src/test/ui/issues/issue-32709.stderr b/src/test/ui/issues/issue-32709.stderr index 84cca5b20af4..04b8c3aa3539 100644 --- a/src/test/ui/issues/issue-32709.stderr +++ b/src/test/ui/issues/issue-32709.stderr @@ -4,6 +4,7 @@ error[E0277]: `?` couldn't convert the error to `()` LL | Err(5)?; | ^ the trait `std::convert::From<{integer}>` is not implemented for `()` | + = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = note: required by `std::convert::From::from` error: aborting due to previous error diff --git a/src/test/ui/try-block/try-block-bad-type.stderr b/src/test/ui/try-block/try-block-bad-type.stderr index 7c7366df1dc3..e1c2c6b675e9 100644 --- a/src/test/ui/try-block/try-block-bad-type.stderr +++ b/src/test/ui/try-block/try-block-bad-type.stderr @@ -4,6 +4,7 @@ error[E0277]: `?` couldn't convert the error to `i32` LL | Err("")?; | ^ the trait `std::convert::From<&str>` is not implemented for `i32` | + = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = help: the following implementations were found: > > diff --git a/src/test/ui/try-on-option.stderr b/src/test/ui/try-on-option.stderr index 4465fbe14b75..db5046f8c151 100644 --- a/src/test/ui/try-on-option.stderr +++ b/src/test/ui/try-on-option.stderr @@ -4,6 +4,7 @@ error[E0277]: `?` couldn't convert the error to `()` LL | x?; | ^ the trait `std::convert::From` is not implemented for `()` | + = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = note: required by `std::convert::From::from` error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`) From 90dd35918de13994cf06058de33860dfbd8ab51f Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 17 May 2019 19:56:35 -0700 Subject: [PATCH 0125/3207] Use iter() for iterating arrays by slice These `into_iter()` calls will change from iterating references to values if we ever get `IntoIterator` for arrays, which may break the code using that iterator. Calling `iter()` is future proof. --- src/liballoc/tests/btree/set.rs | 4 ++-- src/libcore/iter/traits/iterator.rs | 32 ++++++++++++++--------------- src/librustdoc/config.rs | 2 +- src/librustdoc/html/render.rs | 2 +- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/liballoc/tests/btree/set.rs b/src/liballoc/tests/btree/set.rs index d52814118b3c..989beb3b1bfd 100644 --- a/src/liballoc/tests/btree/set.rs +++ b/src/liballoc/tests/btree/set.rs @@ -143,8 +143,8 @@ fn test_union() { #[test] // Only tests the simple function definition with respect to intersection fn test_is_disjoint() { - let one = [1].into_iter().collect::>(); - let two = [2].into_iter().collect::>(); + let one = [1].iter().collect::>(); + let two = [2].iter().collect::>(); assert!(one.is_disjoint(&two)); } diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index 403f33581053..38c7c9bc4d08 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -356,7 +356,7 @@ pub trait Iterator { /// /// ``` /// let a = [0, 1, 2, 3, 4, 5]; - /// let mut iter = a.into_iter().step_by(2); + /// let mut iter = a.iter().step_by(2); /// /// assert_eq!(iter.next(), Some(&0)); /// assert_eq!(iter.next(), Some(&2)); @@ -531,7 +531,7 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3]; /// - /// let mut iter = a.into_iter().map(|x| 2 * x); + /// let mut iter = a.iter().map(|x| 2 * x); /// /// assert_eq!(iter.next(), Some(2)); /// assert_eq!(iter.next(), Some(4)); @@ -620,7 +620,7 @@ pub trait Iterator { /// ``` /// let a = [0i32, 1, 2]; /// - /// let mut iter = a.into_iter().filter(|x| x.is_positive()); + /// let mut iter = a.iter().filter(|x| x.is_positive()); /// /// assert_eq!(iter.next(), Some(&1)); /// assert_eq!(iter.next(), Some(&2)); @@ -634,7 +634,7 @@ pub trait Iterator { /// ``` /// let a = [0, 1, 2]; /// - /// let mut iter = a.into_iter().filter(|x| **x > 1); // need two *s! + /// let mut iter = a.iter().filter(|x| **x > 1); // need two *s! /// /// assert_eq!(iter.next(), Some(&2)); /// assert_eq!(iter.next(), None); @@ -646,7 +646,7 @@ pub trait Iterator { /// ``` /// let a = [0, 1, 2]; /// - /// let mut iter = a.into_iter().filter(|&x| *x > 1); // both & and * + /// let mut iter = a.iter().filter(|&x| *x > 1); // both & and * /// /// assert_eq!(iter.next(), Some(&2)); /// assert_eq!(iter.next(), None); @@ -657,7 +657,7 @@ pub trait Iterator { /// ``` /// let a = [0, 1, 2]; /// - /// let mut iter = a.into_iter().filter(|&&x| x > 1); // two &s + /// let mut iter = a.iter().filter(|&&x| x > 1); // two &s /// /// assert_eq!(iter.next(), Some(&2)); /// assert_eq!(iter.next(), None); @@ -837,7 +837,7 @@ pub trait Iterator { /// ``` /// let a = [-1i32, 0, 1]; /// - /// let mut iter = a.into_iter().skip_while(|x| x.is_negative()); + /// let mut iter = a.iter().skip_while(|x| x.is_negative()); /// /// assert_eq!(iter.next(), Some(&0)); /// assert_eq!(iter.next(), Some(&1)); @@ -851,7 +851,7 @@ pub trait Iterator { /// ``` /// let a = [-1, 0, 1]; /// - /// let mut iter = a.into_iter().skip_while(|x| **x < 0); // need two *s! + /// let mut iter = a.iter().skip_while(|x| **x < 0); // need two *s! /// /// assert_eq!(iter.next(), Some(&0)); /// assert_eq!(iter.next(), Some(&1)); @@ -863,7 +863,7 @@ pub trait Iterator { /// ``` /// let a = [-1, 0, 1, -2]; /// - /// let mut iter = a.into_iter().skip_while(|x| **x < 0); + /// let mut iter = a.iter().skip_while(|x| **x < 0); /// /// assert_eq!(iter.next(), Some(&0)); /// assert_eq!(iter.next(), Some(&1)); @@ -898,7 +898,7 @@ pub trait Iterator { /// ``` /// let a = [-1i32, 0, 1]; /// - /// let mut iter = a.into_iter().take_while(|x| x.is_negative()); + /// let mut iter = a.iter().take_while(|x| x.is_negative()); /// /// assert_eq!(iter.next(), Some(&-1)); /// assert_eq!(iter.next(), None); @@ -911,7 +911,7 @@ pub trait Iterator { /// ``` /// let a = [-1, 0, 1]; /// - /// let mut iter = a.into_iter().take_while(|x| **x < 0); // need two *s! + /// let mut iter = a.iter().take_while(|x| **x < 0); // need two *s! /// /// assert_eq!(iter.next(), Some(&-1)); /// assert_eq!(iter.next(), None); @@ -922,7 +922,7 @@ pub trait Iterator { /// ``` /// let a = [-1, 0, 1, -2]; /// - /// let mut iter = a.into_iter().take_while(|x| **x < 0); + /// let mut iter = a.iter().take_while(|x| **x < 0); /// /// assert_eq!(iter.next(), Some(&-1)); /// @@ -937,7 +937,7 @@ pub trait Iterator { /// /// ``` /// let a = [1, 2, 3, 4]; - /// let mut iter = a.into_iter(); + /// let mut iter = a.iter(); /// /// let result: Vec = iter.by_ref() /// .take_while(|n| **n != 3) @@ -1321,7 +1321,7 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3]; /// - /// let iter = a.into_iter(); + /// let iter = a.iter(); /// /// let sum: i32 = iter.take(5).fold(0, |acc, i| acc + i ); /// @@ -1334,7 +1334,7 @@ pub trait Iterator { /// // let's try that again /// let a = [1, 2, 3]; /// - /// let mut iter = a.into_iter(); + /// let mut iter = a.iter(); /// /// // instead, we add in a .by_ref() /// let sum: i32 = iter.by_ref().take(2).fold(0, |acc, i| acc + i ); @@ -1479,7 +1479,7 @@ pub trait Iterator { /// let a = [1, 2, 3]; /// /// let (even, odd): (Vec, Vec) = a - /// .into_iter() + /// .iter() /// .partition(|&n| n % 2 == 0); /// /// assert_eq!(even, vec![2]); diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 72421c9decc6..4fae7e080b14 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -538,7 +538,7 @@ fn check_deprecated_options(matches: &getopts::Matches, diag: &errors::Handler) "passes", ]; - for flag in deprecated_flags.into_iter() { + for flag in deprecated_flags.iter() { if matches.opt_present(flag) { let mut err = diag.struct_warn(&format!("the '{}' flag is considered deprecated", flag)); diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 0207fcda9e88..964789224ded 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -506,7 +506,7 @@ pub fn initial_ids() -> Vec { "methods", "deref-methods", "implementations", - ].into_iter().map(|id| (String::from(*id))).collect() + ].iter().map(|id| (String::from(*id))).collect() } /// Generates the documentation for `crate` into the directory `dst` From 70f78b3f8cd1a1cc7324bbae6b559315e423b2af Mon Sep 17 00:00:00 2001 From: chandde Date: Fri, 17 May 2019 20:45:25 -0700 Subject: [PATCH 0126/3207] optimize the arm64 OR arm32 check --- src/libtest/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 765ee12a1d67..b64973573c01 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -42,7 +42,7 @@ use term; // libtest won't be fully functional on these platforms. // // See also: https://github.com/rust-lang/rust/issues/54190#issuecomment-422904437 -#[cfg(not(any(all(windows, target_arch = "aarch64"), all(windows, target_arch = "arm"))))] +#[cfg(not(all(windows, any(target_arch = "aarch64", target_arch = "arm"))))] extern crate panic_unwind; pub use self::ColorConfig::*; From 759921e2a0ec87211a0a54ab628f5ba5fbe6e578 Mon Sep 17 00:00:00 2001 From: chandde Date: Sat, 18 May 2019 00:49:54 -0700 Subject: [PATCH 0127/3207] fix line length --- src/libtest/lib.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index b64973573c01..6c57581a6c25 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -37,9 +37,10 @@ extern crate libc; use term; // FIXME(#54291): rustc and/or LLVM don't yet support building with panic-unwind -// on aarch64-pc-windows-msvc, or thumbv7a-pc-windows-msvc, so we don't link libtest against -// libunwind (for the time being), even though it means that -// libtest won't be fully functional on these platforms. +// on aarch64-pc-windows-msvc, or thumbv7a-pc-windows-msvc +// so we don't link libtest against libunwind (for the time being) +// even though it means that libtest won't be fully functional on +// these platforms. // // See also: https://github.com/rust-lang/rust/issues/54190#issuecomment-422904437 #[cfg(not(all(windows, any(target_arch = "aarch64", target_arch = "arm"))))] From b5d4bd2a07218a6cd61bace73d7910a3f1a117c4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 16 May 2019 18:31:53 +0200 Subject: [PATCH 0128/3207] Fix lints handling in rustdoc --- src/librustc/lint/mod.rs | 3 ++ src/librustdoc/clean/mod.rs | 7 ++++ .../passes/collect_intra_doc_links.rs | 34 +++++++++++----- src/librustdoc/passes/mod.rs | 19 +++++---- .../lint-missing-doc-code-example.rs | 39 +++++++++++++++++++ .../lint-missing-doc-code-example.stderr | 0 6 files changed, 85 insertions(+), 17 deletions(-) create mode 100644 src/test/rustdoc-ui/lint-missing-doc-code-example.rs create mode 100644 src/test/rustdoc-ui/lint-missing-doc-code-example.stderr diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 68b65f9b4a1c..9c4683e09463 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -778,6 +778,9 @@ fn lint_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum) let push = builder.levels.push(&krate.attrs); builder.levels.register_id(hir::CRATE_HIR_ID); + for macro_def in &krate.exported_macros { + builder.levels.register_id(macro_def.hir_id); + } intravisit::walk_crate(&mut builder, krate); builder.levels.pop(push); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e9ccc61280b1..7fe3aecca10c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3405,6 +3405,7 @@ pub struct Span { pub locol: usize, pub hiline: usize, pub hicol: usize, + pub original: syntax_pos::Span, } impl Span { @@ -3413,8 +3414,13 @@ impl Span { filename: FileName::Anon(0), loline: 0, locol: 0, hiline: 0, hicol: 0, + original: syntax_pos::DUMMY_SP, } } + + pub fn span(&self) -> syntax_pos::Span { + self.original + } } impl Clean for syntax_pos::Span { @@ -3433,6 +3439,7 @@ impl Clean for syntax_pos::Span { locol: lo.col.to_usize(), hiline: hi.line, hicol: hi.col.to_usize(), + original: *self, } } } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 9e108e605c8b..2c382a1c1759 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -321,7 +321,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { if let Ok(res) = self.resolve(path_str, ns, ¤t_item, parent_node) { res } else { - resolution_failure(cx, &item.attrs, path_str, &dox, link_range); + resolution_failure(cx, &item, path_str, &dox, link_range); // This could just be a normal link or a broken link // we could potentially check if something is // "intra-doc-link-like" and warn in that case. @@ -332,7 +332,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { if let Ok(res) = self.resolve(path_str, ns, ¤t_item, parent_node) { res } else { - resolution_failure(cx, &item.attrs, path_str, &dox, link_range); + resolution_failure(cx, &item, path_str, &dox, link_range); // This could just be a normal link. continue; } @@ -357,7 +357,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { }; if candidates.is_empty() { - resolution_failure(cx, &item.attrs, path_str, &dox, link_range); + resolution_failure(cx, &item, path_str, &dox, link_range); // this could just be a normal link continue; } @@ -368,7 +368,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { } else { ambiguity_error( cx, - &item.attrs, + &item, path_str, &dox, link_range, @@ -381,7 +381,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { if let Some(res) = macro_resolve(cx, path_str) { (res, None) } else { - resolution_failure(cx, &item.attrs, path_str, &dox, link_range); + resolution_failure(cx, &item, path_str, &dox, link_range); continue } } @@ -452,16 +452,24 @@ fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option { /// line containing the failure as a note as well. fn resolution_failure( cx: &DocContext<'_>, - attrs: &Attributes, + item: &Item, path_str: &str, dox: &str, link_range: Option>, ) { + let hir_id = match cx.as_local_hir_id(item.def_id) { + Some(hir_id) => hir_id, + None => { + // If non-local, no need to check anything. + return; + } + }; + let attrs = &item.attrs; let sp = span_of_attrs(attrs); let mut diag = cx.tcx.struct_span_lint_hir( lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE, - hir::CRATE_HIR_ID, + hir_id, sp, &format!("`[{}]` cannot be resolved, ignoring it...", path_str), ); @@ -495,12 +503,20 @@ fn resolution_failure( fn ambiguity_error( cx: &DocContext<'_>, - attrs: &Attributes, + item: &Item, path_str: &str, dox: &str, link_range: Option>, candidates: PerNS>, ) { + let hir_id = match cx.as_local_hir_id(item.def_id) { + Some(hir_id) => hir_id, + None => { + // If non-local, no need to check anything. + return; + } + }; + let attrs = &item.attrs; let sp = span_of_attrs(attrs); let mut msg = format!("`{}` is ", path_str); @@ -532,7 +548,7 @@ fn ambiguity_error( let mut diag = cx.tcx.struct_span_lint_hir( lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE, - hir::CRATE_HIR_ID, + hir_id, sp, &msg, ); diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 99aca0634710..d9af33ac5b62 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -1,7 +1,6 @@ //! Contains information about "passes", used to modify crate information during the documentation //! process. -use rustc::hir; use rustc::hir::def_id::DefId; use rustc::lint as lint; use rustc::middle::privacy::AccessLevels; @@ -314,10 +313,13 @@ pub fn look_for_tests<'tcx>( item: &Item, check_missing_code: bool, ) { - if cx.as_local_hir_id(item.def_id).is_none() { - // If non-local, no need to check anything. - return; - } + let hir_id = match cx.as_local_hir_id(item.def_id) { + Some(hir_id) => hir_id, + None => { + // If non-local, no need to check anything. + return; + } + }; struct Tests { found_tests: usize, @@ -336,10 +338,11 @@ pub fn look_for_tests<'tcx>( find_testable_code(&dox, &mut tests, ErrorCodes::No); if check_missing_code == true && tests.found_tests == 0 { + let sp = span_of_attrs(&item.attrs).substitute_dummy(item.source.span()); let mut diag = cx.tcx.struct_span_lint_hir( lint::builtin::MISSING_DOC_CODE_EXAMPLES, - hir::CRATE_HIR_ID, - span_of_attrs(&item.attrs), + hir_id, + sp, "Missing code example in this documentation"); diag.emit(); } else if check_missing_code == false && @@ -347,7 +350,7 @@ pub fn look_for_tests<'tcx>( !cx.renderinfo.borrow().access_levels.is_doc_reachable(item.def_id) { let mut diag = cx.tcx.struct_span_lint_hir( lint::builtin::PRIVATE_DOC_TESTS, - hir::CRATE_HIR_ID, + hir_id, span_of_attrs(&item.attrs), "Documentation test in private item"); diag.emit(); diff --git a/src/test/rustdoc-ui/lint-missing-doc-code-example.rs b/src/test/rustdoc-ui/lint-missing-doc-code-example.rs new file mode 100644 index 000000000000..3bb1a2b7bef0 --- /dev/null +++ b/src/test/rustdoc-ui/lint-missing-doc-code-example.rs @@ -0,0 +1,39 @@ +#![deny(missing_docs)] +#![deny(missing_doc_code_examples)] + +//! crate level doc +//! ``` +//! println!("hello"): +//! ``` + + +/// doc +/// +/// ``` +/// println!("hello"); +/// ``` +fn test() { +} + +#[allow(missing_docs)] +mod module1 { +} + +#[allow(missing_doc_code_examples)] +/// doc +mod module2 { + + /// doc + pub fn test() {} +} + +/// doc +/// +/// ``` +/// println!("hello"); +/// ``` +pub mod module3 { + + /// doc + pub fn test() {} +} diff --git a/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr b/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr new file mode 100644 index 000000000000..e69de29bb2d1 From c78af2bc60fe8611c063c13bea1295c784403234 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 17 May 2019 13:39:20 +0200 Subject: [PATCH 0129/3207] Update rustdoc-ui tests --- src/test/rustdoc-ui/doc-without-codeblock.rs | 4 +--- .../rustdoc-ui/doc-without-codeblock.stderr | 18 ++++++++++++---- .../lint-missing-doc-code-example.rs | 3 ++- .../lint-missing-doc-code-example.stderr | 21 +++++++++++++++++++ 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/test/rustdoc-ui/doc-without-codeblock.rs b/src/test/rustdoc-ui/doc-without-codeblock.rs index aa3f539ba32a..4b2a91e9c812 100644 --- a/src/test/rustdoc-ui/doc-without-codeblock.rs +++ b/src/test/rustdoc-ui/doc-without-codeblock.rs @@ -1,6 +1,4 @@ -//~ ERROR Missing code example in this documentation - -#![deny(missing_doc_code_examples)] +#![deny(missing_doc_code_examples)] //~ ERROR Missing code example in this documentation /// Some docs. //~^ ERROR Missing code example in this documentation diff --git a/src/test/rustdoc-ui/doc-without-codeblock.stderr b/src/test/rustdoc-ui/doc-without-codeblock.stderr index 208bdedf24dd..23c07c4d32d6 100644 --- a/src/test/rustdoc-ui/doc-without-codeblock.stderr +++ b/src/test/rustdoc-ui/doc-without-codeblock.stderr @@ -1,25 +1,35 @@ error: Missing code example in this documentation + --> $DIR/doc-without-codeblock.rs:1:1 + | +LL | / #![deny(missing_doc_code_examples)] +LL | | +LL | | /// Some docs. +LL | | +... | +LL | | pub fn bar() {} +LL | | } + | |_^ | note: lint level defined here - --> $DIR/doc-without-codeblock.rs:3:9 + --> $DIR/doc-without-codeblock.rs:1:9 | LL | #![deny(missing_doc_code_examples)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: Missing code example in this documentation - --> $DIR/doc-without-codeblock.rs:5:1 + --> $DIR/doc-without-codeblock.rs:3:1 | LL | /// Some docs. | ^^^^^^^^^^^^^^ error: Missing code example in this documentation - --> $DIR/doc-without-codeblock.rs:9:1 + --> $DIR/doc-without-codeblock.rs:7:1 | LL | /// And then, the princess died. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Missing code example in this documentation - --> $DIR/doc-without-codeblock.rs:12:5 + --> $DIR/doc-without-codeblock.rs:10:5 | LL | /// Or maybe not because she saved herself! | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/rustdoc-ui/lint-missing-doc-code-example.rs b/src/test/rustdoc-ui/lint-missing-doc-code-example.rs index 3bb1a2b7bef0..ffe0ddcd8c9b 100644 --- a/src/test/rustdoc-ui/lint-missing-doc-code-example.rs +++ b/src/test/rustdoc-ui/lint-missing-doc-code-example.rs @@ -16,7 +16,7 @@ fn test() { } #[allow(missing_docs)] -mod module1 { +mod module1 { //~ ERROR } #[allow(missing_doc_code_examples)] @@ -35,5 +35,6 @@ mod module2 { pub mod module3 { /// doc + //~^ ERROR pub fn test() {} } diff --git a/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr b/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr index e69de29bb2d1..97a52a13e3f6 100644 --- a/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr +++ b/src/test/rustdoc-ui/lint-missing-doc-code-example.stderr @@ -0,0 +1,21 @@ +error: Missing code example in this documentation + --> $DIR/lint-missing-doc-code-example.rs:19:1 + | +LL | / mod module1 { +LL | | } + | |_^ + | +note: lint level defined here + --> $DIR/lint-missing-doc-code-example.rs:2:9 + | +LL | #![deny(missing_doc_code_examples)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Missing code example in this documentation + --> $DIR/lint-missing-doc-code-example.rs:37:3 + | +LL | /// doc + | ^^^^^^^ + +error: aborting due to 2 previous errors + From 606377740b6022664299b47c8dd8d3e65017021d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 18 May 2019 12:42:13 +0200 Subject: [PATCH 0130/3207] Fix tests not running locally --- src/bootstrap/test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 7826ac947180..be0af8be7b27 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -683,7 +683,7 @@ impl Step for RustdocUi { target: self.target, mode: "ui", suite: "rustdoc-ui", - path: None, + path: Some("src/test/rustdoc-ui"), compare_mode: None, }) } From b18de520800e2985e3313ca9ac21d5099d869428 Mon Sep 17 00:00:00 2001 From: Fabian Drinck Date: Sat, 18 May 2019 13:19:33 +0200 Subject: [PATCH 0131/3207] Declare DefIndex with the newtype_index macro --- src/librustc/hir/def_id.rs | 46 +++++-------------- src/librustc/hir/map/collector.rs | 2 +- src/librustc/hir/map/definitions.rs | 18 ++++---- src/librustc/hir/map/mod.rs | 4 +- .../infer/lexical_region_resolve/graphviz.rs | 4 +- src/librustc/traits/specialize/mod.rs | 2 +- src/librustc_driver/pretty.rs | 2 +- src/librustc_metadata/decoder.rs | 2 +- src/librustc_metadata/encoder.rs | 2 +- src/librustc_metadata/index.rs | 4 +- src/librustc_mir/util/graphviz.rs | 2 +- src/librustc_resolve/macros.rs | 2 +- src/librustc_save_analysis/lib.rs | 2 +- src/librustdoc/core.rs | 2 +- 14 files changed, 36 insertions(+), 58 deletions(-) diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index b268a1a494d1..0c4f5fb3fc16 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -96,34 +96,20 @@ impl fmt::Display for CrateNum { impl serialize::UseSpecializedEncodable for CrateNum {} impl serialize::UseSpecializedDecodable for CrateNum {} -/// A DefIndex is an index into the hir-map for a crate, identifying a -/// particular definition. It should really be considered an interned -/// shorthand for a particular DefPath. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] -pub struct DefIndex(u32); +newtype_index! { + /// A DefIndex is an index into the hir-map for a crate, identifying a + /// particular definition. It should really be considered an interned + /// shorthand for a particular DefPath. + pub struct DefIndex { + DEBUG_FORMAT = "DefIndex({})", -/// The crate root is always assigned index 0 by the AST Map code, -/// thanks to `NodeCollector::new`. -pub const CRATE_DEF_INDEX: DefIndex = DefIndex(0); - -impl fmt::Debug for DefIndex { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "DefIndex({})", self.as_array_index()) + /// The crate root is always assigned index 0 by the AST Map code, + /// thanks to `NodeCollector::new`. + const CRATE_DEF_INDEX = 0, } } impl DefIndex { - /// Converts this DefIndex into a zero-based array index. - #[inline] - pub fn as_array_index(&self) -> usize { - self.0 as usize - } - - #[inline] - pub fn from_array_index(i: usize) -> DefIndex { - DefIndex(i as u32) - } - // Proc macros from a proc-macro crate have a kind of virtual DefIndex. This // function maps the index of the macro within the crate (which is also the // index of the macro in the CrateMetadata::proc_macros array) to the @@ -132,7 +118,7 @@ impl DefIndex { // DefIndex for proc macros start from FIRST_FREE_DEF_INDEX, // because the first FIRST_FREE_DEF_INDEX indexes are reserved // for internal use. - let def_index = DefIndex::from_array_index( + let def_index = DefIndex::from( proc_macro_index.checked_add(FIRST_FREE_DEF_INDEX) .expect("integer overflow adding `proc_macro_index`")); assert!(def_index != CRATE_DEF_INDEX); @@ -141,19 +127,11 @@ impl DefIndex { // This function is the reverse of from_proc_macro_index() above. pub fn to_proc_macro_index(self: DefIndex) -> usize { - self.as_array_index().checked_sub(FIRST_FREE_DEF_INDEX) + self.index().checked_sub(FIRST_FREE_DEF_INDEX) .unwrap_or_else(|| { bug!("using local index {:?} as proc-macro index", self) }) } - - pub fn from_raw_u32(x: u32) -> DefIndex { - DefIndex(x) - } - - pub fn as_raw_u32(&self) -> u32 { - self.0 - } } impl serialize::UseSpecializedEncodable for DefIndex {} @@ -169,7 +147,7 @@ pub struct DefId { impl fmt::Debug for DefId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "DefId({}:{}", self.krate, self.index.as_array_index())?; + write!(f, "DefId({}:{}", self.krate, self.index.index())?; ty::tls::with_opt(|opt_tcx| { if let Some(tcx) = opt_tcx { diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index a1cf338bf12e..eeba628b3bf2 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -226,7 +226,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { fn insert_entry(&mut self, id: HirId, entry: Entry<'hir>) { debug!("hir_map: {:?} => {:?}", id, entry); - let local_map = &mut self.map[id.owner.as_array_index()]; + let local_map = &mut self.map[id.owner.index()]; let i = id.local_id.as_u32() as usize; if local_map.is_none() { *local_map = Some(IndexVec::with_capacity(i + 1)); diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 9cb85c4db475..1cc9a2c0e8a1 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -38,7 +38,7 @@ impl DefPathTable { def_path_hash: DefPathHash) -> DefIndex { let index = { - let index = DefIndex::from_array_index(self.index_to_key.len()); + let index = DefIndex::from(self.index_to_key.len()); debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index); self.index_to_key.push(key); index @@ -49,17 +49,17 @@ impl DefPathTable { } pub fn next_id(&self) -> DefIndex { - DefIndex::from_array_index(self.index_to_key.len()) + DefIndex::from(self.index_to_key.len()) } #[inline(always)] pub fn def_key(&self, index: DefIndex) -> DefKey { - self.index_to_key[index.as_array_index()].clone() + self.index_to_key[index.index()].clone() } #[inline(always)] pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash { - let ret = self.def_path_hashes[index.as_array_index()]; + let ret = self.def_path_hashes[index.index()]; debug!("def_path_hash({:?}) = {:?}", index, ret); return ret } @@ -74,7 +74,7 @@ impl DefPathTable { .map(|(index, &hash)| { let def_id = DefId { krate: cnum, - index: DefIndex::from_array_index(index), + index: DefIndex::from(index), }; (hash, def_id) }) @@ -387,7 +387,7 @@ impl Definitions { #[inline] pub fn as_local_node_id(&self, def_id: DefId) -> Option { if def_id.krate == LOCAL_CRATE { - let node_id = self.def_index_to_node[def_id.index.as_array_index()]; + let node_id = self.def_index_to_node[def_id.index.index()]; if node_id != ast::DUMMY_NODE_ID { return Some(node_id); } @@ -417,7 +417,7 @@ impl Definitions { #[inline] pub fn def_index_to_hir_id(&self, def_index: DefIndex) -> hir::HirId { - let node_id = self.def_index_to_node[def_index.as_array_index()]; + let node_id = self.def_index_to_node[def_index.index()]; self.node_to_hir_id[node_id] } @@ -508,7 +508,7 @@ impl Definitions { // Create the definition. let index = self.table.allocate(key, def_path_hash); - assert_eq!(index.as_array_index(), self.def_index_to_node.len()); + assert_eq!(index.index(), self.def_index_to_node.len()); self.def_index_to_node.push(node_id); // Some things for which we allocate DefIndices don't correspond to @@ -653,7 +653,7 @@ macro_rules! define_global_metadata_kind { .position(|k| *k == def_key) .unwrap(); - DefIndex::from_array_index(index) + DefIndex::from(index) } fn name(&self) -> Symbol { diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index b8ee98551a20..4b94f772554e 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -189,7 +189,7 @@ pub struct Map<'hir> { impl<'hir> Map<'hir> { #[inline] fn lookup(&self, id: HirId) -> Option<&Entry<'hir>> { - let local_map = self.map.get(id.owner.as_array_index())?; + let local_map = self.map.get(id.owner.index())?; local_map.as_ref()?.get(id.local_id)?.as_ref() } @@ -1023,7 +1023,7 @@ impl<'hir> Map<'hir> { local_map.iter_enumerated().filter_map(move |(i, entry)| entry.map(move |_| { // Reconstruct the HirId based on the 3 indices we used to find it HirId { - owner: DefIndex::from_array_index(array_index), + owner: DefIndex::from(array_index), local_id: i, } })) diff --git a/src/librustc/infer/lexical_region_resolve/graphviz.rs b/src/librustc/infer/lexical_region_resolve/graphviz.rs index 073a3f74422c..1878afd581dd 100644 --- a/src/librustc/infer/lexical_region_resolve/graphviz.rs +++ b/src/librustc/infer/lexical_region_resolve/graphviz.rs @@ -56,7 +56,7 @@ pub fn maybe_print_constraints_for<'a, 'gcx, 'tcx>( } let requested_node = env::var("RUST_REGION_GRAPH_NODE") - .ok().and_then(|s| s.parse().map(DefIndex::from_raw_u32).ok()); + .ok().and_then(|s| s.parse().map(DefIndex::from_u32).ok()); if requested_node.is_some() && requested_node != Some(context.index) { return; @@ -90,7 +90,7 @@ pub fn maybe_print_constraints_for<'a, 'gcx, 'tcx>( let mut new_str = String::new(); for c in output_template.chars() { if c == '%' { - new_str.push_str(&context.index.as_raw_u32().to_string()); + new_str.push_str(&context.index.as_u32().to_string()); } else { new_str.push(c); } diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index fc20735eb0f6..fdd1a821e31b 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -298,7 +298,7 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>( // negated `CrateNum` (so remote definitions are visited first) and then // by a flattened version of the `DefIndex`. trait_impls.sort_unstable_by_key(|def_id| { - (-(def_id.krate.as_u32() as i64), def_id.index.as_array_index()) + (-(def_id.krate.as_u32() as i64), def_id.index.index()) }); for impl_def_id in trait_impls { diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index c74ed5ec30c3..812321ff5e6c 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -648,7 +648,7 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec, // have to be user friendly. let name = format!( "hir_id_{}_{}", - hir_id.owner.as_array_index(), + hir_id.owner.index(), hir_id.local_id.index(), ); let lcfg = LabelledCFG { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index e950c2815e9b..d882fe6f27ec 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -264,7 +264,7 @@ impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { #[inline] fn specialized_decode(&mut self) -> Result { - Ok(DefIndex::from_raw_u32(self.read_u32()?)) + Ok(DefIndex::from_u32(self.read_u32()?)) } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0ac03526832b..939aadcc9ec9 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -134,7 +134,7 @@ impl<'a, 'tcx> SpecializedEncoder for EncodeContext<'a, 'tcx> { impl<'a, 'tcx> SpecializedEncoder for EncodeContext<'a, 'tcx> { #[inline] fn specialized_encode(&mut self, def_index: &DefIndex) -> Result<(), Self::Error> { - self.emit_u32(def_index.as_raw_u32()) + self.emit_u32(def_index.as_u32()) } } diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index 4c1e39cd0a9e..934e871559c7 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -93,7 +93,7 @@ impl Index { pub fn record_index(&mut self, item: DefIndex, entry: Lazy>) { assert!(entry.position < (u32::MAX as usize)); let position = entry.position as u32; - let array_index = item.as_array_index(); + let array_index = item.index(); let positions = &mut self.positions; assert!(u32::read_from_bytes_at(positions, array_index) == u32::MAX, @@ -126,7 +126,7 @@ impl<'tcx> LazySeq { def_index, self.len); - let position = u32::read_from_bytes_at(bytes, 1 + def_index.as_array_index()); + let position = u32::read_from_bytes_at(bytes, 1 + def_index.index()); if position == u32::MAX { debug!("Index::lookup: position=u32::MAX"); None diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs index 188da9a82dc9..fc4c6b3fd3f2 100644 --- a/src/librustc_mir/util/graphviz.rs +++ b/src/librustc_mir/util/graphviz.rs @@ -27,7 +27,7 @@ pub fn graphviz_safe_def_name(def_id: DefId) -> String { format!( "{}_{}", def_id.krate.index(), - def_id.index.as_array_index(), + def_id.index.index(), ) } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 9f3e1c308f63..e34a33ef8fad 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -172,7 +172,7 @@ impl<'a> base::Resolver for Resolver<'a> { fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc) { let def_id = DefId { krate: CrateNum::BuiltinMacros, - index: DefIndex::from_array_index(self.macro_map.len()), + index: DefIndex::from(self.macro_map.len()), }; let kind = ext.kind(); self.macro_map.insert(def_id, ext); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index e03da2ed608b..d34f5633946b 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -1170,7 +1170,7 @@ fn generated_code(span: Span) -> bool { fn id_from_def_id(id: DefId) -> rls_data::Id { rls_data::Id { krate: id.krate.as_u32(), - index: id.index.as_raw_u32(), + index: id.index.as_u32(), } } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 428f4f328b90..2a3bc5e99617 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -143,7 +143,7 @@ impl<'tcx> DocContext<'tcx> { crate_num, DefId { krate: crate_num, - index: DefIndex::from_array_index(def_id.index.as_array_index() + 1), + index: DefIndex::from(def_id.index.index() + 1), }, ); From 53e04742543c7034e1da912cc55cfa2a177b8c8b Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Fri, 17 May 2019 23:01:53 +0100 Subject: [PATCH 0132/3207] Add better tests for hidden lifetimes in impl trait --- src/test/ui/impl-trait/hidden-lifetimes.rs | 63 +++++++++++++++++++ .../ui/impl-trait/hidden-lifetimes.stderr | 27 ++++++++ src/test/ui/impl-trait/multiple-lifetimes.rs | 12 ++++ 3 files changed, 102 insertions(+) create mode 100644 src/test/ui/impl-trait/hidden-lifetimes.rs create mode 100644 src/test/ui/impl-trait/hidden-lifetimes.stderr create mode 100644 src/test/ui/impl-trait/multiple-lifetimes.rs diff --git a/src/test/ui/impl-trait/hidden-lifetimes.rs b/src/test/ui/impl-trait/hidden-lifetimes.rs new file mode 100644 index 000000000000..2ee004a37a6f --- /dev/null +++ b/src/test/ui/impl-trait/hidden-lifetimes.rs @@ -0,0 +1,63 @@ +// Test to show what happens if we were not careful and allowed invariant +// lifetimes to escape though an impl trait. +// +// Specifically we swap a long lived and short lived reference, giving us a +// dangling pointer. + +use std::cell::RefCell; +use std::rc::Rc; + +trait Swap: Sized { + fn swap(self, other: Self); +} + +impl Swap for &mut T { + fn swap(self, other: Self) { + std::mem::swap(self, other); + } +} + +impl Swap for Rc> { + fn swap(self, other: Self) { + >::swap(&self, &other); + } +} + +// Here we are hiding `'b` making the caller believe that `&'a mut &'s T` and +// `&'a mut &'l T` are the same type. +fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { + //~^ ERROR hidden type + x +} + +fn dangle_ref() -> &'static [i32; 3] { + let mut res = &[4, 5, 6]; + let x = [1, 2, 3]; + hide_ref(&mut res).swap(hide_ref(&mut &x)); + res +} + +// Here we are hiding `'b` making the caller believe that `Rc>` +// and `Rc>` are the same type. +// +// This is different to the previous example because the concrete return type +// only has a single lifetime. +fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a { + //~^ ERROR hidden type + x +} + +fn dangle_rc_refcell() -> &'static [i32; 3] { + let long = Rc::new(RefCell::new(&[4, 5, 6])); + let x = [1, 2, 3]; + let short = Rc::new(RefCell::new(&x)); + hide_rc_refcell(long.clone()).swap(hide_rc_refcell(short)); + let res: &'static [i32; 3] = *long.borrow(); + res +} + +fn main() { + // both will print nonsense values. + println!("{:?}", dangle_ref()); + println!("{:?}", dangle_rc_refcell()) +} diff --git a/src/test/ui/impl-trait/hidden-lifetimes.stderr b/src/test/ui/impl-trait/hidden-lifetimes.stderr new file mode 100644 index 000000000000..650161753d1e --- /dev/null +++ b/src/test/ui/impl-trait/hidden-lifetimes.stderr @@ -0,0 +1,27 @@ +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/hidden-lifetimes.rs:28:54 + | +LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { + | ^^^^^^^^^^^^^^ + | +note: hidden type `&'a mut &'b T` captures the lifetime 'b as defined on the function body at 28:17 + --> $DIR/hidden-lifetimes.rs:28:17 + | +LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { + | ^^ + +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/hidden-lifetimes.rs:45:70 + | +LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a { + | ^^^^^^^^^^^^^^ + | +note: hidden type `std::rc::Rc>` captures the lifetime 'b as defined on the function body at 45:24 + --> $DIR/hidden-lifetimes.rs:45:24 + | +LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a { + | ^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/impl-trait/multiple-lifetimes.rs b/src/test/ui/impl-trait/multiple-lifetimes.rs new file mode 100644 index 000000000000..8346542135be --- /dev/null +++ b/src/test/ui/impl-trait/multiple-lifetimes.rs @@ -0,0 +1,12 @@ +// Test that multiple liftimes are allowed in impl trait types. +// compile-pass + +trait X<'x>: Sized {} + +impl X<'_> for U {} + +fn multiple_lifeteimes<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl X<'b> + 'a { + x +} + +fn main() {} From a226b53b585d824f2268811894aa08e2495bc025 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 18 May 2019 14:40:17 +0200 Subject: [PATCH 0133/3207] expand comment in StorageLive --- src/librustc_mir/interpret/eval_context.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index db827afdb94f..d4c1e5416d56 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -613,7 +613,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc trace!("{:?} is now live", local); let local_val = LocalValue::Uninitialized; - // StorageLive *always* kills the value that's currently stored + // StorageLive *always* kills the value that's currently stored. + // However, we do not error if the variable already is live; + // see . Ok(mem::replace(&mut self.frame_mut().locals[local].value, local_val)) } From 5f5e30fd548a1cb223a8ed00abf949d5ca536fc4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 18 May 2019 14:40:34 +0200 Subject: [PATCH 0134/3207] update miri --- src/tools/miri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri b/src/tools/miri index bc0c76d861a1..37b2eea7144d 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit bc0c76d861a178911f3f506196a7404eda1e690d +Subproject commit 37b2eea7144d022702f0d2eedcc4c776db15d078 From 2caeaf54a1d44b1fe95c3ecaee9daa4ac576fd76 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 12 May 2019 16:53:39 +0200 Subject: [PATCH 0135/3207] Fix display of const generics in rustdoc --- src/librustdoc/clean/mod.rs | 5 ++++- src/librustdoc/html/format.rs | 4 +--- src/test/rustdoc/generic-const.rs | 30 ++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 src/test/rustdoc/generic-const.rs diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e9ccc61280b1..f91cb469e462 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3149,7 +3149,10 @@ impl<'tcx> Clean for ty::Const<'tcx> { fn clean(&self, cx: &DocContext<'_>) -> Constant { Constant { type_: self.ty.clean(cx), - expr: format!("{:?}", self.val), // FIXME(const_generics) + expr: match self.val { + ConstValue::Param(ty::ParamConst { name, .. }) => format!("{}", name), + e => format!("{:?}", e), // FIXME generic consts with expressions + }, } } } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 3d8af7c7716b..2784d5b3e10a 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -262,9 +262,7 @@ impl fmt::Display for clean::Lifetime { impl fmt::Display for clean::Constant { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.expr, f)?; - f.write_str(": ")?; - fmt::Display::fmt(&self.type_, f) + fmt::Display::fmt(&self.expr, f) } } diff --git a/src/test/rustdoc/generic-const.rs b/src/test/rustdoc/generic-const.rs new file mode 100644 index 000000000000..d6794ac8f1d9 --- /dev/null +++ b/src/test/rustdoc/generic-const.rs @@ -0,0 +1,30 @@ +#![feature(const_generics)] +#![crate_name = "foo"] + +// ignore-tidy-linelength + +pub enum Order { + Sorted, + Unsorted, +} + +// @has foo/struct.VSet.html '//pre[@class="rust struct"]' 'pub struct VSet' +// @has foo/struct.VSet.html '//h3[@id="impl-Send"]/code' 'impl Send for VSet' +// @has foo/struct.VSet.html '//h3[@id="impl-Sync"]/code' 'impl Sync for VSet' +pub struct VSet { + inner: Vec, +} + +// @has foo/struct.VSet.html '//h3[@id="impl"]/code' 'impl VSet' +impl VSet { + pub fn new() -> Self { + Self { inner: Vec::new() } + } +} + +// @has foo/struct.VSet.html '//h3[@id="impl-1"]/code' 'impl VSet' +impl VSet { + pub fn new() -> Self { + Self { inner: Vec::new() } + } +} From cb0039e3b749350fc649f3d19cb964ee798c1ac8 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 18 May 2019 17:51:12 +0200 Subject: [PATCH 0136/3207] Misc changes to rustc_metadata --- src/librustc_metadata/creader.rs | 6 +++--- src/librustc_metadata/locator.rs | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 7f2a1c0b4b1d..3e00ba3c6200 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -95,7 +95,7 @@ enum LoadError<'a> { impl<'a> LoadError<'a> { fn report(self) -> ! { match self { - LoadError::LocatorError(mut locate_ctxt) => locate_ctxt.report_errs(), + LoadError::LocatorError(locate_ctxt) => locate_ctxt.report_errs(), } } } @@ -365,8 +365,8 @@ impl<'a> CrateLoader<'a> { span, ident, crate_name: name, - hash: hash.map(|a| &*a), - extra_filename: extra_filename, + hash, + extra_filename, filesearch: self.sess.target_filesearch(path_kind), target: &self.sess.target.target, triple: self.sess.opts.target_triple.clone(), diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 7d7dd1061a95..3832c8ee227d 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -321,7 +321,7 @@ impl<'a> Context<'a> { } } - pub fn report_errs(&mut self) -> ! { + pub fn report_errs(self) -> ! { let add = match self.root { &None => String::new(), &Some(ref r) => format!(" which `{}` depends on", r.ident), @@ -901,8 +901,7 @@ fn get_metadata_section_imp(target: &Target, let mut inflated = Vec::new(); match DeflateDecoder::new(compressed_bytes).read_to_end(&mut inflated) { Ok(_) => { - let buf = unsafe { OwningRef::new_assert_stable_address(inflated) }; - rustc_erase_owner!(buf.map_owner_box()) + rustc_erase_owner!(OwningRef::new(inflated).map_owner_box()) } Err(_) => { return Err(format!("failed to decompress metadata: {}", filename.display())); From 13a00963a6684455c129f19a643b65226f438f37 Mon Sep 17 00:00:00 2001 From: Brent Kerby Date: Sat, 18 May 2019 10:03:12 -0600 Subject: [PATCH 0137/3207] fix copy-paste typo in docs for ptr::read_volatile --- src/libcore/ptr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index b6de9f57b011..ada784e9ce70 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -837,7 +837,7 @@ pub unsafe fn write_unaligned(dst: *mut T, src: T) { /// /// * `src` must be properly aligned. /// -/// Like [`read`], `read_unaligned` creates a bitwise copy of `T`, regardless of +/// Like [`read`], `read_volatile` creates a bitwise copy of `T`, regardless of /// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the returned /// value and the value at `*src` can [violate memory safety][read-ownership]. /// However, storing non-[`Copy`] types in volatile memory is almost certainly From 01cf36ebde50521993a61013487059be5f568c19 Mon Sep 17 00:00:00 2001 From: Brent Kerby Date: Sat, 18 May 2019 12:38:06 -0600 Subject: [PATCH 0138/3207] Simplify BufRead doc example using NLL --- src/libstd/io/mod.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 8fea6251e652..917199f8ea8d 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1579,18 +1579,13 @@ pub trait BufRead: Read { /// let stdin = io::stdin(); /// let mut stdin = stdin.lock(); /// - /// // we can't have two `&mut` references to `stdin`, so use a block - /// // to end the borrow early. - /// let length = { - /// let buffer = stdin.fill_buf().unwrap(); + /// let buffer = stdin.fill_buf().unwrap(); /// - /// // work with buffer - /// println!("{:?}", buffer); - /// - /// buffer.len() - /// }; + /// // work with buffer + /// println!("{:?}", buffer); /// /// // ensure the bytes we worked with aren't returned again later + /// let length = buffer.len(); /// stdin.consume(length); /// ``` #[stable(feature = "rust1", since = "1.0.0")] From 1c939a3e5539a45b400b620e5d41a5c162b05c74 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Sat, 18 May 2019 22:54:33 +0200 Subject: [PATCH 0139/3207] Update RLS --- src/tools/rls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rls b/src/tools/rls index 5b8e99bb6195..9692ca8fd82a 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 5b8e99bb61958ca8abcb7c5eda70521726be1065 +Subproject commit 9692ca8fd82a8f96a4113dc4b88c1fb1d79c1c60 From 8d419588f1ce626c37cc05780c8eb37322726fa4 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Sat, 18 May 2019 23:59:57 +0200 Subject: [PATCH 0140/3207] Reverse RLS toolstate check override As per https://github.com/rust-lang/rust/pull/60946#issuecomment-493707005 --- src/ci/docker/x86_64-gnu-tools/checkregression.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/ci/docker/x86_64-gnu-tools/checkregression.py b/src/ci/docker/x86_64-gnu-tools/checkregression.py index 8aa90319d661..0cc0a6329e5b 100755 --- a/src/ci/docker/x86_64-gnu-tools/checkregression.py +++ b/src/ci/docker/x86_64-gnu-tools/checkregression.py @@ -21,12 +21,7 @@ if __name__ == '__main__': state = cur[os_name] new_state = toolstate.get(tool, '') if verb == 'regressed': - if tool == 'rls': - # Temporary override until - # https://github.com/rust-lang/rust/issues/60848 is fixed. - updated = False - else: - updated = new_state < state + updated = new_state < state elif verb == 'changed': updated = new_state != state else: From 86cda2d48e14f5cb755f54e6728bd9485d04713e Mon Sep 17 00:00:00 2001 From: Brent Kerby Date: Sat, 18 May 2019 16:22:59 -0600 Subject: [PATCH 0141/3207] Fix typos in docs of GlobalAlloc --- src/libcore/alloc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index c124457118cb..0451edec87b2 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -480,7 +480,7 @@ pub unsafe trait GlobalAlloc { /// this allocator, /// /// * `layout` must be the same layout that was used - /// to allocated that block of memory, + /// to allocate that block of memory, #[stable(feature = "global_alloc", since = "1.28.0")] unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout); @@ -535,7 +535,7 @@ pub unsafe trait GlobalAlloc { /// * `ptr` must be currently allocated via this allocator, /// /// * `layout` must be the same layout that was used - /// to allocated that block of memory, + /// to allocate that block of memory, /// /// * `new_size` must be greater than zero. /// From a91ad60158647c1f6a89b9c01915279ce9314a65 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Sat, 18 May 2019 22:27:33 -0400 Subject: [PATCH 0142/3207] =?UTF-8?q?Make=20clear=20that=20status=20quo=20?= =?UTF-8?q?=E2=89=A0=20guarantee?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/run-pass/union/union-nonzero.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/run-pass/union/union-nonzero.rs b/src/test/run-pass/union/union-nonzero.rs index 2108cc3a4ea7..bd84b46bf3d2 100644 --- a/src/test/run-pass/union/union-nonzero.rs +++ b/src/test/run-pass/union/union-nonzero.rs @@ -6,8 +6,9 @@ // For example, if a union `U` can contain both a `&T` and a `*const T`, there's definitely no // bit-value that an `Option` could reuse as `None`; this test makes sure that isn't done. // -// Secondly, this tests the status quo to not apply such optimizations to types containing unions -// even if they're theoretically possible. (discussion: https://github.com/rust-lang/rust/issues/36394) +// Secondly, this tests the status quo (not a guarantee; subject to change!) to not apply such +// optimizations to types containing unions even if they're theoretically possible. (discussion: +// https://github.com/rust-lang/rust/issues/36394) // // Notably this nails down part of the behavior that `MaybeUninit` assumes: that a // `Option>` does not take advantage of non-zero optimization, and thus is a safe From ea7aa76911b6b896d503a812b26bfd6227fa90d9 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 18 May 2019 20:25:15 -0700 Subject: [PATCH 0143/3207] Document BinaryHeap time complexity I went into some detail on the time complexity of `push` because it is relevant for using BinaryHeap efficiently -- specifically that you should avoid pushing many elements in ascending order when possible. --- src/liballoc/collections/binary_heap.rs | 43 +++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/liballoc/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs index 39fcfaa78937..c5a0b6e877b6 100644 --- a/src/liballoc/collections/binary_heap.rs +++ b/src/liballoc/collections/binary_heap.rs @@ -231,6 +231,20 @@ use super::SpecExtend; /// assert_eq!(heap.pop(), Some(Reverse(5))); /// assert_eq!(heap.pop(), None); /// ``` +/// +/// # Time complexity +/// +/// | [push] | [pop] | [peek]/[peek\_mut] | +/// |--------|----------|--------------------| +/// | O(1)~ | O(log n) | O(1) | +/// +/// The value for `push` is an expected cost; the method documentation gives a +/// more detailed analysis. +/// +/// [push]: #method.push +/// [pop]: #method.pop +/// [peek]: #method.peek +/// [peek\_mut]: #method.peek_mut #[stable(feature = "rust1", since = "1.0.0")] pub struct BinaryHeap { data: Vec, @@ -384,6 +398,10 @@ impl BinaryHeap { /// } /// assert_eq!(heap.peek(), Some(&2)); /// ``` + /// + /// # Time complexity + /// + /// Cost is O(1) in the worst case. #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] pub fn peek_mut(&mut self) -> Option> { if self.is_empty() { @@ -411,6 +429,11 @@ impl BinaryHeap { /// assert_eq!(heap.pop(), Some(1)); /// assert_eq!(heap.pop(), None); /// ``` + /// + /// # Time complexity + /// + /// The worst case cost of `pop` on a heap containing *n* elements is O(log + /// n). #[stable(feature = "rust1", since = "1.0.0")] pub fn pop(&mut self) -> Option { self.data.pop().map(|mut item| { @@ -438,6 +461,22 @@ impl BinaryHeap { /// assert_eq!(heap.len(), 3); /// assert_eq!(heap.peek(), Some(&5)); /// ``` + /// + /// # Time complexity + /// + /// The expected cost of `push`, averaged over every possible ordering of + /// the elements being pushed, and over a sufficiently large number of + /// pushes, is O(1). This is the most meaningful cost metric when pushing + /// elements that are *not* already in any sorted pattern. + /// + /// The time complexity degrades if elements are pushed in predominantly + /// ascending order. In the worst case, elements are pushed in ascending + /// sorted order and the amortized cost per push is O(log n) against a heap + /// containing *n* elements. + /// + /// The worst case cost of a *single* call to `push` is O(n). The worst case + /// occurs when capacity is exhausted and needs a resize. The resize cost + /// has been amortized in the previous figures. #[stable(feature = "rust1", since = "1.0.0")] pub fn push(&mut self, item: T) { let old_len = self.len(); @@ -650,6 +689,10 @@ impl BinaryHeap { /// assert_eq!(heap.peek(), Some(&5)); /// /// ``` + /// + /// # Time complexity + /// + /// Cost is O(1) in the worst case. #[stable(feature = "rust1", since = "1.0.0")] pub fn peek(&self) -> Option<&T> { self.data.get(0) From b53d839b239d8fcf4cddfbd565ce5a8836217d5c Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 19 May 2019 12:31:08 +0900 Subject: [PATCH 0144/3207] Move arbitrary_self_types's tests into ui/self --- src/test/ui/{ => self}/arbitrary-self-types-not-object-safe.rs | 0 .../ui/{ => self}/arbitrary-self-types-not-object-safe.stderr | 0 .../self}/arbitrary_self_types_pointers_and_wrappers.rs | 1 + .../self/arbitrary_self_types_raw_pointer_struct.rs | 0 .../self/arbitrary_self_types_raw_pointer_trait.rs | 0 src/test/{run-pass => ui}/self/arbitrary_self_types_silly.rs | 0 .../self}/arbitrary_self_types_stdlib_pointers.rs | 1 + src/test/{run-pass => ui}/self/arbitrary_self_types_struct.rs | 0 src/test/{run-pass => ui}/self/arbitrary_self_types_trait.rs | 0 .../{run-pass => ui}/self/arbitrary_self_types_unsized_struct.rs | 0 10 files changed, 2 insertions(+) rename src/test/ui/{ => self}/arbitrary-self-types-not-object-safe.rs (100%) rename src/test/ui/{ => self}/arbitrary-self-types-not-object-safe.stderr (100%) rename src/test/{run-pass => ui/self}/arbitrary_self_types_pointers_and_wrappers.rs (99%) rename src/test/{run-pass => ui}/self/arbitrary_self_types_raw_pointer_struct.rs (100%) rename src/test/{run-pass => ui}/self/arbitrary_self_types_raw_pointer_trait.rs (100%) rename src/test/{run-pass => ui}/self/arbitrary_self_types_silly.rs (100%) rename src/test/{run-pass => ui/self}/arbitrary_self_types_stdlib_pointers.rs (99%) rename src/test/{run-pass => ui}/self/arbitrary_self_types_struct.rs (100%) rename src/test/{run-pass => ui}/self/arbitrary_self_types_trait.rs (100%) rename src/test/{run-pass => ui}/self/arbitrary_self_types_unsized_struct.rs (100%) diff --git a/src/test/ui/arbitrary-self-types-not-object-safe.rs b/src/test/ui/self/arbitrary-self-types-not-object-safe.rs similarity index 100% rename from src/test/ui/arbitrary-self-types-not-object-safe.rs rename to src/test/ui/self/arbitrary-self-types-not-object-safe.rs diff --git a/src/test/ui/arbitrary-self-types-not-object-safe.stderr b/src/test/ui/self/arbitrary-self-types-not-object-safe.stderr similarity index 100% rename from src/test/ui/arbitrary-self-types-not-object-safe.stderr rename to src/test/ui/self/arbitrary-self-types-not-object-safe.stderr diff --git a/src/test/run-pass/arbitrary_self_types_pointers_and_wrappers.rs b/src/test/ui/self/arbitrary_self_types_pointers_and_wrappers.rs similarity index 99% rename from src/test/run-pass/arbitrary_self_types_pointers_and_wrappers.rs rename to src/test/ui/self/arbitrary_self_types_pointers_and_wrappers.rs index 6904c29111ee..65fec3becace 100644 --- a/src/test/run-pass/arbitrary_self_types_pointers_and_wrappers.rs +++ b/src/test/ui/self/arbitrary_self_types_pointers_and_wrappers.rs @@ -1,3 +1,4 @@ +// run-pass #![feature(arbitrary_self_types, unsize, coerce_unsized, dispatch_from_dyn)] #![feature(rustc_attrs)] diff --git a/src/test/run-pass/self/arbitrary_self_types_raw_pointer_struct.rs b/src/test/ui/self/arbitrary_self_types_raw_pointer_struct.rs similarity index 100% rename from src/test/run-pass/self/arbitrary_self_types_raw_pointer_struct.rs rename to src/test/ui/self/arbitrary_self_types_raw_pointer_struct.rs diff --git a/src/test/run-pass/self/arbitrary_self_types_raw_pointer_trait.rs b/src/test/ui/self/arbitrary_self_types_raw_pointer_trait.rs similarity index 100% rename from src/test/run-pass/self/arbitrary_self_types_raw_pointer_trait.rs rename to src/test/ui/self/arbitrary_self_types_raw_pointer_trait.rs diff --git a/src/test/run-pass/self/arbitrary_self_types_silly.rs b/src/test/ui/self/arbitrary_self_types_silly.rs similarity index 100% rename from src/test/run-pass/self/arbitrary_self_types_silly.rs rename to src/test/ui/self/arbitrary_self_types_silly.rs diff --git a/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs b/src/test/ui/self/arbitrary_self_types_stdlib_pointers.rs similarity index 99% rename from src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs rename to src/test/ui/self/arbitrary_self_types_stdlib_pointers.rs index 9f6a647a07b3..29563fbbd867 100644 --- a/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs +++ b/src/test/ui/self/arbitrary_self_types_stdlib_pointers.rs @@ -1,3 +1,4 @@ +// run-pass #![feature(arbitrary_self_types)] #![feature(rustc_attrs)] diff --git a/src/test/run-pass/self/arbitrary_self_types_struct.rs b/src/test/ui/self/arbitrary_self_types_struct.rs similarity index 100% rename from src/test/run-pass/self/arbitrary_self_types_struct.rs rename to src/test/ui/self/arbitrary_self_types_struct.rs diff --git a/src/test/run-pass/self/arbitrary_self_types_trait.rs b/src/test/ui/self/arbitrary_self_types_trait.rs similarity index 100% rename from src/test/run-pass/self/arbitrary_self_types_trait.rs rename to src/test/ui/self/arbitrary_self_types_trait.rs diff --git a/src/test/run-pass/self/arbitrary_self_types_unsized_struct.rs b/src/test/ui/self/arbitrary_self_types_unsized_struct.rs similarity index 100% rename from src/test/run-pass/self/arbitrary_self_types_unsized_struct.rs rename to src/test/ui/self/arbitrary_self_types_unsized_struct.rs From 88fa5c6a45a533a78c698a22f4b16002a3bc9fc3 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 19 May 2019 13:59:44 +0300 Subject: [PATCH 0145/3207] Improve type size assertions Now they - Tell what the new size is, when it changes - Do not require passing an identifier --- src/librustc/hir/mod.rs | 2 +- src/librustc/middle/region.rs | 2 +- src/librustc/mir/interpret/pointer.rs | 2 +- src/librustc/mir/interpret/value.rs | 4 ++-- src/librustc/mir/mod.rs | 9 ++++----- src/librustc/mir/tcx.rs | 6 +++--- src/librustc/ty/mod.rs | 2 +- src/librustc/ty/sty.rs | 4 ++-- src/librustc_data_structures/macros.rs | 9 +++++++++ src/libsyntax/ast.rs | 4 ++-- src/libsyntax/parse/token.rs | 6 +++--- src/libsyntax/tokenstream.rs | 4 ++-- 12 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index f407be4e87b8..3ca79cb85012 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1356,7 +1356,7 @@ pub struct Expr { // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert!(MEM_SIZE_OF_EXPR: std::mem::size_of::() == 72); +static_assert_size!(Expr, 72); impl Expr { pub fn precedence(&self) -> ExprPrecedence { diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 8ef4e9ac8f45..37681ad7fcdd 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -158,7 +158,7 @@ newtype_index! { impl_stable_hash_for!(struct crate::middle::region::FirstStatementIndex { private }); // compilation error if size of `ScopeData` is not the same as a `u32` -static_assert!(ASSERT_SCOPE_DATA: mem::size_of::() == 4); +static_assert_size!(ScopeData, 4); impl Scope { /// Returns a item-local ID associated with this scope. diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs index 75e0f704a585..59b7891b90fd 100644 --- a/src/librustc/mir/interpret/pointer.rs +++ b/src/librustc/mir/interpret/pointer.rs @@ -78,7 +78,7 @@ pub struct Pointer { pub tag: Tag, } -static_assert!(POINTER_SIZE: ::std::mem::size_of::() == 16); +static_assert_size!(Pointer, 16); /// Produces a `Pointer` which points to the beginning of the Allocation impl From for Pointer { diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 7e45568725f3..551b86390db4 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -54,7 +54,7 @@ pub enum ConstValue<'tcx> { } #[cfg(target_arch = "x86_64")] -static_assert!(CONST_SIZE: ::std::mem::size_of::>() == 40); +static_assert_size!(ConstValue<'_>, 40); impl<'tcx> ConstValue<'tcx> { #[inline] @@ -111,7 +111,7 @@ pub enum Scalar { } #[cfg(target_arch = "x86_64")] -static_assert!(SCALAR_SIZE: ::std::mem::size_of::() == 24); +static_assert_size!(Scalar, 24); impl fmt::Display for Scalar { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index bd67aabfe8e5..dd43cb2f18ec 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1738,7 +1738,7 @@ pub struct Statement<'tcx> { // `Statement` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert!(MEM_SIZE_OF_STATEMENT: mem::size_of::>() == 56); +static_assert_size!(Statement<'_>, 56); impl<'tcx> Statement<'tcx> { /// Changes a statement to a nop. This is both faster than deleting instructions and avoids @@ -1997,10 +1997,9 @@ pub type PlaceProjection<'tcx> = Projection, Local, Ty<'tcx>>; /// and the index is a local. pub type PlaceElem<'tcx> = ProjectionElem>; -// at least on 64 bit systems, `PlaceElem` should not be larger than two pointers -static_assert!(PROJECTION_ELEM_IS_2_PTRS_LARGE: - mem::size_of::>() <= 16 -); +// At least on 64 bit systems, `PlaceElem` should not be larger than two pointers. +#[cfg(target_arch = "x86_64")] +static_assert_size!(PlaceElem<'_>, 16); /// Alias for projections as they appear in `UserTypeProjection`, where we /// need neither the `V` parameter for `Index` nor the `T` for `Field`. diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index d3fa5e84b6ad..5135aeb2392c 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -17,9 +17,9 @@ pub struct PlaceTy<'tcx> { pub variant_index: Option, } -static_assert!(PLACE_TY_IS_3_PTRS_LARGE: - mem::size_of::>() <= 24 -); +// At least on 64 bit systems, `PlaceTy` should not be larger than two or three pointers. +#[cfg(target_arch = "x86_64")] +static_assert_size!(PlaceTy<'_>, 16); impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> { pub fn from_ty(ty: Ty<'tcx>) -> PlaceTy<'tcx> { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 2f71861d4dc0..1e4bb37c44ef 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -510,7 +510,7 @@ pub struct TyS<'tcx> { // `TyS` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert!(MEM_SIZE_OF_TY_S: ::std::mem::size_of::>() == 32); +static_assert_size!(TyS<'_>, 32); impl<'tcx> Ord for TyS<'tcx> { fn cmp(&self, other: &TyS<'tcx>) -> Ordering { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 760f3d60d057..269064af93bc 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -211,7 +211,7 @@ pub enum TyKind<'tcx> { // `TyKind` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert!(MEM_SIZE_OF_TY_KIND: ::std::mem::size_of::>() == 24); +static_assert_size!(TyKind<'_>, 24); /// A closure can be modeled as a struct that looks like: /// @@ -2207,7 +2207,7 @@ pub struct Const<'tcx> { } #[cfg(target_arch = "x86_64")] -static_assert!(CONST_SIZE: ::std::mem::size_of::>() == 48); +static_assert_size!(Const<'_>, 48); impl<'tcx> Const<'tcx> { #[inline] diff --git a/src/librustc_data_structures/macros.rs b/src/librustc_data_structures/macros.rs index 029e7267c824..7fc23999284a 100644 --- a/src/librustc_data_structures/macros.rs +++ b/src/librustc_data_structures/macros.rs @@ -10,3 +10,12 @@ macro_rules! static_assert { static $name: () = [()][!($test: bool) as usize]; } } + +/// Type size assertion. The first argument is a type and the second argument is its expected size. +#[macro_export] +#[allow_internal_unstable(underscore_const_names)] +macro_rules! static_assert_size { + ($ty:ty, $size:expr) => { + const _: [(); $size] = [(); ::std::mem::size_of::<$ty>()]; + } +} diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d12240655e62..b55ca453fb3d 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -16,7 +16,7 @@ use crate::ThinVec; use rustc_data_structures::indexed_vec::Idx; #[cfg(target_arch = "x86_64")] -use rustc_data_structures::static_assert; +use rustc_data_structures::static_assert_size; use rustc_target::spec::abi::Abi; use syntax_pos::{Span, DUMMY_SP}; @@ -964,7 +964,7 @@ pub struct Expr { // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert!(MEM_SIZE_OF_EXPR: std::mem::size_of::() == 96); +static_assert_size!(Expr, 96); impl Expr { /// Whether this expression would be valid somewhere that expects a value; for example, an `if` diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 049fb6cb78b8..068fc41c87a0 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -19,7 +19,7 @@ use log::info; use std::fmt; use std::mem; #[cfg(target_arch = "x86_64")] -use rustc_data_structures::static_assert; +use rustc_data_structures::static_assert_size; use rustc_data_structures::sync::Lrc; #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] @@ -74,7 +74,7 @@ pub enum Lit { } #[cfg(target_arch = "x86_64")] -static_assert!(MEM_SIZE_OF_LIT: mem::size_of::() == 8); +static_assert_size!(Lit, 8); impl Lit { crate fn literal_name(&self) -> &'static str { @@ -220,7 +220,7 @@ pub enum Token { // `Token` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert!(MEM_SIZE_OF_STATEMENT: mem::size_of::() == 16); +static_assert_size!(Token, 16); impl Token { /// Recovers a `Token` from an `ast::Ident`. This creates a raw identifier if necessary. diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 93b5ecadd148..3cb16c30a50d 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -21,7 +21,7 @@ use crate::print::pprust; use syntax_pos::{BytePos, Mark, Span, DUMMY_SP}; #[cfg(target_arch = "x86_64")] -use rustc_data_structures::static_assert; +use rustc_data_structures::static_assert_size; use rustc_data_structures::sync::Lrc; use serialize::{Decoder, Decodable, Encoder, Encodable}; use smallvec::{SmallVec, smallvec}; @@ -158,7 +158,7 @@ pub type TreeAndJoint = (TokenTree, IsJoint); // `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert!(MEM_SIZE_OF_TOKEN_STREAM: mem::size_of::() == 8); +static_assert_size!(TokenStream, 8); #[derive(Clone, Copy, Debug, PartialEq)] pub enum IsJoint { From 6bb3980e7a7b6ecf891e2309cc858fe167d1a651 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 19 May 2019 13:00:28 +0100 Subject: [PATCH 0146/3207] Stop using gensyms in HIR lowering These names aren't ever handled by resolve, so there's no reason to make them gensyms. --- src/librustc/hir/lowering.rs | 37 +++++++++++++++--------------------- src/libsyntax_pos/symbol.rs | 7 +++++++ 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 970f6ba01773..3ec4d4e8cc8f 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -855,10 +855,6 @@ impl<'a> LoweringContext<'a> { self.sess.diagnostic() } - fn str_to_ident(&self, s: &'static str) -> Ident { - Ident::with_empty_ctxt(Symbol::gensym(s)) - } - fn with_anonymous_lifetime_mode( &mut self, anonymous_lifetime_mode: AnonymousLifetimeMode, @@ -4621,18 +4617,18 @@ impl<'a> LoweringContext<'a> { ); head.span = desugared_span; - let iter = self.str_to_ident("iter"); + let iter = Ident::with_empty_ctxt(sym::iter); - let next_ident = self.str_to_ident("__next"); + let next_ident = Ident::with_empty_ctxt(sym::__next); let (next_pat, next_pat_hid) = self.pat_ident_binding_mode( desugared_span, next_ident, hir::BindingAnnotation::Mutable, ); - // `::std::option::Option::Some(val) => next = val` + // `::std::option::Option::Some(val) => __next = val` let pat_arm = { - let val_ident = self.str_to_ident("val"); + let val_ident = Ident::with_empty_ctxt(sym::val); let (val_pat, val_pat_hid) = self.pat_ident(pat.span, val_ident); let val_expr = P(self.expr_ident(pat.span, val_ident, val_pat_hid)); let next_expr = P(self.expr_ident(pat.span, next_ident, next_pat_hid)); @@ -4771,17 +4767,13 @@ impl<'a> LoweringContext<'a> { let unstable_span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::QuestionMark, e.span, - Some(vec![ - Symbol::intern("try_trait") - ].into()), + Some(vec![sym::try_trait].into()), ); let try_span = self.sess.source_map().end_point(e.span); let try_span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::QuestionMark, try_span, - Some(vec![ - Symbol::intern("try_trait") - ].into()), + Some(vec![sym::try_trait].into()), ); // `Try::into_result()` @@ -4802,7 +4794,8 @@ impl<'a> LoweringContext<'a> { // `allow(unreachable_code)` let allow = { let allow_ident = Ident::with_empty_ctxt(sym::allow).with_span_pos(e.span); - let uc_ident = Ident::from_str("unreachable_code").with_span_pos(e.span); + let uc_ident = Ident::with_empty_ctxt(sym::unreachable_code) + .with_span_pos(e.span); let uc_nested = attr::mk_nested_word_item(uc_ident); attr::mk_list_item(e.span, allow_ident, vec![uc_nested]) }; @@ -4812,7 +4805,7 @@ impl<'a> LoweringContext<'a> { // `Ok(val) => #[allow(unreachable_code)] val,` let ok_arm = { - let val_ident = self.str_to_ident("val"); + let val_ident = Ident::with_empty_ctxt(sym::val); let (val_pat, val_pat_nid) = self.pat_ident(e.span, val_ident); let val_expr = P(self.expr_ident_with_attrs( e.span, @@ -4828,7 +4821,7 @@ impl<'a> LoweringContext<'a> { // `Err(err) => #[allow(unreachable_code)] // return Try::from_error(From::from(err)),` let err_arm = { - let err_ident = self.str_to_ident("err"); + let err_ident = Ident::with_empty_ctxt(sym::err); let (err_local, err_local_nid) = self.pat_ident(try_span, err_ident); let from_expr = { let from_path = &[sym::convert, sym::From, sym::from]; @@ -5552,7 +5545,7 @@ impl<'a> LoweringContext<'a> { // match ::std::future::poll_with_tls_context(unsafe { // ::std::pin::Pin::new_unchecked(&mut pinned) // }) { - // ::std::task::Poll::Ready(x) => break x, + // ::std::task::Poll::Ready(result) => break result, // ::std::task::Poll::Pending => {}, // } // yield (); @@ -5580,12 +5573,12 @@ impl<'a> LoweringContext<'a> { let gen_future_span = self.sess.source_map().mark_span_with_reason( CompilerDesugaringKind::Await, await_span, - Some(vec![Symbol::intern("gen_future")].into()), + Some(vec![sym::gen_future].into()), ); // let mut pinned = ; let expr = P(self.lower_expr(expr)); - let pinned_ident = self.str_to_ident("pinned"); + let pinned_ident = Ident::with_empty_ctxt(sym::pinned); let (pinned_pat, pinned_pat_hid) = self.pat_ident_binding_mode( span, pinned_ident, @@ -5621,11 +5614,11 @@ impl<'a> LoweringContext<'a> { )) }; - // `::std::task::Poll::Ready(x) => break x` + // `::std::task::Poll::Ready(result) => break result` let loop_node_id = self.sess.next_node_id(); let loop_hir_id = self.lower_node_id(loop_node_id); let ready_arm = { - let x_ident = self.str_to_ident("x"); + let x_ident = Ident::with_empty_ctxt(sym::result); let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident); let x_expr = P(self.expr_ident(span, x_ident, x_pat_hid)); let ready_pat = self.pat_std_enum( diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 01b126f48b32..97b22282668a 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -229,6 +229,7 @@ symbols! { eh_personality, eh_unwind_resume, enable, + err, Err, except, exclusive_range_pattern, @@ -260,6 +261,7 @@ symbols! { fundamental, future, Future, + gen_future, generators, generic_associated_types, generic_param_attrs, @@ -361,6 +363,7 @@ symbols! { never, never_type, next, + __next, nll, no_builtins, no_core, @@ -406,6 +409,7 @@ symbols! { Pending, pin, Pin, + pinned, platform_intrinsics, plugin, plugin_registrar, @@ -569,6 +573,7 @@ symbols! { trivial_bounds, Try, try_blocks, + try_trait, tuple_indexing, ty, type_alias_enum_variants, @@ -587,6 +592,7 @@ symbols! { uniform_paths, universal_impl_trait, unmarked_api, + unreachable_code, unrestricted_attribute_tokens, unsafe_destructor_blind_to_params, unsafe_no_drop_flag, @@ -601,6 +607,7 @@ symbols! { use_nested_groups, usize, v1, + val, vis, visible_private_types, volatile, From 3e73ca6e336650eb0cb8429b3932d63d71c2a476 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 19 May 2019 22:17:12 +0900 Subject: [PATCH 0147/3207] Move run-pass/self/* to ui/self --- .../{run-pass => ui}/self/auxiliary/explicit_self_xcrate.rs | 0 src/test/{run-pass => ui}/self/builtin-superkinds-self-type.rs | 0 src/test/{run-pass => ui}/self/by-value-self-in-mut-slot.rs | 0 src/test/{run-pass => ui}/self/explicit-self-closures.rs | 2 +- src/test/{run-pass => ui}/self/explicit-self-generic.rs | 0 src/test/{run-pass => ui}/self/explicit-self-objects-uniq.rs | 0 src/test/{run-pass => ui}/self/explicit-self.rs | 0 src/test/{run-pass => ui}/self/explicit_self_xcrate_exe.rs | 0 src/test/{run-pass => ui}/self/move-self.rs | 0 .../self/object-safety-sized-self-by-value-self.rs | 0 .../self/object-safety-sized-self-generic-method.rs | 0 .../self/object-safety-sized-self-return-Self.rs | 0 src/test/{run-pass/self/self-impl.rs => ui/self/self-impl-2.rs} | 0 .../{run-pass => ui}/self/self-in-mut-slot-default-method.rs | 0 .../{run-pass => ui}/self/self-in-mut-slot-immediate-value.rs | 0 src/test/{run-pass => ui}/self/self-in-typedefs.rs | 2 +- src/test/{run-pass => ui}/self/self-re-assign.rs | 0 src/test/{run-pass => ui}/self/self-shadowing-import.rs | 0 src/test/{run-pass => ui}/self/self-type-param.rs | 2 +- src/test/{run-pass => ui}/self/string-self-append.rs | 0 src/test/{run-pass => ui}/self/ufcs-explicit-self.rs | 0 src/test/{run-pass => ui}/self/uniq-self-in-mut-slot.rs | 0 src/test/{run-pass => ui}/self/where-for-self.rs | 0 23 files changed, 3 insertions(+), 3 deletions(-) rename src/test/{run-pass => ui}/self/auxiliary/explicit_self_xcrate.rs (100%) rename src/test/{run-pass => ui}/self/builtin-superkinds-self-type.rs (100%) rename src/test/{run-pass => ui}/self/by-value-self-in-mut-slot.rs (100%) rename src/test/{run-pass => ui}/self/explicit-self-closures.rs (94%) rename src/test/{run-pass => ui}/self/explicit-self-generic.rs (100%) rename src/test/{run-pass => ui}/self/explicit-self-objects-uniq.rs (100%) rename src/test/{run-pass => ui}/self/explicit-self.rs (100%) rename src/test/{run-pass => ui}/self/explicit_self_xcrate_exe.rs (100%) rename src/test/{run-pass => ui}/self/move-self.rs (100%) rename src/test/{run-pass => ui}/self/object-safety-sized-self-by-value-self.rs (100%) rename src/test/{run-pass => ui}/self/object-safety-sized-self-generic-method.rs (100%) rename src/test/{run-pass => ui}/self/object-safety-sized-self-return-Self.rs (100%) rename src/test/{run-pass/self/self-impl.rs => ui/self/self-impl-2.rs} (100%) rename src/test/{run-pass => ui}/self/self-in-mut-slot-default-method.rs (100%) rename src/test/{run-pass => ui}/self/self-in-mut-slot-immediate-value.rs (100%) rename src/test/{run-pass => ui}/self/self-in-typedefs.rs (96%) rename src/test/{run-pass => ui}/self/self-re-assign.rs (100%) rename src/test/{run-pass => ui}/self/self-shadowing-import.rs (100%) rename src/test/{run-pass => ui}/self/self-type-param.rs (93%) rename src/test/{run-pass => ui}/self/string-self-append.rs (100%) rename src/test/{run-pass => ui}/self/ufcs-explicit-self.rs (100%) rename src/test/{run-pass => ui}/self/uniq-self-in-mut-slot.rs (100%) rename src/test/{run-pass => ui}/self/where-for-self.rs (100%) diff --git a/src/test/run-pass/self/auxiliary/explicit_self_xcrate.rs b/src/test/ui/self/auxiliary/explicit_self_xcrate.rs similarity index 100% rename from src/test/run-pass/self/auxiliary/explicit_self_xcrate.rs rename to src/test/ui/self/auxiliary/explicit_self_xcrate.rs diff --git a/src/test/run-pass/self/builtin-superkinds-self-type.rs b/src/test/ui/self/builtin-superkinds-self-type.rs similarity index 100% rename from src/test/run-pass/self/builtin-superkinds-self-type.rs rename to src/test/ui/self/builtin-superkinds-self-type.rs diff --git a/src/test/run-pass/self/by-value-self-in-mut-slot.rs b/src/test/ui/self/by-value-self-in-mut-slot.rs similarity index 100% rename from src/test/run-pass/self/by-value-self-in-mut-slot.rs rename to src/test/ui/self/by-value-self-in-mut-slot.rs diff --git a/src/test/run-pass/self/explicit-self-closures.rs b/src/test/ui/self/explicit-self-closures.rs similarity index 94% rename from src/test/run-pass/self/explicit-self-closures.rs rename to src/test/ui/self/explicit-self-closures.rs index 61be98fe3d3c..1217823da116 100644 --- a/src/test/run-pass/self/explicit-self-closures.rs +++ b/src/test/ui/self/explicit-self-closures.rs @@ -1,4 +1,4 @@ -// run-pass +// compile-pass #![allow(dead_code)] // Test to make sure that explicit self params work inside closures diff --git a/src/test/run-pass/self/explicit-self-generic.rs b/src/test/ui/self/explicit-self-generic.rs similarity index 100% rename from src/test/run-pass/self/explicit-self-generic.rs rename to src/test/ui/self/explicit-self-generic.rs diff --git a/src/test/run-pass/self/explicit-self-objects-uniq.rs b/src/test/ui/self/explicit-self-objects-uniq.rs similarity index 100% rename from src/test/run-pass/self/explicit-self-objects-uniq.rs rename to src/test/ui/self/explicit-self-objects-uniq.rs diff --git a/src/test/run-pass/self/explicit-self.rs b/src/test/ui/self/explicit-self.rs similarity index 100% rename from src/test/run-pass/self/explicit-self.rs rename to src/test/ui/self/explicit-self.rs diff --git a/src/test/run-pass/self/explicit_self_xcrate_exe.rs b/src/test/ui/self/explicit_self_xcrate_exe.rs similarity index 100% rename from src/test/run-pass/self/explicit_self_xcrate_exe.rs rename to src/test/ui/self/explicit_self_xcrate_exe.rs diff --git a/src/test/run-pass/self/move-self.rs b/src/test/ui/self/move-self.rs similarity index 100% rename from src/test/run-pass/self/move-self.rs rename to src/test/ui/self/move-self.rs diff --git a/src/test/run-pass/self/object-safety-sized-self-by-value-self.rs b/src/test/ui/self/object-safety-sized-self-by-value-self.rs similarity index 100% rename from src/test/run-pass/self/object-safety-sized-self-by-value-self.rs rename to src/test/ui/self/object-safety-sized-self-by-value-self.rs diff --git a/src/test/run-pass/self/object-safety-sized-self-generic-method.rs b/src/test/ui/self/object-safety-sized-self-generic-method.rs similarity index 100% rename from src/test/run-pass/self/object-safety-sized-self-generic-method.rs rename to src/test/ui/self/object-safety-sized-self-generic-method.rs diff --git a/src/test/run-pass/self/object-safety-sized-self-return-Self.rs b/src/test/ui/self/object-safety-sized-self-return-Self.rs similarity index 100% rename from src/test/run-pass/self/object-safety-sized-self-return-Self.rs rename to src/test/ui/self/object-safety-sized-self-return-Self.rs diff --git a/src/test/run-pass/self/self-impl.rs b/src/test/ui/self/self-impl-2.rs similarity index 100% rename from src/test/run-pass/self/self-impl.rs rename to src/test/ui/self/self-impl-2.rs diff --git a/src/test/run-pass/self/self-in-mut-slot-default-method.rs b/src/test/ui/self/self-in-mut-slot-default-method.rs similarity index 100% rename from src/test/run-pass/self/self-in-mut-slot-default-method.rs rename to src/test/ui/self/self-in-mut-slot-default-method.rs diff --git a/src/test/run-pass/self/self-in-mut-slot-immediate-value.rs b/src/test/ui/self/self-in-mut-slot-immediate-value.rs similarity index 100% rename from src/test/run-pass/self/self-in-mut-slot-immediate-value.rs rename to src/test/ui/self/self-in-mut-slot-immediate-value.rs diff --git a/src/test/run-pass/self/self-in-typedefs.rs b/src/test/ui/self/self-in-typedefs.rs similarity index 96% rename from src/test/run-pass/self/self-in-typedefs.rs rename to src/test/ui/self/self-in-typedefs.rs index 9c0906013faf..e4fe7324ef3a 100644 --- a/src/test/run-pass/self/self-in-typedefs.rs +++ b/src/test/ui/self/self-in-typedefs.rs @@ -1,4 +1,4 @@ -// run-pass +// compile-pass #![feature(untagged_unions)] diff --git a/src/test/run-pass/self/self-re-assign.rs b/src/test/ui/self/self-re-assign.rs similarity index 100% rename from src/test/run-pass/self/self-re-assign.rs rename to src/test/ui/self/self-re-assign.rs diff --git a/src/test/run-pass/self/self-shadowing-import.rs b/src/test/ui/self/self-shadowing-import.rs similarity index 100% rename from src/test/run-pass/self/self-shadowing-import.rs rename to src/test/ui/self/self-shadowing-import.rs diff --git a/src/test/run-pass/self/self-type-param.rs b/src/test/ui/self/self-type-param.rs similarity index 93% rename from src/test/run-pass/self/self-type-param.rs rename to src/test/ui/self/self-type-param.rs index 6deae5f2d12f..57e01caa692d 100644 --- a/src/test/run-pass/self/self-type-param.rs +++ b/src/test/ui/self/self-type-param.rs @@ -1,4 +1,4 @@ -// run-pass +// compile-pass #![allow(dead_code)] // pretty-expanded FIXME #23616 diff --git a/src/test/run-pass/self/string-self-append.rs b/src/test/ui/self/string-self-append.rs similarity index 100% rename from src/test/run-pass/self/string-self-append.rs rename to src/test/ui/self/string-self-append.rs diff --git a/src/test/run-pass/self/ufcs-explicit-self.rs b/src/test/ui/self/ufcs-explicit-self.rs similarity index 100% rename from src/test/run-pass/self/ufcs-explicit-self.rs rename to src/test/ui/self/ufcs-explicit-self.rs diff --git a/src/test/run-pass/self/uniq-self-in-mut-slot.rs b/src/test/ui/self/uniq-self-in-mut-slot.rs similarity index 100% rename from src/test/run-pass/self/uniq-self-in-mut-slot.rs rename to src/test/ui/self/uniq-self-in-mut-slot.rs diff --git a/src/test/run-pass/self/where-for-self.rs b/src/test/ui/self/where-for-self.rs similarity index 100% rename from src/test/run-pass/self/where-for-self.rs rename to src/test/ui/self/where-for-self.rs From a759565763c51ed856937d3a8b520d26e5270ba2 Mon Sep 17 00:00:00 2001 From: VeryTastyTomato Date: Sun, 19 May 2019 13:51:46 +0000 Subject: [PATCH 0148/3207] Fix data types indication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the data types indication in basic examples of the Trait std::fmt::LowerExp and std::fmt::UpperExp. Since there aren’t any type annotation on the let statement using the number 42.0, they are of type f64 according to The Book: https://doc.rust-lang.org/book/ch03-02-data-types.html#floating-point-types --- src/libcore/fmt/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 43c1a3b7767a..2f6d745d146d 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -886,7 +886,7 @@ pub trait Pointer { /// /// # Examples /// -/// Basic usage with `i32`: +/// Basic usage with `f64`: /// /// ``` /// let x = 42.0; // 42.0 is '4.2e1' in scientific notation @@ -929,7 +929,7 @@ pub trait LowerExp { /// /// # Examples /// -/// Basic usage with `f32`: +/// Basic usage with `f64`: /// /// ``` /// let x = 42.0; // 42.0 is '4.2E1' in scientific notation From 8e99c76089ecb69479532e22ae2879e3bb1b3d68 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sat, 11 May 2019 10:55:34 -0400 Subject: [PATCH 0149/3207] [const-prop] Support propagating into Assert's `cond` Operand --- src/librustc_mir/transform/const_prop.rs | 146 +++++++++++---------- src/test/mir-opt/const_prop/array_index.rs | 2 +- src/test/mir-opt/const_prop/checked_add.rs | 2 +- 3 files changed, 81 insertions(+), 69 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 4e214c3c7253..0247ffbb9d15 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -656,75 +656,87 @@ impl<'b, 'a, 'tcx> MutVisitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { location: Location, ) { self.super_terminator(terminator, location); - let source_info = terminator.source_info;; - if let TerminatorKind::Assert { expected, msg, cond, .. } = &terminator.kind { - if let Some(value) = self.eval_operand(&cond, source_info) { - trace!("assertion on {:?} should be {:?}", value, expected); - let expected = ScalarMaybeUndef::from(Scalar::from_bool(*expected)); - if expected != self.ecx.read_scalar(value).unwrap() { - // poison all places this operand references so that further code - // doesn't use the invalid value - match cond { - Operand::Move(ref place) | Operand::Copy(ref place) => { - let mut place = place; - while let Place::Projection(ref proj) = *place { - place = &proj.base; - } - if let Place::Base(PlaceBase::Local(local)) = *place { - self.places[local] = None; - } - }, - Operand::Constant(_) => {} + let source_info = terminator.source_info; + match &mut terminator.kind { + TerminatorKind::Assert { expected, msg, ref mut cond, .. } => { + if let Some(value) = self.eval_operand(&cond, source_info) { + trace!("assertion on {:?} should be {:?}", value, expected); + let expected = ScalarMaybeUndef::from(Scalar::from_bool(*expected)); + let value_const = self.ecx.read_scalar(value).unwrap(); + if expected != value_const { + // poison all places this operand references so that further code + // doesn't use the invalid value + match cond { + Operand::Move(ref place) | Operand::Copy(ref place) => { + let mut place = place; + while let Place::Projection(ref proj) = *place { + place = &proj.base; + } + if let Place::Base(PlaceBase::Local(local)) = *place { + self.places[local] = None; + } + }, + Operand::Constant(_) => {} + } + let span = terminator.source_info.span; + let hir_id = self + .tcx + .hir() + .as_local_hir_id(self.source.def_id()) + .expect("some part of a failing const eval must be local"); + use rustc::mir::interpret::InterpError::*; + let msg = match msg { + Overflow(_) | + OverflowNeg | + DivisionByZero | + RemainderByZero => msg.description().to_owned(), + BoundsCheck { ref len, ref index } => { + let len = self + .eval_operand(len, source_info) + .expect("len must be const"); + let len = match self.ecx.read_scalar(len) { + Ok(ScalarMaybeUndef::Scalar(Scalar::Bits { + bits, .. + })) => bits, + other => bug!("const len not primitive: {:?}", other), + }; + let index = self + .eval_operand(index, source_info) + .expect("index must be const"); + let index = match self.ecx.read_scalar(index) { + Ok(ScalarMaybeUndef::Scalar(Scalar::Bits { + bits, .. + })) => bits, + other => bug!("const index not primitive: {:?}", other), + }; + format!( + "index out of bounds: \ + the len is {} but the index is {}", + len, + index, + ) + }, + // Need proper const propagator for these + _ => return, + }; + self.tcx.lint_hir( + ::rustc::lint::builtin::CONST_ERR, + hir_id, + span, + &msg, + ); + } else { + if let ScalarMaybeUndef::Scalar(scalar) = value_const { + *cond = self.operand_from_scalar( + scalar, + self.tcx.types.bool, + source_info.span, + ); + } } - let span = terminator.source_info.span; - let hir_id = self - .tcx - .hir() - .as_local_hir_id(self.source.def_id()) - .expect("some part of a failing const eval must be local"); - use rustc::mir::interpret::InterpError::*; - let msg = match msg { - Overflow(_) | - OverflowNeg | - DivisionByZero | - RemainderByZero => msg.description().to_owned(), - BoundsCheck { ref len, ref index } => { - let len = self - .eval_operand(len, source_info) - .expect("len must be const"); - let len = match self.ecx.read_scalar(len) { - Ok(ScalarMaybeUndef::Scalar(Scalar::Bits { - bits, .. - })) => bits, - other => bug!("const len not primitive: {:?}", other), - }; - let index = self - .eval_operand(index, source_info) - .expect("index must be const"); - let index = match self.ecx.read_scalar(index) { - Ok(ScalarMaybeUndef::Scalar(Scalar::Bits { - bits, .. - })) => bits, - other => bug!("const index not primitive: {:?}", other), - }; - format!( - "index out of bounds: \ - the len is {} but the index is {}", - len, - index, - ) - }, - // Need proper const propagator for these - _ => return, - }; - self.tcx.lint_hir( - ::rustc::lint::builtin::CONST_ERR, - hir_id, - span, - &msg, - ); } - } + }, + _ => {} } } } diff --git a/src/test/mir-opt/const_prop/array_index.rs b/src/test/mir-opt/const_prop/array_index.rs index 4b97af68ff08..dd22eb5d604e 100644 --- a/src/test/mir-opt/const_prop/array_index.rs +++ b/src/test/mir-opt/const_prop/array_index.rs @@ -23,7 +23,7 @@ fn main() { // bb0: { // ... // _5 = const true; -// assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb1; +// assert(const true, "index out of bounds: the len is move _4 but the index is _3") -> bb1; // } // bb1: { // _1 = _2[_3]; diff --git a/src/test/mir-opt/const_prop/checked_add.rs b/src/test/mir-opt/const_prop/checked_add.rs index 0718316307c5..fe98cf24eec0 100644 --- a/src/test/mir-opt/const_prop/checked_add.rs +++ b/src/test/mir-opt/const_prop/checked_add.rs @@ -16,6 +16,6 @@ fn main() { // bb0: { // ... // _2 = (const 2u32, const false); -// assert(!move (_2.1: bool), "attempt to add with overflow") -> bb1; +// assert(!const false, "attempt to add with overflow") -> bb1; // } // END rustc.main.ConstProp.after.mir From 3f5c743b531e948788db18ce8d514de06113cb35 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sat, 11 May 2019 11:24:14 -0400 Subject: [PATCH 0150/3207] [const-prop] Support propagating into SwitchInt's `discr` Operand --- src/librustc_mir/transform/const_prop.rs | 7 +++++ src/test/mir-opt/const_prop/switch_int.rs | 38 +++++++++++++++++++++++ src/test/mir-opt/simplify_if.rs | 8 ++--- 3 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 src/test/mir-opt/const_prop/switch_int.rs diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 0247ffbb9d15..023b7132bd58 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -736,6 +736,13 @@ impl<'b, 'a, 'tcx> MutVisitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { } } }, + TerminatorKind::SwitchInt { ref mut discr, switch_ty, .. } => { + if let Some(value) = self.eval_operand(&discr, source_info) { + if let ScalarMaybeUndef::Scalar(scalar) = self.ecx.read_scalar(value).unwrap() { + *discr = self.operand_from_scalar(scalar, switch_ty, source_info.span); + } + } + }, _ => {} } } diff --git a/src/test/mir-opt/const_prop/switch_int.rs b/src/test/mir-opt/const_prop/switch_int.rs new file mode 100644 index 000000000000..0df1112ec3eb --- /dev/null +++ b/src/test/mir-opt/const_prop/switch_int.rs @@ -0,0 +1,38 @@ +#[inline(never)] +fn foo(_: i32) { } + +fn main() { + match 1 { + 1 => foo(0), + _ => foo(-1), + } +} + +// END RUST SOURCE +// START rustc.main.ConstProp.before.mir +// bb0: { +// ... +// _1 = const 1i32; +// switchInt(_1) -> [1i32: bb1, otherwise: bb2]; +// } +// END rustc.main.ConstProp.before.mir +// START rustc.main.ConstProp.after.mir +// bb0: { +// ... +// switchInt(const 1i32) -> [1i32: bb1, otherwise: bb2]; +// } +// END rustc.main.ConstProp.after.mir +// START rustc.main.SimplifyBranches-after-const-prop.before.mir +// bb0: { +// ... +// _1 = const 1i32; +// switchInt(const 1i32) -> [1i32: bb1, otherwise: bb2]; +// } +// END rustc.main.SimplifyBranches-after-const-prop.before.mir +// START rustc.main.SimplifyBranches-after-const-prop.after.mir +// bb0: { +// ... +// _1 = const 1i32; +// goto -> bb1; +// } +// END rustc.main.SimplifyBranches-after-const-prop.after.mir diff --git a/src/test/mir-opt/simplify_if.rs b/src/test/mir-opt/simplify_if.rs index b2a99a6d446b..35512b94c0c8 100644 --- a/src/test/mir-opt/simplify_if.rs +++ b/src/test/mir-opt/simplify_if.rs @@ -5,15 +5,15 @@ fn main() { } // END RUST SOURCE -// START rustc.main.SimplifyBranches-after-copy-prop.before.mir +// START rustc.main.SimplifyBranches-after-const-prop.before.mir // bb0: { // ... // switchInt(const false) -> [false: bb3, otherwise: bb1]; // } -// END rustc.main.SimplifyBranches-after-copy-prop.before.mir -// START rustc.main.SimplifyBranches-after-copy-prop.after.mir +// END rustc.main.SimplifyBranches-after-const-prop.before.mir +// START rustc.main.SimplifyBranches-after-const-prop.after.mir // bb0: { // ... // goto -> bb3; // } -// END rustc.main.SimplifyBranches-after-copy-prop.after.mir +// END rustc.main.SimplifyBranches-after-const-prop.after.mir From 2baab0eaaa8daa0f972b580748815db970ca547d Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sat, 11 May 2019 12:28:53 -0400 Subject: [PATCH 0151/3207] [const-prop] Remove catch all match and add FIXME --- src/librustc_mir/transform/const_prop.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 023b7132bd58..86c7f7bbdedc 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -743,7 +743,20 @@ impl<'b, 'a, 'tcx> MutVisitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { } } }, - _ => {} + //none of these have Operands to const-propagate + TerminatorKind::Goto { .. } | + TerminatorKind::Resume | + TerminatorKind::Abort | + TerminatorKind::Return | + TerminatorKind::Unreachable | + TerminatorKind::Drop { .. } | + TerminatorKind::DropAndReplace { .. } | + TerminatorKind::Yield { .. } | + TerminatorKind::GeneratorDrop | + TerminatorKind::FalseEdges { .. } | + TerminatorKind::FalseUnwind { .. } => { } + //FIXME(wesleywiser) Call does have Operands that could be const-propagated + TerminatorKind::Call { .. } => { } } } } From ec853ba026261bc1c8c53a99d210c02f88fde54f Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sat, 11 May 2019 12:33:10 -0400 Subject: [PATCH 0152/3207] [const-prop] Don't const-prop into terminators unless mir-opt-level >= 2 --- src/librustc_mir/transform/const_prop.rs | 29 ++++++++++++++++-------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 86c7f7bbdedc..8f3dd72c4f24 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -546,6 +546,10 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> { } } } + + fn should_const_prop(&self) -> bool { + self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2 + } } fn type_size_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -639,7 +643,7 @@ impl<'b, 'a, 'tcx> MutVisitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { assert!(self.places[local].is_none()); self.places[local] = Some(value); - if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2 { + if self.should_const_prop() { self.replace_with_const(rval, value, statement.source_info.span); } } @@ -726,20 +730,25 @@ impl<'b, 'a, 'tcx> MutVisitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { &msg, ); } else { - if let ScalarMaybeUndef::Scalar(scalar) = value_const { - *cond = self.operand_from_scalar( - scalar, - self.tcx.types.bool, - source_info.span, - ); + if self.should_const_prop() { + if let ScalarMaybeUndef::Scalar(scalar) = value_const { + *cond = self.operand_from_scalar( + scalar, + self.tcx.types.bool, + source_info.span, + ); + } } } } }, TerminatorKind::SwitchInt { ref mut discr, switch_ty, .. } => { - if let Some(value) = self.eval_operand(&discr, source_info) { - if let ScalarMaybeUndef::Scalar(scalar) = self.ecx.read_scalar(value).unwrap() { - *discr = self.operand_from_scalar(scalar, switch_ty, source_info.span); + if self.should_const_prop() { + if let Some(value) = self.eval_operand(&discr, source_info) { + if let ScalarMaybeUndef::Scalar(scalar) = + self.ecx.read_scalar(value).unwrap() { + *discr = self.operand_from_scalar(scalar, switch_ty, source_info.span); + } } } }, From b96be5b1889a28d0d44b54a18c8d0467da109656 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 14 May 2019 13:47:01 +1000 Subject: [PATCH 0153/3207] Avoid `as_str()` in `ParamTy::is_self`. It's a hot function, and a direct `Symbol` comparison is faster. The patch also converts some `&InternedString`s to `InternedString`. --- src/librustc/hir/mod.rs | 4 ++-- src/librustc/infer/error_reporting/mod.rs | 6 +++--- .../infer/error_reporting/nice_region_error/util.rs | 2 +- src/librustc/ty/sty.rs | 2 +- .../nll/region_infer/error_reporting/region_name.rs | 10 +++++----- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index f407be4e87b8..22312e7459be 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -609,9 +609,9 @@ impl Generics { own_counts } - pub fn get_named(&self, name: &InternedString) -> Option<&GenericParam> { + pub fn get_named(&self, name: InternedString) -> Option<&GenericParam> { for param in &self.params { - if *name == param.name.ident().as_interned_str() { + if name == param.name.ident().as_interned_str() { return Some(param); } } diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 4b6e7da33308..e4505a240379 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -194,20 +194,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let mut sp = cm.def_span(self.hir().span_by_hir_id(node)); if let Some(param) = self.hir() .get_generics(scope) - .and_then(|generics| generics.get_named(&br.name)) + .and_then(|generics| generics.get_named(br.name)) { sp = param.span; } (format!("the lifetime {} as defined on", br.name), sp) } ty::ReFree(ty::FreeRegion { - bound_region: ty::BoundRegion::BrNamed(_, ref name), + bound_region: ty::BoundRegion::BrNamed(_, name), .. }) => { let mut sp = cm.def_span(self.hir().span_by_hir_id(node)); if let Some(param) = self.hir() .get_generics(scope) - .and_then(|generics| generics.get_named(&name)) + .and_then(|generics| generics.get_named(name)) { sp = param.span; } diff --git a/src/librustc/infer/error_reporting/nice_region_error/util.rs b/src/librustc/infer/error_reporting/nice_region_error/util.rs index 3ed28a1f9882..feade7a8f56f 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/util.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/util.rs @@ -43,7 +43,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { ) -> Option> { let (id, bound_region) = match *anon_region { ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region), - ty::ReEarlyBound(ref ebr) => ( + ty::ReEarlyBound(ebr) => ( self.tcx().parent(ebr.def_id).unwrap(), ty::BoundRegion::BrNamed(ebr.def_id, ebr.name), ), diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 760f3d60d057..d20840ef7cf4 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1136,7 +1136,7 @@ impl<'a, 'gcx, 'tcx> ParamTy { // FIXME(#50125): Ignoring `Self` with `index != 0` might lead to weird behavior elsewhere, // but this should only be possible when using `-Z continue-parse-after-error` like // `compile-fail/issue-36638.rs`. - self.name == keywords::SelfUpper.name().as_str() && self.index == 0 + self.name.as_symbol() == keywords::SelfUpper.name() && self.index == 0 } } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index 4ced31593b1a..452293ac4ea8 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -60,8 +60,8 @@ impl RegionName { } #[allow(dead_code)] - crate fn name(&self) -> &InternedString { - &self.name + crate fn name(&self) -> InternedString { + self.name } crate fn highlight_region_name( @@ -206,7 +206,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { match error_region { ty::ReEarlyBound(ebr) => { if ebr.has_name() { - let span = self.get_named_span(tcx, error_region, &ebr.name); + let span = self.get_named_span(tcx, error_region, ebr.name); Some(RegionName { name: ebr.name, source: RegionNameSource::NamedEarlyBoundRegion(span) @@ -223,7 +223,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { ty::ReFree(free_region) => match free_region.bound_region { ty::BoundRegion::BrNamed(_, name) => { - let span = self.get_named_span(tcx, error_region, &name); + let span = self.get_named_span(tcx, error_region, name); Some(RegionName { name, source: RegionNameSource::NamedFreeRegion(span), @@ -306,7 +306,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { &self, tcx: TyCtxt<'_, '_, 'tcx>, error_region: &RegionKind, - name: &InternedString, + name: InternedString, ) -> Span { let scope = error_region.free_region_binding_scope(tcx); let node = tcx.hir().as_local_hir_id(scope).unwrap_or(hir::DUMMY_HIR_ID); From 257eaf523f7faabfc9845a238ec3776fc45fcd81 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 14 May 2019 14:55:15 +1000 Subject: [PATCH 0154/3207] Introduce `InternedString::intern`. `InternedString::intern(x)` is preferable to `Symbol::intern(x).as_interned_str()`, because the former involves one call to `with_interner` while the latter involves two. The case within InternedString::decode() is particularly hot, and this change reduces the number of `with_interner` calls by up to 13%. --- src/librustc/mir/mono.rs | 6 +-- src/librustc/traits/object_safety.rs | 5 ++- src/librustc/traits/structural_impls.rs | 14 ++---- src/librustc/ty/mod.rs | 2 +- src/librustc/ty/print/pretty.rs | 12 +++--- src/librustc/ty/query/values.rs | 4 +- src/librustc_codegen_utils/symbol_names.rs | 12 +++--- .../error_reporting/region_name.rs | 3 +- src/librustc_mir/monomorphize/item.rs | 4 +- src/librustc_mir/transform/check_unsafety.rs | 43 ++++++++----------- src/librustc_typeck/check/intrinsic.rs | 6 +-- src/librustc_typeck/collect.rs | 6 +-- src/libsyntax_pos/symbol.rs | 9 +++- 13 files changed, 60 insertions(+), 66 deletions(-) diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs index e82e90ede8c1..a26468b0fb6c 100644 --- a/src/librustc/mir/mono.rs +++ b/src/librustc/mir/mono.rs @@ -1,6 +1,6 @@ use crate::hir::def_id::{DefId, CrateNum, LOCAL_CRATE}; use crate::hir::HirId; -use syntax::symbol::{Symbol, InternedString}; +use syntax::symbol::InternedString; use crate::ty::{Instance, TyCtxt}; use crate::util::nodemap::FxHashMap; use rustc_data_structures::base_n; @@ -280,7 +280,7 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> CodegenUnitNameBuilder<'a, 'gcx, 'tcx> { cgu_name } else { let cgu_name = &cgu_name.as_str()[..]; - Symbol::intern(&CodegenUnit::mangle_name(cgu_name)).as_interned_str() + InternedString::intern(&CodegenUnit::mangle_name(cgu_name)) } } @@ -336,6 +336,6 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> CodegenUnitNameBuilder<'a, 'gcx, 'tcx> { write!(cgu_name, ".{}", special_suffix).unwrap(); } - Symbol::intern(&cgu_name[..]).as_interned_str() + InternedString::intern(&cgu_name[..]) } } diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 1c8ea5c7b9c5..55216f644a18 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -18,7 +18,8 @@ use crate::ty::{self, Ty, TyCtxt, TypeFoldable, Predicate, ToPredicate}; use crate::ty::subst::{Subst, InternalSubsts}; use std::borrow::Cow; use std::iter::{self}; -use syntax::ast::{self, Name}; +use syntax::ast::{self}; +use syntax::symbol::InternedString; use syntax_pos::Span; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] @@ -539,7 +540,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { // are implemented let unsized_self_ty: Ty<'tcx> = self.mk_ty_param( ::std::u32::MAX, - Name::intern("RustaceansAreAwesome").as_interned_str(), + InternedString::intern("RustaceansAreAwesome"), ); // `Receiver[Self => U]` diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 400a0f526c4e..404fadbc78af 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -312,17 +312,15 @@ impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector { } fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { - use syntax::symbol::Symbol; - match t.sty { ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => { self.types.insert( bound_ty.var.as_u32(), match bound_ty.kind { ty::BoundTyKind::Param(name) => name, - ty::BoundTyKind::Anon => Symbol::intern( - &format!("^{}", bound_ty.var.as_u32()) - ).as_interned_str(), + ty::BoundTyKind::Anon => + InternedString::intern(&format!("^{}", bound_ty.var.as_u32()), + ), } ); } @@ -334,8 +332,6 @@ impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector { } fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { - use syntax::symbol::Symbol; - match r { ty::ReLateBound(index, br) if *index == self.binder_index => { match br { @@ -344,9 +340,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector { } ty::BoundRegion::BrAnon(var) => { - self.regions.insert(Symbol::intern( - &format!("'^{}", var) - ).as_interned_str()); + self.regions.insert(InternedString::intern(&format!("'^{}", var))); } _ => (), diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 2f71861d4dc0..e1c432d5b6da 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -3405,7 +3405,7 @@ impl_stable_hash_for!(struct self::SymbolName { impl SymbolName { pub fn new(name: &str) -> SymbolName { SymbolName { - name: Symbol::intern(name).as_interned_str() + name: InternedString::intern(name) } } diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 8e98d4d85b9c..91b708d7dbe1 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -7,10 +7,8 @@ use crate::middle::region; use crate::ty::{self, DefIdTree, ParamConst, Ty, TyCtxt, TypeFoldable}; use crate::ty::subst::{Kind, Subst, UnpackedKind}; use crate::mir::interpret::ConstValue; -use syntax::symbol::{keywords, Symbol}; - use rustc_target::spec::abi::Abi; -use syntax::symbol::InternedString; +use syntax::symbol::{keywords, InternedString}; use std::cell::Cell; use std::fmt::{self, Write as _}; @@ -1285,10 +1283,10 @@ impl FmtPrinter<'_, 'gcx, 'tcx, F> { { fn name_by_region_index(index: usize) -> InternedString { match index { - 0 => Symbol::intern("'r"), - 1 => Symbol::intern("'s"), - i => Symbol::intern(&format!("'t{}", i-2)), - }.as_interned_str() + 0 => InternedString::intern("'r"), + 1 => InternedString::intern("'s"), + i => InternedString::intern(&format!("'t{}", i-2)), + } } // Replace any anonymous late-bound regions with named diff --git a/src/librustc/ty/query/values.rs b/src/librustc/ty/query/values.rs index a4b8d365a12e..2fb318a47bef 100644 --- a/src/librustc/ty/query/values.rs +++ b/src/librustc/ty/query/values.rs @@ -1,7 +1,7 @@ use crate::ty::{self, Ty, TyCtxt, AdtSizedConstraint}; use crate::ty::util::NeedsDrop; -use syntax::symbol::Symbol; +use syntax::symbol::InternedString; pub(super) trait Value<'tcx>: Sized { fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self; @@ -28,7 +28,7 @@ impl<'tcx> Value<'tcx> for Ty<'tcx> { impl<'tcx> Value<'tcx> for ty::SymbolName { fn from_cycle_error<'a>(_: TyCtxt<'a, 'tcx, 'tcx>) -> Self { - ty::SymbolName { name: Symbol::intern("").as_interned_str() } + ty::SymbolName { name: InternedString::intern("") } } } diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index d50a9a1607b2..6915687ceba9 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -101,7 +101,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_mir::monomorphize::item::{InstantiationMode, MonoItem, MonoItemExt}; use rustc_mir::monomorphize::Instance; -use syntax_pos::symbol::{Symbol, InternedString}; +use syntax_pos::symbol::InternedString; use log::debug; @@ -238,13 +238,13 @@ fn compute_symbol_name(tcx: TyCtxt<'_, 'tcx, 'tcx>, instance: Instance<'tcx>) -> if def_id.is_local() { if tcx.plugin_registrar_fn(LOCAL_CRATE) == Some(def_id) { let disambiguator = tcx.sess.local_crate_disambiguator(); - return Symbol::intern(&tcx.sess.generate_plugin_registrar_symbol(disambiguator)) - .as_interned_str(); + return + InternedString::intern(&tcx.sess.generate_plugin_registrar_symbol(disambiguator)); } if tcx.proc_macro_decls_static(LOCAL_CRATE) == Some(def_id) { let disambiguator = tcx.sess.local_crate_disambiguator(); - return Symbol::intern(&tcx.sess.generate_proc_macro_decls_symbol(disambiguator)) - .as_interned_str(); + return + InternedString::intern(&tcx.sess.generate_proc_macro_decls_symbol(disambiguator)); } } @@ -322,7 +322,7 @@ fn compute_symbol_name(tcx: TyCtxt<'_, 'tcx, 'tcx>, instance: Instance<'tcx>) -> let _ = printer.write_str("{{vtable-shim}}"); } - Symbol::intern(&printer.path.finish(hash)).as_interned_str() + InternedString::intern(&printer.path.finish(hash)) } // Follow C++ namespace-mangling style, see diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index 452293ac4ea8..4d8acd241acd 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -12,7 +12,6 @@ use rustc::ty::subst::{SubstsRef, UnpackedKind}; use rustc::ty::{self, RegionKind, RegionVid, Ty, TyCtxt}; use rustc::ty::print::RegionHighlightMode; use rustc_errors::DiagnosticBuilder; -use syntax::ast::Name; use syntax::symbol::keywords; use syntax_pos::Span; use syntax_pos::symbol::InternedString; @@ -791,6 +790,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { let c = *counter; *counter += 1; - Name::intern(&format!("'{:?}", c)).as_interned_str() + InternedString::intern(&format!("'{:?}", c)) } } diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index 999e7402afd9..6b40245d39a8 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -10,7 +10,7 @@ use syntax::attr::InlineAttr; use std::fmt::{self, Write}; use std::iter; use rustc::mir::mono::Linkage; -use syntax_pos::symbol::Symbol; +use syntax_pos::symbol::InternedString; use syntax::source_map::Span; pub use rustc::mir::mono::MonoItem; @@ -61,7 +61,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug { MonoItem::GlobalAsm(hir_id) => { let def_id = tcx.hir().local_def_id_from_hir_id(hir_id); ty::SymbolName { - name: Symbol::intern(&format!("global_asm_{:?}", def_id)).as_interned_str() + name: InternedString::intern(&format!("global_asm_{:?}", def_id)) } } } diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index fab07a2290eb..394d1f06029c 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -12,7 +12,7 @@ use rustc::lint::builtin::{SAFE_EXTERN_STATICS, SAFE_PACKED_BORROWS, UNUSED_UNSA use rustc::mir::*; use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext}; -use syntax::symbol::{Symbol, sym}; +use syntax::symbol::{InternedString, sym}; use std::ops::Bound; @@ -167,9 +167,9 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { (CastTy::FnPtr, CastTy::Int(_)) => { self.register_violations(&[UnsafetyViolation { source_info: self.source_info, - description: Symbol::intern("cast of pointer to int").as_interned_str(), - details: Symbol::intern("casting pointers to integers in constants") - .as_interned_str(), + description: InternedString::intern("cast of pointer to int"), + details: InternedString::intern( + "casting pointers to integers in constants"), kind: UnsafetyViolationKind::General, }], &[]); }, @@ -185,9 +185,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.mir, self.tcx).sty { self.register_violations(&[UnsafetyViolation { source_info: self.source_info, - description: Symbol::intern("pointer operation").as_interned_str(), - details: Symbol::intern("operations on pointers in constants") - .as_interned_str(), + description: InternedString::intern("pointer operation"), + details: InternedString::intern("operations on pointers in constants"), kind: UnsafetyViolationKind::General, }], &[]); } @@ -212,13 +211,11 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { self.source_scope_local_data[source_info.scope].lint_root; self.register_violations(&[UnsafetyViolation { source_info, - description: Symbol::intern("borrow of packed field").as_interned_str(), - details: - Symbol::intern("fields of packed structs might be misaligned: \ - dereferencing a misaligned pointer or even just \ - creating a misaligned reference is undefined \ - behavior") - .as_interned_str(), + description: InternedString::intern("borrow of packed field"), + details: InternedString::intern( + "fields of packed structs might be misaligned: dereferencing a \ + misaligned pointer or even just creating a misaligned reference \ + is undefined behavior"), kind: UnsafetyViolationKind::BorrowPacked(lint_root) }], &[]); } @@ -315,12 +312,10 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { self.source_scope_local_data[source_info.scope].lint_root; self.register_violations(&[UnsafetyViolation { source_info, - description: Symbol::intern("use of extern static").as_interned_str(), - details: - Symbol::intern("extern statics are not controlled by the Rust type \ - system: invalid data, aliasing violations or data \ - races will cause undefined behavior") - .as_interned_str(), + description: InternedString::intern("use of extern static"), + details: InternedString::intern( + "extern statics are not controlled by the Rust type system: invalid \ + data, aliasing violations or data races will cause undefined behavior"), kind: UnsafetyViolationKind::ExternStatic(lint_root) }], &[]); } @@ -340,8 +335,8 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { let source_info = self.source_info; self.register_violations(&[UnsafetyViolation { source_info, - description: Symbol::intern(description).as_interned_str(), - details: Symbol::intern(details).as_interned_str(), + description: InternedString::intern(description), + details: InternedString::intern(details), kind, }], &[]); } @@ -441,8 +436,8 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { let source_info = self.source_info; self.register_violations(&[UnsafetyViolation { source_info, - description: Symbol::intern(description).as_interned_str(), - details: Symbol::intern(details).as_interned_str(), + description: InternedString::intern(description), + details: InternedString::intern(details), kind: UnsafetyViolationKind::GeneralAndConstFn, }], &[]); } diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 40c60caffa42..c6191e6b579c 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -7,7 +7,7 @@ use rustc::ty::subst::Subst; use crate::require_same_types; use rustc_target::spec::abi::Abi; -use syntax::symbol::Symbol; +use syntax::symbol::InternedString; use rustc::hir; @@ -80,7 +80,7 @@ pub fn intrisic_operation_unsafety(intrinsic: &str) -> hir::Unsafety { /// and in libcore/intrinsics.rs pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::ForeignItem) { - let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)).as_interned_str()); + let param = |n| tcx.mk_ty_param(n, InternedString::intern(&format!("P{}", n))); let name = it.ident.as_str(); let mk_va_list_ty = || { @@ -397,7 +397,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::ForeignItem) { let param = |n| { - let name = Symbol::intern(&format!("P{}", n)).as_interned_str(); + let name = InternedString::intern(&format!("P{}", n)); tcx.mk_ty_param(n, name) }; diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 6527e8655b5e..711d79f95f53 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -39,7 +39,7 @@ use syntax::ast::{Ident, MetaItemKind}; use syntax::attr::{InlineAttr, OptimizeAttr, list_contains_name, mark_used}; use syntax::source_map::Spanned; use syntax::feature_gate; -use syntax::symbol::{keywords, Symbol, sym}; +use syntax::symbol::{InternedString, keywords, Symbol, sym}; use syntax_pos::{Span, DUMMY_SP}; use rustc::hir::def::{CtorKind, Res, DefKind}; @@ -1082,7 +1082,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty .enumerate() .map(|(i, &arg)| ty::GenericParamDef { index: type_start + i as u32, - name: Symbol::intern(arg).as_interned_str(), + name: InternedString::intern(arg), def_id, pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { @@ -1097,7 +1097,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty params.extend(upvars.iter().zip((dummy_args.len() as u32)..).map(|(_, i)| { ty::GenericParamDef { index: type_start + i, - name: Symbol::intern("").as_interned_str(), + name: InternedString::intern(""), def_id, pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 01b126f48b32..e0425220c3fd 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -1134,6 +1134,13 @@ pub struct InternedString { } impl InternedString { + /// Maps a string to its interned representation. + pub fn intern(string: &str) -> Self { + InternedString { + symbol: Symbol::intern(string) + } + } + pub fn with R, R>(self, f: F) -> R { let str = with_interner(|interner| { interner.get(self.symbol) as *const str @@ -1236,7 +1243,7 @@ impl fmt::Display for InternedString { impl Decodable for InternedString { fn decode(d: &mut D) -> Result { - Ok(Symbol::intern(&d.read_str()?).as_interned_str()) + Ok(InternedString::intern(&d.read_str()?)) } } From c06cdbeac55ec87181d015d2ef759349521773ea Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 14 May 2019 15:13:42 +1000 Subject: [PATCH 0155/3207] Introduce `LocalInternedString::intern`. `LocalInternedString::intern(x)` is preferable to `Symbol::intern(x).as_str()`, because the former involves one call to `with_interner` while the latter involves two. --- src/librustc/lint/context.rs | 9 +++++---- src/librustc_codegen_llvm/intrinsic.rs | 4 ++-- src/librustc_codegen_ssa/mir/block.rs | 10 +++++----- src/libsyntax_pos/symbol.rs | 13 ++++++++++++- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index e713cf8d8055..7e1e751e8564 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -828,8 +828,8 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> { // This shouldn't ever be needed, but just in case: Ok(vec![match trait_ref { - Some(trait_ref) => Symbol::intern(&format!("{:?}", trait_ref)).as_str(), - None => Symbol::intern(&format!("<{}>", self_ty)).as_str(), + Some(trait_ref) => LocalInternedString::intern(&format!("{:?}", trait_ref)), + None => LocalInternedString::intern(&format!("<{}>", self_ty)), }]) } @@ -845,9 +845,10 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> { // This shouldn't ever be needed, but just in case: path.push(match trait_ref { Some(trait_ref) => { - Symbol::intern(&format!("", trait_ref, self_ty)).as_str() + LocalInternedString::intern(&format!("", trait_ref, + self_ty)) }, - None => Symbol::intern(&format!("", self_ty)).as_str(), + None => LocalInternedString::intern(&format!("", self_ty)), }); Ok(path) diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index ceb08f943678..9ae0e26196d9 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -20,7 +20,7 @@ use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, Primitive}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc::hir; use syntax::ast::{self, FloatTy}; -use syntax::symbol::Symbol; +use syntax::symbol::LocalInternedString; use rustc_codegen_ssa::traits::*; @@ -213,7 +213,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { } "type_name" => { let tp_ty = substs.type_at(0); - let ty_name = Symbol::intern(&tp_ty.to_string()).as_str(); + let ty_name = LocalInternedString::intern(&tp_ty.to_string()); self.const_str_slice(ty_name) } "type_id" => { diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 96b8558c1d2c..c7dd019fc3eb 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -15,7 +15,7 @@ use crate::traits::*; use std::borrow::Cow; -use syntax::symbol::Symbol; +use syntax::symbol::LocalInternedString; use syntax_pos::Pos; use super::{FunctionCx, LocalRef}; @@ -401,7 +401,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Get the location information. let loc = bx.sess().source_map().lookup_char_pos(span.lo()); - let filename = Symbol::intern(&loc.file.name.to_string()).as_str(); + let filename = LocalInternedString::intern(&loc.file.name.to_string()); let line = bx.const_u32(loc.line as u32); let col = bx.const_u32(loc.col.to_usize() as u32 + 1); @@ -423,7 +423,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } _ => { let str = msg.description(); - let msg_str = Symbol::intern(str).as_str(); + let msg_str = LocalInternedString::intern(str); let msg_file_line_col = bx.static_panic_msg( Some(msg_str), filename, @@ -535,7 +535,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let layout = bx.layout_of(ty); if layout.abi.is_uninhabited() { let loc = bx.sess().source_map().lookup_char_pos(span.lo()); - let filename = Symbol::intern(&loc.file.name.to_string()).as_str(); + let filename = LocalInternedString::intern(&loc.file.name.to_string()); let line = bx.const_u32(loc.line as u32); let col = bx.const_u32(loc.col.to_usize() as u32 + 1); @@ -543,7 +543,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { "Attempted to instantiate uninhabited type {}", ty ); - let msg_str = Symbol::intern(&str).as_str(); + let msg_str = LocalInternedString::intern(&str); let msg_file_line_col = bx.static_panic_msg( Some(msg_str), filename, diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index e0425220c3fd..043238789345 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -1029,6 +1029,17 @@ pub struct LocalInternedString { } impl LocalInternedString { + /// Maps a string to its interned representation. + pub fn intern(string: &str) -> Self { + let string = with_interner(|interner| { + let symbol = interner.intern(string); + interner.strings[symbol.0.as_usize()] + }); + LocalInternedString { + string: unsafe { std::mem::transmute::<&str, &str>(string) } + } + } + pub fn as_interned_str(self) -> InternedString { InternedString { symbol: Symbol::intern(self.string) @@ -1105,7 +1116,7 @@ impl fmt::Display for LocalInternedString { impl Decodable for LocalInternedString { fn decode(d: &mut D) -> Result { - Ok(Symbol::intern(&d.read_str()?).as_str()) + Ok(LocalInternedString::intern(&d.read_str()?)) } } From e33c4415b3a504bd723328a38bce0f14786db61b Mon Sep 17 00:00:00 2001 From: MaulingMonkey Date: Sun, 19 May 2019 17:10:48 -0700 Subject: [PATCH 0156/3207] Add basic CDB support to debuginfo compiletest s, to help catch `*.natvis` regressions, like those fixed in #60687. Several Microsoft debuggers (VS, VS Code, WinDbg, CDB, ...) consume the `*.natvis` files we embed into rust `*.pdb` files. While this only tests CDB, that test coverage should help for all of them. CHANGES src\bootstrap - test.rs: Run CDB debuginfo tests on MSVC targets src\test\debuginfo - issue-13213.rs: CDB has trouble with this, skip for now (newly discovered regression?) - pretty-std.rs: Was ignored, re-enable for CDB only to start with, add CDB tests. - should-fail.rs: Add CDB tests. src\tools\compiletest: - Added "-cdb" option - Added Mode::DebugInfoCdb ("debuginfo-cdb") - Added run_debuginfo_cdb_test[_no_opt] - Renamed Mode::DebugInfoBoth -> DebugInfoGdbLldb ("debuginfo-gdb+lldb") since it's no longer clear what "Both" means. - Find CDB at the default Win10 SDK install path "C:\Program Files (x86)\Windows Kits\10\Debugger\*\cdb.exe" - Ignore CDB tests if CDB not found. ISSUES - `compute_stamp_hash`: not sure if there's any point in hashing `%ProgramFiles(x86)%` - `OsString` lacks any `*.natvis` entries (would be nice to add in a followup changelist) - DSTs (array/string slices) which work in VS & VS Code fail in CDB. - I've avoided `Mode::DebugInfoAll` as 3 debuggers leads to pow(2,3)=8 possible combinations. REFERENCE CDB is not part of the base Visual Studio install, but can be added via the Windows 10 SDK: https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk Installing just "Debugging Tools for Windows" is sufficient. CDB appears to already be installed on appveyor CI, where this changelist can find it, based on it's use here: https://github.com/rust-lang/rust/blob/0ffc57311030a1930edfa721fe57d0000a063af4/appveyor.yml#L227 CDB commands and command line reference: https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-reference --- src/bootstrap/test.rs | 8 +- src/test/debuginfo/issue-13213.rs | 1 + src/test/debuginfo/pretty-std.rs | 53 ++++++++++++- src/test/debuginfo/should-fail.rs | 7 ++ src/tools/compiletest/src/common.rs | 16 +++- src/tools/compiletest/src/header.rs | 21 +++-- src/tools/compiletest/src/main.rs | 66 ++++++++++++++-- src/tools/compiletest/src/runtest.rs | 110 +++++++++++++++++++++++++-- 8 files changed, 251 insertions(+), 31 deletions(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 7826ac947180..40105e091173 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -976,14 +976,10 @@ impl Step for Compiletest { } if suite == "debuginfo" { - // Skip debuginfo tests on MSVC - if builder.config.build.contains("msvc") { - return; - } - + let msvc = builder.config.build.contains("msvc"); if mode == "debuginfo" { return builder.ensure(Compiletest { - mode: "debuginfo-both", + mode: if msvc { "debuginfo-cdb" } else { "debuginfo-gdb+lldb" }, ..self }); } diff --git a/src/test/debuginfo/issue-13213.rs b/src/test/debuginfo/issue-13213.rs index 3c9a365fd4f7..393478460d48 100644 --- a/src/test/debuginfo/issue-13213.rs +++ b/src/test/debuginfo/issue-13213.rs @@ -1,4 +1,5 @@ // min-lldb-version: 310 +// ignore-cdb: Fails with exit code 0xc0000135 ("the application failed to initialize properly") // aux-build:issue-13213-aux.rs diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs index 82802eff08ab..f568371d68a1 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -1,6 +1,5 @@ -// ignore-windows failing on win32 bot // ignore-freebsd: gdb package too new -// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 +// only-cdb // Test temporarily ignored on GDB/LLDB due to debuginfo tests being disabled, see PR 47155 // ignore-android: FIXME(#10381) // compile-flags:-g // min-gdb-version 7.7 @@ -63,6 +62,56 @@ // lldb-check:[...]$5 = None +// === CDB TESTS ================================================================================== + +// cdb-command: g + +// cdb-command: dx slice,d +// cdb-check:slice,d [...] +// NOTE: While slices have a .natvis entry that works in VS & VS Code, it fails in CDB 10.0.18362.1 + +// cdb-command: dx vec,d +// cdb-check:vec,d [...] : { size=4 } [Type: [...]::Vec] +// cdb-check: [size] : 4 [Type: [...]] +// cdb-check: [capacity] : [...] [Type: [...]] +// cdb-check: [0] : 4 [Type: unsigned __int64] +// cdb-check: [1] : 5 [Type: unsigned __int64] +// cdb-check: [2] : 6 [Type: unsigned __int64] +// cdb-check: [3] : 7 [Type: unsigned __int64] + +// cdb-command: dx str_slice +// cdb-check:str_slice [...] +// NOTE: While string slices have a .natvis entry that works in VS & VS Code, it fails in CDB 10.0.18362.1 + +// cdb-command: dx string +// cdb-check:string : "IAMA string!" [Type: [...]::String] +// cdb-check: [] [Type: [...]::String] +// cdb-check: [size] : 0xc [Type: [...]] +// cdb-check: [capacity] : 0xc [Type: [...]] +// cdb-check: [0] : 73 'I' [Type: char] +// cdb-check: [1] : 65 'A' [Type: char] +// cdb-check: [2] : 77 'M' [Type: char] +// cdb-check: [3] : 65 'A' [Type: char] +// cdb-check: [4] : 32 ' ' [Type: char] +// cdb-check: [5] : 115 's' [Type: char] +// cdb-check: [6] : 116 't' [Type: char] +// cdb-check: [7] : 114 'r' [Type: char] +// cdb-check: [8] : 105 'i' [Type: char] +// cdb-check: [9] : 110 'n' [Type: char] +// cdb-check: [10] : 103 'g' [Type: char] +// cdb-check: [11] : 33 '!' [Type: char] + +// cdb-command: dx os_string +// cdb-check:os_string [Type: [...]::OsString] +// NOTE: OsString doesn't have a .natvis entry yet. + +// cdb-command: dx some +// cdb-check:some : { Some 8 } [Type: [...]::Option] +// cdb-command: dx none +// cdb-check:none : { None } [Type: [...]::Option] +// cdb-command: dx some_string +// cdb-check:some_string : { Some "IAMA optional string!" } [Type: [...]::Option<[...]::String>] + #![allow(unused_variables)] use std::ffi::OsString; diff --git a/src/test/debuginfo/should-fail.rs b/src/test/debuginfo/should-fail.rs index 8765c018b102..1e0d22cbce40 100644 --- a/src/test/debuginfo/should-fail.rs +++ b/src/test/debuginfo/should-fail.rs @@ -18,6 +18,13 @@ // lldb-command:print x // lldb-check:[...]$0 = 5 +// === CDB TESTS ================================================================================== + +// cdb-command:g + +// cdb-command:dx x +// cdb-check:string [...] : 5 [Type: [...]] + fn main() { let x = 1; diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 4699dee1716a..722979c3c140 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -1,5 +1,6 @@ pub use self::Mode::*; +use std::ffi::OsString; use std::fmt; use std::path::{Path, PathBuf}; use std::str::FromStr; @@ -15,7 +16,8 @@ pub enum Mode { RunPass, RunPassValgrind, Pretty, - DebugInfoBoth, + DebugInfoCdb, + DebugInfoGdbLldb, DebugInfoGdb, DebugInfoLldb, Codegen, @@ -33,9 +35,10 @@ impl Mode { pub fn disambiguator(self) -> &'static str { // Run-pass and pretty run-pass tests could run concurrently, and if they do, // they need to keep their output segregated. Same is true for debuginfo tests that - // can be run both on gdb and lldb. + // can be run on cdb, gdb, and lldb. match self { Pretty => ".pretty", + DebugInfoCdb => ".cdb", DebugInfoGdb => ".gdb", DebugInfoLldb => ".lldb", _ => "", @@ -52,7 +55,8 @@ impl FromStr for Mode { "run-pass" => Ok(RunPass), "run-pass-valgrind" => Ok(RunPassValgrind), "pretty" => Ok(Pretty), - "debuginfo-both" => Ok(DebugInfoBoth), + "debuginfo-cdb" => Ok(DebugInfoCdb), + "debuginfo-gdb+lldb" => Ok(DebugInfoGdbLldb), "debuginfo-lldb" => Ok(DebugInfoLldb), "debuginfo-gdb" => Ok(DebugInfoGdb), "codegen" => Ok(Codegen), @@ -77,7 +81,8 @@ impl fmt::Display for Mode { RunPass => "run-pass", RunPassValgrind => "run-pass-valgrind", Pretty => "pretty", - DebugInfoBoth => "debuginfo-both", + DebugInfoCdb => "debuginfo-cdb", + DebugInfoGdbLldb => "debuginfo-gdb+lldb", DebugInfoGdb => "debuginfo-gdb", DebugInfoLldb => "debuginfo-lldb", Codegen => "codegen", @@ -198,6 +203,9 @@ pub struct Config { /// Host triple for the compiler being invoked pub host: String, + /// Path to / name of the Microsoft Console Debugger (CDB) executable + pub cdb: Option, + /// Path to / name of the GDB executable pub gdb: Option, diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index dbc477585cbf..ab5594f36050 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -57,9 +57,9 @@ enum ParsedNameDirective { NoMatch, /// Match. Match, - /// Mode was DebugInfoBoth and this matched gdb. + /// Mode was DebugInfoGdbLldb and this matched gdb. MatchGdb, - /// Mode was DebugInfoBoth and this matched lldb. + /// Mode was DebugInfoGdbLldb and this matched lldb. MatchLldb, } @@ -81,13 +81,17 @@ impl EarlyProps { revisions: vec![], }; - if config.mode == common::DebugInfoBoth { + if config.mode == common::DebugInfoGdbLldb { if config.lldb_python_dir.is_none() { props.ignore = props.ignore.no_lldb(); } if config.gdb_version.is_none() { props.ignore = props.ignore.no_gdb(); } + } else if config.mode == common::DebugInfoCdb { + if config.cdb.is_none() { + props.ignore = Ignore::Ignore; + } } let rustc_has_profiler_support = env::var_os("RUSTC_PROFILER_SUPPORT").is_some(); @@ -133,12 +137,12 @@ impl EarlyProps { } } - if (config.mode == common::DebugInfoGdb || config.mode == common::DebugInfoBoth) && + if (config.mode == common::DebugInfoGdb || config.mode == common::DebugInfoGdbLldb) && props.ignore.can_run_gdb() && ignore_gdb(config, ln) { props.ignore = props.ignore.no_gdb(); } - if (config.mode == common::DebugInfoLldb || config.mode == common::DebugInfoBoth) && + if (config.mode == common::DebugInfoLldb || config.mode == common::DebugInfoGdbLldb) && props.ignore.can_run_lldb() && ignore_lldb(config, ln) { props.ignore = props.ignore.no_lldb(); } @@ -804,7 +808,7 @@ impl Config { ParsedNameDirective::Match } else { match self.mode { - common::DebugInfoBoth => { + common::DebugInfoGdbLldb => { if name == "gdb" { ParsedNameDirective::MatchGdb } else if name == "lldb" { @@ -813,6 +817,11 @@ impl Config { ParsedNameDirective::NoMatch } }, + common::DebugInfoCdb => if name == "cdb" { + ParsedNameDirective::Match + } else { + ParsedNameDirective::NoMatch + }, common::DebugInfoGdb => if name == "gdb" { ParsedNameDirective::Match } else { diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 442e58bfd74e..631ed067c341 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -1,5 +1,6 @@ #![crate_name = "compiletest"] #![feature(test)] +#![feature(path_buf_capacity)] #![feature(vec_remove_item)] #![deny(warnings, rust_2018_idioms)] @@ -8,7 +9,7 @@ extern crate test; use crate::common::CompareMode; use crate::common::{expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS}; use crate::common::{Config, TestPaths}; -use crate::common::{DebugInfoBoth, DebugInfoGdb, DebugInfoLldb, Mode, Pretty}; +use crate::common::{DebugInfoCdb, DebugInfoGdbLldb, DebugInfoGdb, DebugInfoLldb, Mode, Pretty}; use getopts::Options; use std::env; use std::ffi::OsString; @@ -164,6 +165,12 @@ pub fn parse_config(args: Vec) -> Config { .optopt("", "logfile", "file to log test execution to", "FILE") .optopt("", "target", "the target to build for", "TARGET") .optopt("", "host", "the host to build for", "HOST") + .optopt( + "", + "cdb", + "path to CDB to use for CDB debuginfo tests", + "PATH", + ) .optopt( "", "gdb", @@ -273,6 +280,7 @@ pub fn parse_config(args: Vec) -> Config { let target = opt_str2(matches.opt_str("target")); let android_cross_path = opt_path(matches, "android-cross-path"); + let cdb = analyze_cdb(matches.opt_str("cdb"), &target); let (gdb, gdb_version, gdb_native_rust) = analyze_gdb(matches.opt_str("gdb"), &target, &android_cross_path); let (lldb_version, lldb_native_rust) = extract_lldb_version(matches.opt_str("lldb-version")); @@ -319,6 +327,7 @@ pub fn parse_config(args: Vec) -> Config { target_rustcflags: matches.opt_str("target-rustcflags"), target: target, host: opt_str2(matches.opt_str("host")), + cdb, gdb, gdb_version, gdb_native_rust, @@ -421,7 +430,7 @@ pub fn opt_str2(maybestr: Option) -> String { pub fn run_tests(config: &Config) { if config.target.contains("android") { - if config.mode == DebugInfoGdb || config.mode == DebugInfoBoth { + if config.mode == DebugInfoGdb || config.mode == DebugInfoGdbLldb { println!( "{} debug-info test uses tcp 5039 port.\ please reserve it", @@ -440,8 +449,8 @@ pub fn run_tests(config: &Config) { match config.mode { // Note that we don't need to emit the gdb warning when - // DebugInfoBoth, so it is ok to list that here. - DebugInfoBoth | DebugInfoLldb => { + // DebugInfoGdbLldb, so it is ok to list that here. + DebugInfoGdbLldb | DebugInfoLldb => { if let Some(lldb_version) = config.lldb_version.as_ref() { if is_blacklisted_lldb_version(&lldb_version[..]) { println!( @@ -470,7 +479,8 @@ pub fn run_tests(config: &Config) { return; } } - _ => { /* proceed */ } + + DebugInfoCdb | _ => { /* proceed */ } } // FIXME(#33435) Avoid spurious failures in codegen-units/partitioning tests. @@ -667,7 +677,7 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> Vec, ) -> test::TestFn { let mut config = config.clone(); - if config.mode == DebugInfoBoth { + if config.mode == DebugInfoGdbLldb { // If both gdb and lldb were ignored, then the test as a whole // would be ignored. if !ignore.can_run_gdb() { @@ -841,6 +851,48 @@ fn is_android_gdb_target(target: &String) -> bool { } } +/// Returns `true` if the given target is a MSVC target for the purpouses of CDB testing. +fn is_pc_windows_msvc_target(target: &String) -> bool { + target.ends_with("-pc-windows-msvc") +} + +fn find_cdb(target: &String) -> Option { + if cfg!(windows) && is_pc_windows_msvc_target(target) { + let pf86 = env::var_os("ProgramFiles(x86)").or(env::var_os("ProgramFiles"))?; + let cdb_arch = if cfg!(target_arch="x86") { + "x86" + } else if cfg!(target_arch="x86_64") { + "x64" + } else if cfg!(target_arch="aarch64") { + "arm64" + } else if cfg!(target_arch="arm") { + "arm" + } else { + return None; // No compatible CDB.exe in the Windows 10 SDK + }; + + let mut path = PathBuf::with_capacity(64); + path.push(pf86); + path.push(r"Windows Kits\10\Debuggers"); // We could check more known install locations (8.1?) + path.push(cdb_arch); + path.push(r"cdb.exe"); + + if path.exists() { + Some(path.into_os_string()) + } else { + None + } + } + else { + None + } +} + +/// Returns Path to CDB +fn analyze_cdb(cdb: Option, target: &String) -> Option { + cdb.map(|s| OsString::from(s)).or(find_cdb(target)) +} + /// Returns (Path to GDB, GDB Version, GDB has Rust Support) fn analyze_gdb(gdb: Option, target: &String, android_cross_path: &PathBuf) -> (Option, Option, bool) { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 2082de7cbce3..c0dedccdff8a 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -3,7 +3,7 @@ use crate::common::CompareMode; use crate::common::{expected_output_path, UI_EXTENSIONS, UI_FIXED, UI_STDERR, UI_STDOUT}; use crate::common::{output_base_dir, output_base_name, output_testname_unique}; -use crate::common::{Codegen, CodegenUnits, DebugInfoBoth, DebugInfoGdb, DebugInfoLldb, Rustdoc}; +use crate::common::{Codegen, CodegenUnits, DebugInfoCdb, DebugInfoGdbLldb, DebugInfoGdb, DebugInfoLldb, Rustdoc}; use crate::common::{CompileFail, Pretty, RunFail, RunPass, RunPassValgrind}; use crate::common::{Config, TestPaths}; use crate::common::{Incremental, MirOpt, RunMake, Ui, JsDocTest, Assembly}; @@ -242,7 +242,15 @@ pub fn compute_stamp_hash(config: &Config) -> String { let mut hash = DefaultHasher::new(); config.stage_id.hash(&mut hash); - if config.mode == DebugInfoGdb || config.mode == DebugInfoBoth { + if config.mode == DebugInfoCdb { + match config.cdb { + None => env::var_os("ProgramFiles(x86)").hash(&mut hash), + Some(ref s) if s.is_empty() => env::var_os("ProgramFiles(x86)").hash(&mut hash), + Some(ref s) => s.hash(&mut hash), + } + } + + if config.mode == DebugInfoGdb || config.mode == DebugInfoGdbLldb { match config.gdb { None => env::var_os("PATH").hash(&mut hash), Some(ref s) if s.is_empty() => env::var_os("PATH").hash(&mut hash), @@ -250,7 +258,7 @@ pub fn compute_stamp_hash(config: &Config) -> String { }; } - if config.mode == DebugInfoLldb || config.mode == DebugInfoBoth { + if config.mode == DebugInfoLldb || config.mode == DebugInfoGdbLldb { env::var_os("PATH").hash(&mut hash); env::var_os("PYTHONPATH").hash(&mut hash); } @@ -285,10 +293,11 @@ impl<'test> TestCx<'test> { RunFail => self.run_rfail_test(), RunPassValgrind => self.run_valgrind_test(), Pretty => self.run_pretty_test(), - DebugInfoBoth => { + DebugInfoGdbLldb => { self.run_debuginfo_gdb_test(); self.run_debuginfo_lldb_test(); }, + DebugInfoCdb => self.run_debuginfo_cdb_test(), DebugInfoGdb => self.run_debuginfo_gdb_test(), DebugInfoLldb => self.run_debuginfo_lldb_test(), Codegen => self.run_codegen_test(), @@ -656,6 +665,95 @@ impl<'test> TestCx<'test> { self.compose_and_run_compiler(rustc, Some(src)) } + fn run_debuginfo_cdb_test(&self) { + assert!(self.revision.is_none(), "revisions not relevant here"); + + let config = Config { + target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags), + host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags), + mode: DebugInfoCdb, + ..self.config.clone() + }; + + let test_cx = TestCx { + config: &config, + ..*self + }; + + test_cx.run_debuginfo_cdb_test_no_opt(); + } + + fn run_debuginfo_cdb_test_no_opt(&self) { + // compile test file (it should have 'compile-flags:-g' in the header) + let compile_result = self.compile_test(); + if !compile_result.status.success() { + self.fatal_proc_rec("compilation failed!", &compile_result); + } + + let exe_file = self.make_exe_name(); + + let prefixes = { + static PREFIXES: &'static [&'static str] = &["cdb", "cdbg"]; + // No "native rust support" variation for CDB yet. + PREFIXES + }; + + // Parse debugger commands etc from test files + let DebuggerCommands { + commands, + check_lines, + breakpoint_lines, + .. + } = self.parse_debugger_commands(prefixes); + + // https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-commands + let mut script_str = String::with_capacity(2048); + script_str.push_str("version\n"); // List CDB (and more) version info in test output + script_str.push_str(".nvlist\n"); // List loaded `*.natvis` files (bulk of MSVC debugger customizations) + + // Set breakpoints on every line that contains the string "#break" + let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy(); + for line in &breakpoint_lines { + script_str.push_str(&format!( + "bp `{}:{}`\n", + source_file_name, line + )); + } + + // Append the other `cdb-command:`s + for line in &commands { + script_str.push_str(line); + script_str.push_str("\n"); + } + + script_str.push_str("\nqq\n"); // Quit the debugger (including remote debugger, if any) + + // Write the script into a file + debug!("script_str = {}", script_str); + self.dump_output_file(&script_str, "debugger.script"); + let debugger_script = self.make_out_name("debugger.script"); + + let cdb_path = &self.config.cdb.as_ref().unwrap(); + let mut cdb = Command::new(cdb_path); + cdb + .arg("-lines") // Enable source line debugging. + .arg("-cf").arg(&debugger_script) + .arg(&exe_file); + + let debugger_run_result = self.compose_and_run( + cdb, + self.config.run_lib_path.to_str().unwrap(), + None, // aux_path + None // input + ); + + if !debugger_run_result.status.success() { + self.fatal_proc_rec("Error while running CDB", &debugger_run_result); + } + + self.check_debugger_output(&debugger_run_result, &check_lines); + } + fn run_debuginfo_gdb_test(&self) { assert!(self.revision.is_none(), "revisions not relevant here"); @@ -1429,7 +1527,7 @@ impl<'test> TestCx<'test> { RunPass | Ui => self.should_run_successfully(), Incremental => self.revision.unwrap().starts_with("r"), RunFail | RunPassValgrind | MirOpt | - DebugInfoBoth | DebugInfoGdb | DebugInfoLldb => true, + DebugInfoCdb | DebugInfoGdbLldb | DebugInfoGdb | DebugInfoLldb => true, _ => false, }; let output_file = if will_execute { @@ -1870,7 +1968,7 @@ impl<'test> TestCx<'test> { rustc.arg(dir_opt); } - RunFail | RunPassValgrind | Pretty | DebugInfoBoth | DebugInfoGdb | DebugInfoLldb + RunFail | RunPassValgrind | Pretty | DebugInfoCdb | DebugInfoGdbLldb | DebugInfoGdb | DebugInfoLldb | Codegen | Rustdoc | RunMake | CodegenUnits | JsDocTest | Assembly => { // do not use JSON output } From f6637f3fcc01d7efe9a2e00f62d35a7e68ae892d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 17 May 2019 09:35:26 +1000 Subject: [PATCH 0157/3207] Move `is_gensymed` from `Symbol` to `Ident`. Note that the `is_gensymed` call on `primitive_types` is unnecessary because that table only contains the name of primitive types (e.g. `i32`) and never contains gensyms. --- src/librustc_resolve/lib.rs | 7 +++---- src/librustc_resolve/resolve_imports.rs | 2 +- src/libsyntax/ast.rs | 6 +----- src/libsyntax_pos/symbol.rs | 10 +++++----- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 77e8cc3272cc..c4a4dd306055 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -4225,7 +4225,7 @@ impl<'a> Resolver<'a> { let add_module_candidates = |module: Module<'_>, names: &mut Vec| { for (&(ident, _), resolution) in module.resolutions.borrow().iter() { if let Some(binding) = resolution.borrow().binding { - if !ident.name.is_gensymed() && filter_fn(binding.res()) { + if !ident.is_gensymed() && filter_fn(binding.res()) { names.push(TypoSuggestion { candidate: ident.name, article: binding.res().article(), @@ -4243,7 +4243,7 @@ impl<'a> Resolver<'a> { for rib in self.ribs[ns].iter().rev() { // Locals and type parameters for (ident, &res) in &rib.bindings { - if !ident.name.is_gensymed() && filter_fn(res) { + if !ident.is_gensymed() && filter_fn(res) { names.push(TypoSuggestion { candidate: ident.name, article: res.article(), @@ -4273,7 +4273,7 @@ impl<'a> Resolver<'a> { }, ); - if !ident.name.is_gensymed() && filter_fn(crate_mod) { + if !ident.is_gensymed() && filter_fn(crate_mod) { Some(TypoSuggestion { candidate: ident.name, article: "a", @@ -4298,7 +4298,6 @@ impl<'a> Resolver<'a> { names.extend( self.primitive_type_table.primitive_types .iter() - .filter(|(name, _)| !name.is_gensymed()) .map(|(name, _)| { TypoSuggestion { candidate: *name, diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 4058f0bce0f9..3a6a8b56ff35 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -1395,7 +1395,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { // so they can cause name conflict errors downstream. let is_good_import = binding.is_import() && !binding.is_ambiguity() && // Note that as_str() de-gensyms the Symbol - !(ident.name.is_gensymed() && ident.name.as_str() != "_"); + !(ident.is_gensymed() && ident.name.as_str() != "_"); if is_good_import || binding.is_macro_def() { let res = binding.res(); if res != Res::Err { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d12240655e62..88c22085bc4d 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -72,11 +72,7 @@ pub struct Path { impl PartialEq for Path { fn eq(&self, symbol: &Symbol) -> bool { self.segments.len() == 1 && { - let name = self.segments[0].ident.name; - // Make sure these symbols are pure strings - debug_assert!(!symbol.is_gensymed()); - debug_assert!(!name.is_gensymed()); - name == *symbol + self.segments[0].ident.name == *symbol } } } diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 97b22282668a..3cd5577e19e4 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -684,6 +684,11 @@ impl Ident { if self.name == keywords::Underscore.name() { self.gensym() } else { self } } + // WARNING: this function is deprecated and will be removed in the future. + pub fn is_gensymed(self) -> bool { + with_interner(|interner| interner.is_gensymed(self.name)) + } + pub fn as_str(self) -> LocalInternedString { self.name.as_str() } @@ -786,11 +791,6 @@ impl Symbol { with_interner(|interner| interner.gensymed(self)) } - // WARNING: this function is deprecated and will be removed in the future. - pub fn is_gensymed(self) -> bool { - with_interner(|interner| interner.is_gensymed(self)) - } - pub fn as_str(self) -> LocalInternedString { with_interner(|interner| unsafe { LocalInternedString { From e57c0dbeb72cf631930429a20badd41290bb0608 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 17 May 2019 10:27:17 +1000 Subject: [PATCH 0158/3207] Eliminate `Symbol::gensymed`. --- src/libsyntax/std_inject.rs | 13 ++++--------- src/libsyntax_ext/test.rs | 2 +- src/libsyntax_pos/symbol.rs | 7 ++----- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 6784a2abe551..fe8c9f03a2c6 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -63,18 +63,13 @@ pub fn maybe_inject_crates_ref( // .rev() to preserve ordering above in combination with insert(0, ...) let alt_std_name = alt_std_name.map(Symbol::intern); - for orig_name in names.iter().rev() { - let orig_name = Symbol::intern(orig_name); - let mut rename = orig_name; + for orig_name_str in names.iter().rev() { // HACK(eddyb) gensym the injected crates on the Rust 2018 edition, // so they don't accidentally interfere with the new import paths. - if rust_2018 { - rename = orig_name.gensymed(); - } - let orig_name = if rename != orig_name { - Some(orig_name) + let (rename, orig_name) = if rust_2018 { + (Symbol::gensym(orig_name_str), Some(Symbol::intern(orig_name_str))) } else { - None + (Symbol::intern(orig_name_str), None) }; krate.module.items.insert(0, P(ast::Item { attrs: vec![attr::mk_attr_outer( diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index 86ae6ab5fece..211a098022f9 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -127,7 +127,7 @@ pub fn expand_test_or_bench( ]) }; - let mut test_const = cx.item(sp, ast::Ident::new(item.ident.name.gensymed(), sp), + let mut test_const = cx.item(sp, ast::Ident::new(item.ident.name, sp).gensym(), vec![ // #[cfg(test)] cx.attribute(attr_sp, cx.meta_list(attr_sp, Symbol::intern("cfg"), vec![ diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 3cd5577e19e4..2bf3b1fa4657 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -677,7 +677,8 @@ impl Ident { } pub fn gensym(self) -> Ident { - Ident::new(self.name.gensymed(), self.span) + let name = with_interner(|interner| interner.gensymed(self.name)); + Ident::new(name, self.span) } pub fn gensym_if_underscore(self) -> Ident { @@ -787,10 +788,6 @@ impl Symbol { with_interner(|interner| interner.gensym(string)) } - pub fn gensymed(self) -> Self { - with_interner(|interner| interner.gensymed(self)) - } - pub fn as_str(self) -> LocalInternedString { with_interner(|interner| unsafe { LocalInternedString { From 88d29992bdd3d881b336b724675c59323e70e2e7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 17 May 2019 10:44:51 +1000 Subject: [PATCH 0159/3207] Remove `Symbol::gensym()`. --- src/librustc_allocator/expand.rs | 2 +- src/librustc_resolve/build_reduced_graph.rs | 2 +- src/libsyntax/diagnostics/plugin.rs | 6 +-- src/libsyntax/ext/tt/macro_rules.rs | 4 +- src/libsyntax/std_inject.rs | 10 ++-- src/libsyntax/test.rs | 13 ++--- src/libsyntax_ext/proc_macro_decls.rs | 2 +- src/libsyntax_pos/symbol.rs | 56 ++++++++++++--------- 8 files changed, 52 insertions(+), 43 deletions(-) diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs index 585c6fde6345..6931b3542f76 100644 --- a/src/librustc_allocator/expand.rs +++ b/src/librustc_allocator/expand.rs @@ -140,7 +140,7 @@ impl MutVisitor for ExpandAllocatorDirectives<'_> { // Generate the submodule itself let name = f.kind.fn_name("allocator_abi"); - let allocator_abi = Ident::with_empty_ctxt(Symbol::gensym(&name)); + let allocator_abi = Ident::from_str(&name).gensym(); let module = f.cx.item_mod(span, span, allocator_abi, Vec::new(), items); let module = f.cx.monotonic_expander().flat_map_item(module).pop().unwrap(); diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index f70ca6f859b9..3b58a99d19fe 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -314,7 +314,7 @@ impl<'a> Resolver<'a> { Ident::new(keywords::SelfLower.name(), new_span) ), kind: ast::UseTreeKind::Simple( - Some(Ident::new(Name::gensym("__dummy"), new_span)), + Some(Ident::from_str_and_span("__dummy", new_span).gensym()), ast::DUMMY_NODE_ID, ast::DUMMY_NODE_ID, ), diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index 21024eb41ef5..c988dc61bec4 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -7,7 +7,7 @@ use crate::ext::base::{ExtCtxt, MacEager, MacResult}; use crate::ext::build::AstBuilder; use crate::parse::token; use crate::ptr::P; -use crate::symbol::{keywords, Symbol}; +use crate::symbol::keywords; use crate::tokenstream::{TokenTree}; use smallvec::smallvec; @@ -121,13 +121,13 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt<'_>, let span = span.apply_mark(ecx.current_expansion.mark); - let sym = Ident::new(Symbol::gensym(&format!("__register_diagnostic_{}", code)), span); + let name = Ident::from_str_and_span(&format!("__register_diagnostic_{}", code), span).gensym(); MacEager::items(smallvec![ ecx.item_mod( span, span, - sym, + name, vec![], vec![], ) diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 06651750de74..672b7b428552 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -252,8 +252,8 @@ pub fn compile( def: &ast::Item, edition: Edition ) -> SyntaxExtension { - let lhs_nm = ast::Ident::with_empty_ctxt(Symbol::gensym("lhs")); - let rhs_nm = ast::Ident::with_empty_ctxt(Symbol::gensym("rhs")); + let lhs_nm = ast::Ident::from_str("lhs").gensym(); + let rhs_nm = ast::Ident::from_str("rhs").gensym(); // Parse the macro_rules! invocation let body = match def.node { diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index fe8c9f03a2c6..1be7986ad53c 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -2,7 +2,7 @@ use crate::ast; use crate::attr; use crate::edition::Edition; use crate::ext::hygiene::{Mark, SyntaxContext}; -use crate::symbol::{Symbol, keywords, sym}; +use crate::symbol::{Ident, Symbol, keywords, sym}; use crate::source_map::{ExpnInfo, MacroAttribute, dummy_spanned, hygiene, respan}; use crate::ptr::P; use crate::tokenstream::TokenStream; @@ -66,10 +66,12 @@ pub fn maybe_inject_crates_ref( for orig_name_str in names.iter().rev() { // HACK(eddyb) gensym the injected crates on the Rust 2018 edition, // so they don't accidentally interfere with the new import paths. + let orig_name_sym = Symbol::intern(orig_name_str); + let orig_name_ident = Ident::with_empty_ctxt(orig_name_sym); let (rename, orig_name) = if rust_2018 { - (Symbol::gensym(orig_name_str), Some(Symbol::intern(orig_name_str))) + (orig_name_ident.gensym(), Some(orig_name_sym)) } else { - (Symbol::intern(orig_name_str), None) + (orig_name_ident, None) }; krate.module.items.insert(0, P(ast::Item { attrs: vec![attr::mk_attr_outer( @@ -79,7 +81,7 @@ pub fn maybe_inject_crates_ref( )], vis: dummy_spanned(ast::VisibilityKind::Inherited), node: ast::ItemKind::ExternCrate(alt_std_name.or(orig_name)), - ident: ast::Ident::with_empty_ctxt(rename), + ident: rename, id: ast::DUMMY_NODE_ID, span: DUMMY_SP, tokens: None, diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 3fd0790161cd..3dc7aad94593 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -232,11 +232,11 @@ fn mk_reexport_mod(cx: &mut TestCtxt<'_>, items, }; - let sym = Ident::with_empty_ctxt(Symbol::gensym("__test_reexports")); + let name = Ident::from_str("__test_reexports").gensym(); let parent = if parent == ast::DUMMY_NODE_ID { ast::CRATE_NODE_ID } else { parent }; cx.ext_cx.current_expansion.mark = cx.ext_cx.resolver.get_module_scope(parent); let it = cx.ext_cx.monotonic_expander().flat_map_item(P(ast::Item { - ident: sym, + ident: name, attrs: Vec::new(), id: ast::DUMMY_NODE_ID, node: ast::ItemKind::Mod(reexport_mod), @@ -245,7 +245,7 @@ fn mk_reexport_mod(cx: &mut TestCtxt<'_>, tokens: None, })).pop().unwrap(); - (it, sym) + (it, name) } /// Crawl over the crate, inserting test reexports and the test main function @@ -373,9 +373,10 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { main_body); // Honor the reexport_test_harness_main attribute - let main_id = Ident::new( - cx.reexport_test_harness_main.unwrap_or(Symbol::gensym("main")), - sp); + let main_id = match cx.reexport_test_harness_main { + Some(sym) => Ident::new(sym, sp), + None => Ident::from_str_and_span("main", sp).gensym(), + }; P(ast::Item { ident: main_id, diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs index c582fb422c97..200445d12488 100644 --- a/src/libsyntax_ext/proc_macro_decls.rs +++ b/src/libsyntax_ext/proc_macro_decls.rs @@ -429,7 +429,7 @@ fn mk_decls( let module = cx.item_mod( span, span, - ast::Ident::with_empty_ctxt(Symbol::gensym("decls")), + ast::Ident::from_str("decls").gensym(), vec![doc_hidden], vec![krate, decls_static], ).map(|mut i| { diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 2bf3b1fa4657..fb99be0fe33f 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -630,10 +630,12 @@ pub struct Ident { impl Ident { #[inline] + /// Constructs a new identifier from a symbol and a span. pub const fn new(name: Symbol, span: Span) -> Ident { Ident { name, span } } + /// Constructs a new identifier with an empty syntax context. #[inline] pub const fn with_empty_ctxt(name: Symbol) -> Ident { Ident::new(name, DUMMY_SP) @@ -644,11 +646,16 @@ impl Ident { Ident::with_empty_ctxt(string.as_symbol()) } - /// Maps a string to an identifier with an empty syntax context. + /// Maps a string to an identifier with an empty span. pub fn from_str(string: &str) -> Ident { Ident::with_empty_ctxt(Symbol::intern(string)) } + /// Maps a string and a span to an identifier. + pub fn from_str_and_span(string: &str, span: Span) -> Ident { + Ident::new(Symbol::intern(string), span) + } + /// Replaces `lo` and `hi` with those from `span`, but keep hygiene context. pub fn with_span_pos(self, span: Span) -> Ident { Ident::new(self.name, span.with_ctxt(self.span.ctxt())) @@ -676,11 +683,14 @@ impl Ident { Ident::new(self.name, self.span.modern_and_legacy()) } + /// Transforms an identifier into one with the same name, but gensymed. pub fn gensym(self) -> Ident { let name = with_interner(|interner| interner.gensymed(self.name)); Ident::new(name, self.span) } + /// Transforms an underscore identifier into one with the same name, but + /// gensymed. Leaves non-underscore identifiers unchanged. pub fn gensym_if_underscore(self) -> Ident { if self.name == keywords::Underscore.name() { self.gensym() } else { self } } @@ -742,30 +752,34 @@ impl Decodable for Ident { Ok(if !string.starts_with('#') { Ident::from_str(&string) } else { // FIXME(jseyfried): intercrate hygiene - Ident::with_empty_ctxt(Symbol::gensym(&string[1..])) + Ident::from_str(&string[1..]).gensym() }) } } /// A symbol is an interned or gensymed string. A gensym is a symbol that is -/// never equal to any other symbol. E.g.: -/// ``` -/// assert_eq!(Symbol::intern("x"), Symbol::intern("x")) -/// assert_ne!(Symbol::gensym("x"), Symbol::intern("x")) -/// assert_ne!(Symbol::gensym("x"), Symbol::gensym("x")) -/// ``` +/// never equal to any other symbol. +/// /// Conceptually, a gensym can be thought of as a normal symbol with an /// invisible unique suffix. Gensyms are useful when creating new identifiers /// that must not match any existing identifiers, e.g. during macro expansion -/// and syntax desugaring. +/// and syntax desugaring. Because gensyms should always be identifiers, all +/// gensym operations are on `Ident` rather than `Symbol`. (Indeed, in the +/// future the gensym-ness may be moved from `Symbol` to hygiene data.) /// -/// Internally, a Symbol is implemented as an index, and all operations +/// Examples: +/// ``` +/// assert_eq!(Ident::from_str("x"), Ident::from_str("x")) +/// assert_ne!(Ident::from_str("x").gensym(), Ident::from_str("x")) +/// assert_ne!(Ident::from_str("x").gensym(), Ident::from_str("x").gensym()) +/// ``` +/// Internally, a symbol is implemented as an index, and all operations /// (including hashing, equality, and ordering) operate on that index. The use /// of `newtype_index!` means that `Option` only takes up 4 bytes, /// because `newtype_index!` reserves the last 256 values for tagging purposes. /// -/// Note that `Symbol` cannot directly be a `newtype_index!` because it implements -/// `fmt::Debug`, `Encodable`, and `Decodable` in special ways. +/// Note that `Symbol` cannot directly be a `newtype_index!` because it +/// implements `fmt::Debug`, `Encodable`, and `Decodable` in special ways. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Symbol(SymbolIndex); @@ -783,11 +797,6 @@ impl Symbol { with_interner(|interner| interner.intern(string)) } - /// Gensyms a new `usize`, using the current interner. - pub fn gensym(string: &str) -> Self { - with_interner(|interner| interner.gensym(string)) - } - pub fn as_str(self) -> LocalInternedString { with_interner(|interner| unsafe { LocalInternedString { @@ -895,11 +904,6 @@ impl Interner { } } - fn gensym(&mut self, string: &str) -> Symbol { - let symbol = self.intern(string); - self.gensymed(symbol) - } - fn gensymed(&mut self, symbol: Symbol) -> Symbol { self.gensyms.push(symbol); Symbol::new(SymbolIndex::MAX_AS_U32 - self.gensyms.len() as u32 + 1) @@ -1267,11 +1271,13 @@ mod tests { assert_eq!(i.intern("cat"), Symbol::new(1)); // dog is still at zero assert_eq!(i.intern("dog"), Symbol::new(0)); - assert_eq!(i.gensym("zebra"), Symbol::new(SymbolIndex::MAX_AS_U32)); + let z = i.intern("zebra"); + assert_eq!(i.gensymed(z), Symbol::new(SymbolIndex::MAX_AS_U32)); // gensym of same string gets new number: - assert_eq!(i.gensym("zebra"), Symbol::new(SymbolIndex::MAX_AS_U32 - 1)); + assert_eq!(i.gensymed(z), Symbol::new(SymbolIndex::MAX_AS_U32 - 1)); // gensym of *existing* string gets new number: - assert_eq!(i.gensym("dog"), Symbol::new(SymbolIndex::MAX_AS_U32 - 2)); + let d = i.intern("dog"); + assert_eq!(i.gensymed(d), Symbol::new(SymbolIndex::MAX_AS_U32 - 2)); } #[test] From a89e8d2a66bd6016b3a516b5483cb89580b79fcb Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Mon, 20 May 2019 09:21:26 +0200 Subject: [PATCH 0160/3207] ci: remove yet another outdated comment --- .azure-pipelines/auto.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.azure-pipelines/auto.yml b/.azure-pipelines/auto.yml index 2d240f8191a0..05d33e2f9d59 100644 --- a/.azure-pipelines/auto.yml +++ b/.azure-pipelines/auto.yml @@ -160,9 +160,6 @@ jobs: - template: steps/macos.yml strategy: matrix: - # macOS builders. These are placed near the beginning because they are very - # slow to run. - # OSX builders running tests, these run the full test suite. # NO_DEBUG_ASSERTIONS=1 to make them go faster, but also do have some # runners that run `//ignore-debug` tests. From f23c1ba74ba22b076536885d98bec63a9da6572c Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Mon, 20 May 2019 09:22:47 +0200 Subject: [PATCH 0161/3207] ci: use ##vso[task.prependpath] on azure --- .azure-pipelines/steps/linux.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.azure-pipelines/steps/linux.yml b/.azure-pipelines/steps/linux.yml index 238fd1d5ea78..36f980cf992d 100644 --- a/.azure-pipelines/steps/linux.yml +++ b/.azure-pipelines/steps/linux.yml @@ -12,7 +12,9 @@ steps: chmod +x $HOME/stamp export PATH=$PATH:$HOME/.local/bin:$HOME/Library/Python/2.7/bin/:$HOME - echo "##vso[task.setvariable variable=PATH;]$PATH" + echo "##vso[task.prependpath]$HOME/.local/bin" + echo "##vso[task.prependpath]$HOME/Library/Python/2.7/bin" + echo "##vso[task.prependpath]$HOME" mkdir -p $HOME/rustsrc displayName: Prep From d27cb827c60e70eb5415a45e882c8f0a1fa72f3e Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Mon, 20 May 2019 09:38:11 +0200 Subject: [PATCH 0162/3207] ci: add an image for dist-x86_64-linux try on azure --- .azure-pipelines/try.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.azure-pipelines/try.yml b/.azure-pipelines/try.yml index 8a4f48830296..bdd36e8555d7 100644 --- a/.azure-pipelines/try.yml +++ b/.azure-pipelines/try.yml @@ -17,6 +17,7 @@ jobs: strategy: matrix: dist-x86_64-linux: + IMAGE: dist-x86_64-linux DEPLOY: 1 # "alternate" deployments, these are "nightlies" but have LLVM assertions From b9be68ce2ed75a3801075f66f50200e329211400 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 20 May 2019 09:50:37 +0200 Subject: [PATCH 0163/3207] remove confusing remarks about mixed volatile and non-volatile accesses --- src/libcore/ptr.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index ada784e9ce70..fc3525b1184a 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -810,9 +810,6 @@ pub unsafe fn write_unaligned(dst: *mut T, src: T) { /// to not be elided or reordered by the compiler across other volatile /// operations. /// -/// Memory accessed with `read_volatile` or [`write_volatile`] should not be -/// accessed with non-volatile operations. -/// /// [`write_volatile`]: ./fn.write_volatile.html /// /// # Notes @@ -881,9 +878,6 @@ pub unsafe fn read_volatile(src: *const T) -> T { /// to not be elided or reordered by the compiler across other volatile /// operations. /// -/// Memory accessed with [`read_volatile`] or `write_volatile` should not be -/// accessed with non-volatile operations. -/// /// `write_volatile` does not drop the contents of `dst`. This is safe, but it /// could leak allocations or resources, so care should be taken not to overwrite /// an object that should be dropped. From 9f37b3a4c251d7caaa2870952e217be369e8e9c1 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Mon, 20 May 2019 10:07:17 +0200 Subject: [PATCH 0164/3207] ci: deploy artifacts on azure --- .azure-pipelines/steps/run-script.yml | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/.azure-pipelines/steps/run-script.yml b/.azure-pipelines/steps/run-script.yml index cb8e8a629a7e..bf18518e6b1c 100644 --- a/.azure-pipelines/steps/run-script.yml +++ b/.azure-pipelines/steps/run-script.yml @@ -1,13 +1,14 @@ steps: -# Log time information from this machine and an external machine for insight into possible -# clock drift. Timezones don't matter since relative deltas give all the necessary info. -- bash: | - date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true) - displayName: Log time information (before) - bash: | + # Log time information from this machine and an external machine for insight into possible + # clock drift. Timezones don't matter since relative deltas give all the necessary info. + date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true) + which sccache stamp sh -x -c "$RUN_SCRIPT" + + date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true) env: CI: true CI_JOB_NAME: $(IMAGE) @@ -20,5 +21,15 @@ steps: displayName: Run script - bash: | - date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true) - displayName: Log time information (after) + deploy_dir=rustc-builds + if [ "$DEPLOY_ALT" == "1" ]; then + deploy_dir=rustc-builds-alt + fi + aws s3 cp --no-progress --recursive --acl public-read ./deploy s3://$DEPLOY_BUCKET/$deploy_dir + env: + # Explicitly decrypt secret variables + # See https://docs.microsoft.com/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch#secret-variables + AWS_ACCESS_KEY_ID: $(SCCACHE_AWS_ACCESS_KEY_ID) + AWS_SECRET_ACCESS_KEY: $(SCCACHE_AWS_SECRET_ACCESS_KEY) + condition: and(succeeded(), or(eq(variables.DEPLOY, '1'), eq(variables.DEPLOY_ALT, '1'))) + displayName: Upload artifacts From a79c06a9ce1986d3c4dbc27b5e51d60d77befafb Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 17 May 2019 15:28:45 +0200 Subject: [PATCH 0165/3207] Document requirements for HashStable implementations better. --- src/librustc_data_structures/stable_hasher.rs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index 13e245d3c01e..2b844aa24d49 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -140,6 +140,30 @@ impl Hasher for StableHasher { /// Something that implements `HashStable` can be hashed in a way that is /// stable across multiple compilation sessions. +/// +/// Note that `HashStable` imposes rather more strict requirements than usual +/// hash functions: +/// +/// - Stable hashes are sometimes used as identifiers. Therefore they must +/// conform to the corresponding `PartialEq` implementations: +/// +/// - `x == y` implies `hash_stable(x) == hash_stable(y)`, and +/// - `x != y` implies `hash_stable(x) != hash_stable(y)`. +/// +/// That second condition is usually not required for hash functions +/// (e.g. `Hash`). In practice this means that `hash_stable` must feed any +/// information into the hasher that a `PartialEq` comparision takes into +/// account. See [#49300](https://github.com/rust-lang/rust/issues/49300) +/// for an example where violating this invariant has caused trouble in the +/// past. +/// +/// - `hash_stable()` must be independent of the current +/// compilation session. E.g. they must not hash memory addresses or other +/// things that are "randomly" assigned per compilation session. +/// +/// - `hash_stable()` must be independent of the host architecture. The +/// `StableHasher` takes care of endianness and `isize`/`usize` platform +/// differences. pub trait HashStable { fn hash_stable(&self, hcx: &mut CTX, From b7afe777f79462c9023a30b31785b81e8346c96c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 1 May 2019 19:39:52 +0200 Subject: [PATCH 0166/3207] stabilize core parts of MaybeUninit and deprecate mem::uninitialized in the future Also expand the documentation a bit --- src/liballoc/lib.rs | 2 +- src/libcore/lib.rs | 2 +- src/libcore/mem.rs | 300 ++++++++---------- src/libstd/lib.rs | 1 - src/test/codegen/box-maybe-uninit.rs | 1 - .../run-pass/panic-uninitialized-zeroed.rs | 2 +- 6 files changed, 138 insertions(+), 170 deletions(-) diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 2edd946ff11c..d90036eaf49b 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -109,7 +109,7 @@ #![feature(rustc_const_unstable)] #![feature(const_vec_new)] #![feature(slice_partition_dedup)] -#![feature(maybe_uninit, maybe_uninit_slice, maybe_uninit_array)] +#![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_array)] #![feature(alloc_layout_extra)] #![feature(try_trait)] #![feature(iter_nth_back)] diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 28db55578c3d..4a70329b64bc 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -125,7 +125,7 @@ #![feature(structural_match)] #![feature(abi_unadjusted)] #![feature(adx_target_feature)] -#![feature(maybe_uninit, maybe_uninit_slice, maybe_uninit_array)] +#![feature(maybe_uninit_slice, maybe_uninit_array)] #![feature(external_doc)] #[prelude_import] diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 9fb071d29524..9e23a5e61e4c 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -465,29 +465,39 @@ pub const fn needs_drop() -> bool { /// Creates a value whose bytes are all zero. /// -/// This has the same effect as allocating space with -/// [`mem::uninitialized`][uninit] and then zeroing it out. It is useful for -/// FFI sometimes, but should generally be avoided. +/// This has the same effect as [`MaybeUninit::zeroed().assume_init()`][zeroed]. +/// It is useful for FFI sometimes, but should generally be avoided. /// /// There is no guarantee that an all-zero byte-pattern represents a valid value of -/// some type `T`. If `T` has a destructor and the value is destroyed (due to -/// a panic or the end of a scope) before being initialized, then the destructor -/// will run on zeroed data, likely leading to [undefined behavior][ub]. +/// some type `T`. For example, the all-zero byte-pattern is not a valid value +/// for reference types (`&T` and `&mut T`). Using `zeroed` on such types +/// causes immediate [undefined behavior][ub]. /// -/// See also the documentation for [`mem::uninitialized`][uninit], which has -/// many of the same caveats. +/// See the documentation of [`MaybeUninit`] and [`MaybeUninit::zeroed()`][zeroed] +/// for more discussion on how to initialize values. /// -/// [uninit]: fn.uninitialized.html +/// [zeroed]: union.MaybeUninit.html#method.zeroed +/// [`MaybeUninit`]: union.MaybeUninit.html /// [ub]: ../../reference/behavior-considered-undefined.html /// /// # Examples /// +/// Correct usage of this function: initializing an integer with zero. +/// /// ``` /// use std::mem; /// /// let x: i32 = unsafe { mem::zeroed() }; /// assert_eq!(0, x); /// ``` +/// +/// *Incorrect* usage of this function: initializing a reference with zero. +/// +/// ```no_run +/// use std::mem; +/// +/// let _x: &i32 = unsafe { mem::zeroed() }; // Undefined behavior! +/// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn zeroed() -> T { @@ -498,130 +508,13 @@ pub unsafe fn zeroed() -> T { /// Bypasses Rust's normal memory-initialization checks by pretending to /// produce a value of type `T`, while doing nothing at all. /// -/// **This is incredibly dangerous and should not be done lightly. Deeply -/// consider initializing your memory with a default value instead.** +/// **This functon is deprecated because it basically cannot be used correctly.** /// -/// This is useful for FFI functions and initializing arrays sometimes, -/// but should generally be avoided. +/// Use [`MaybeUninit`] instead. /// -/// # Undefined behavior -/// -/// It is [undefined behavior][ub] to read uninitialized memory, even just an -/// uninitialized boolean. For instance, if you branch on the value of such -/// a boolean, your program may take one, both, or neither of the branches. -/// -/// Writing to the uninitialized value is similarly dangerous. Rust believes the -/// value is initialized, and will therefore try to [`Drop`] the uninitialized -/// value and its fields if you try to overwrite it in a normal manner. The only way -/// to safely initialize an uninitialized value is with [`ptr::write`][write], -/// [`ptr::copy`][copy], or [`ptr::copy_nonoverlapping`][copy_no]. -/// -/// If the value does implement [`Drop`], it must be initialized before -/// it goes out of scope (and therefore would be dropped). Note that this -/// includes a `panic` occurring and unwinding the stack suddenly. -/// -/// If you partially initialize an array, you may need to use -/// [`ptr::drop_in_place`][drop_in_place] to remove the elements you have fully -/// initialized followed by [`mem::forget`][mem_forget] to prevent drop running -/// on the array. If a partially allocated array is dropped this will lead to -/// undefined behaviour. -/// -/// # Examples -/// -/// Here's how to safely initialize an array of [`Vec`]s. -/// -/// ``` -/// use std::mem; -/// use std::ptr; -/// -/// // Only declare the array. This safely leaves it -/// // uninitialized in a way that Rust will track for us. -/// // However we can't initialize it element-by-element -/// // safely, and we can't use the `[value; 1000]` -/// // constructor because it only works with `Copy` data. -/// let mut data: [Vec; 1000]; -/// -/// unsafe { -/// // So we need to do this to initialize it. -/// data = mem::uninitialized(); -/// -/// // DANGER ZONE: if anything panics or otherwise -/// // incorrectly reads the array here, we will have -/// // Undefined Behavior. -/// -/// // It's ok to mutably iterate the data, since this -/// // doesn't involve reading it at all. -/// // (ptr and len are statically known for arrays) -/// for elem in &mut data[..] { -/// // *elem = Vec::new() would try to drop the -/// // uninitialized memory at `elem` -- bad! -/// // -/// // Vec::new doesn't allocate or do really -/// // anything. It's only safe to call here -/// // because we know it won't panic. -/// ptr::write(elem, Vec::new()); -/// } -/// -/// // SAFE ZONE: everything is initialized. -/// } -/// -/// println!("{:?}", &data[0]); -/// ``` -/// -/// This example emphasizes exactly how delicate and dangerous using `mem::uninitialized` -/// can be. Note that the [`vec!`] macro *does* let you initialize every element with a -/// value that is only [`Clone`], so the following is semantically equivalent and -/// vastly less dangerous, as long as you can live with an extra heap -/// allocation: -/// -/// ``` -/// let data: Vec> = vec![Vec::new(); 1000]; -/// println!("{:?}", &data[0]); -/// ``` -/// -/// This example shows how to handle partially initialized arrays, which could -/// be found in low-level datastructures. -/// -/// ``` -/// use std::mem; -/// use std::ptr; -/// -/// // Count the number of elements we have assigned. -/// let mut data_len: usize = 0; -/// let mut data: [String; 1000]; -/// -/// unsafe { -/// data = mem::uninitialized(); -/// -/// for elem in &mut data[0..500] { -/// ptr::write(elem, String::from("hello")); -/// data_len += 1; -/// } -/// -/// // For each item in the array, drop if we allocated it. -/// for i in &mut data[0..data_len] { -/// ptr::drop_in_place(i); -/// } -/// } -/// // Forget the data. If this is allowed to drop, you may see a crash such as: -/// // 'mem_uninit_test(2457,0x7fffb55dd380) malloc: *** error for object -/// // 0x7ff3b8402920: pointer being freed was not allocated' -/// mem::forget(data); -/// ``` -/// -/// [`Vec`]: ../../std/vec/struct.Vec.html -/// [`vec!`]: ../../std/macro.vec.html -/// [`Clone`]: ../../std/clone/trait.Clone.html -/// [ub]: ../../reference/behavior-considered-undefined.html -/// [write]: ../ptr/fn.write.html -/// [drop_in_place]: ../ptr/fn.drop_in_place.html -/// [mem_zeroed]: fn.zeroed.html -/// [mem_forget]: fn.forget.html -/// [copy]: ../intrinsics/fn.copy.html -/// [copy_no]: ../intrinsics/fn.copy_nonoverlapping.html -/// [`Drop`]: ../ops/trait.Drop.html +/// [`MaybeUninit`]: union.MaybeUninit.html #[inline] -#[rustc_deprecated(since = "2.0.0", reason = "use `mem::MaybeUninit::uninit` instead")] +#[rustc_deprecated(since = "1.40.0", reason = "use `mem::MaybeUninit` instead")] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn uninitialized() -> T { intrinsics::panic_if_uninhabited::(); @@ -899,7 +792,6 @@ pub fn discriminant(v: &T) -> Discriminant { } } -// FIXME: Reference `MaybeUninit` from these docs, once that is stable. /// A wrapper to inhibit compiler from automatically calling `T`’s destructor. /// /// This wrapper is 0-cost. @@ -908,6 +800,7 @@ pub fn discriminant(v: &T) -> Discriminant { /// As a consequence, it has *no effect* on the assumptions that the compiler makes /// about all values being initialized at their type. In particular, initializing /// a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined behavior. +/// If you need to handle uninitialized data, use [`MaybeUninit`] instead. /// /// # Examples /// @@ -942,6 +835,7 @@ pub fn discriminant(v: &T) -> Discriminant { /// ``` /// /// [`mem::zeroed`]: fn.zeroed.html +/// [`MaybeUninit`]: union.MaybeUninit.html #[stable(feature = "manually_drop", since = "1.20.0")] #[lang = "manually_drop"] #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -1042,17 +936,18 @@ impl DerefMut for ManuallyDrop { } } -/// A wrapper to construct uninitialized instances of `T`. +/// A wrapper type to construct uninitialized instances of `T`. +/// +/// # Initialization invariant /// /// The compiler, in general, assumes that variables are properly initialized /// at their respective type. For example, a variable of reference type must /// be aligned and non-NULL. This is an invariant that must *always* be upheld, /// even in unsafe code. As a consequence, zero-initializing a variable of reference -/// type causes instantaneous undefined behavior, no matter whether that reference +/// type causes instantaneous [undefined behavior][ub], no matter whether that reference /// ever gets used to access memory: /// /// ```rust,no_run -/// #![feature(maybe_uninit)] /// use std::mem::{self, MaybeUninit}; /// /// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior! @@ -1067,7 +962,6 @@ impl DerefMut for ManuallyDrop { /// always be `true` or `false`. Hence, creating an uninitialized `bool` is undefined behavior: /// /// ```rust,no_run -/// #![feature(maybe_uninit)] /// use std::mem::{self, MaybeUninit}; /// /// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior! @@ -1078,10 +972,9 @@ impl DerefMut for ManuallyDrop { /// Moreover, uninitialized memory is special in that the compiler knows that /// it does not have a fixed value. This makes it undefined behavior to have /// uninitialized data in a variable even if that variable has an integer type, -/// which otherwise can hold any bit pattern: +/// which otherwise can hold any *fixed* bit pattern: /// /// ```rust,no_run -/// #![feature(maybe_uninit)] /// use std::mem::{self, MaybeUninit}; /// /// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior! @@ -1091,37 +984,108 @@ impl DerefMut for ManuallyDrop { /// (Notice that the rules around uninitialized integers are not finalized yet, but /// until they are, it is advisable to avoid them.) /// +/// On top of that, remember that most types have additional invariants beyond merely +/// being considered initialized at the type level. For example, a `1`-initialized [`Vec`] +/// is considered initialized because the only requirement the compiler knows about it +/// is that the data pointer must be non-null. Creating such a `Vec` does not cause +/// *immediate* undefined behavior, but will cause undefined behavior with most +/// safe operations (including dropping it). +/// +/// [`Vec`]: ../../std/vec/struct.Vec.html +/// +/// # Examples +/// /// `MaybeUninit` serves to enable unsafe code to deal with uninitialized data. /// It is a signal to the compiler indicating that the data here might *not* /// be initialized: /// /// ```rust -/// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// /// // Create an explicitly uninitialized reference. The compiler knows that data inside /// // a `MaybeUninit` may be invalid, and hence this is not UB: /// let mut x = MaybeUninit::<&i32>::uninit(); /// // Set it to a valid value. -/// x.write(&0); +/// unsafe { x.as_mut_ptr().write(&0); } /// // Extract the initialized data -- this is only allowed *after* properly /// // initializing `x`! /// let x = unsafe { x.assume_init() }; /// ``` /// /// The compiler then knows to not make any incorrect assumptions or optimizations on this code. -// -// FIXME before stabilizing, explain how to initialize a struct field-by-field. +/// +/// ## Initializing an array element-by-element +/// +/// `MaybeUninit` can be used to initialize a large array element-by-element: +/// +/// ``` +/// use std::mem::{self, MaybeUninit}; +/// use std::ptr; +/// +/// let data = unsafe { +/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is +/// // safe because the type we are claiming to have initialized here is a +/// // bunch of `MaybeUninit`s, which do not require initialization. +/// let mut data: [MaybeUninit>; 1000] = MaybeUninit::uninit().assume_init(); +/// +/// // Dropping a `MaybeUninit` does nothing, so if there is a panic during this loop, +/// // we have a memory leak, but there is no memory safety issue. +/// for elem in &mut data[..] { +/// ptr::write(elem.as_mut_ptr(), vec![42]); +/// } +/// +/// // Everything is initialized. Transmute the array to the +/// // initialized type. +/// mem::transmute::<_, [Vec; 1000]>(data) +/// }; +/// +/// println!("{:?}", &data[0]); +/// ``` +/// +/// You can also work with partially initialized arrays, which could +/// be found in low-level datastructures. +/// +/// ``` +/// use std::mem::MaybeUninit; +/// use std::ptr; +/// +/// unsafe { +/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is +/// // safe because the type we are claiming to have initialized here is a +/// // bunch of `MaybeUninit`s, which do not require initialization. +/// let mut data: [MaybeUninit; 1000] = MaybeUninit::uninit().assume_init(); +/// // Count the number of elements we have assigned. +/// let mut data_len: usize = 0; +/// +/// for elem in &mut data[0..500] { +/// ptr::write(elem.as_mut_ptr(), String::from("hello")); +/// data_len += 1; +/// } +/// +/// // For each item in the array, drop if we allocated it. +/// for elem in &mut data[0..data_len] { +/// ptr::drop_in_place(elem.as_mut_ptr()); +/// } +/// } +/// ``` +/// +/// ## Initializing a struct field-by-field +/// +/// There is unfortunately currently no supported way to create a raw pointer or reference +/// to a field of a struct inside `MaybeUninit`. That means it is not possible +/// to create a struct by calling `MaybeUninit::uninit::()` and then writing +/// to its fields. +/// +/// [ub]: ../../reference/behavior-considered-undefined.html #[allow(missing_debug_implementations)] -#[unstable(feature = "maybe_uninit", issue = "53491")] +#[stable(feature = "maybe_uninit", since = "1.36.0")] #[derive(Copy)] -// NOTE: after stabilizing `MaybeUninit`, proceed to deprecate `mem::uninitialized`. pub union MaybeUninit { uninit: (), value: ManuallyDrop, } -#[unstable(feature = "maybe_uninit", issue = "53491")] +#[stable(feature = "maybe_uninit", since = "1.36.0")] impl Clone for MaybeUninit { #[inline(always)] fn clone(&self) -> Self { @@ -1132,10 +1096,13 @@ impl Clone for MaybeUninit { impl MaybeUninit { /// Creates a new `MaybeUninit` initialized with the given value. + /// It is safe to call [`assume_init`] on the return value of this function. /// /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. /// It is your responsibility to make sure `T` gets dropped if it got initialized. - #[unstable(feature = "maybe_uninit", issue = "53491")] + /// + /// [`assume_init`]: #method.assume_init + #[stable(feature = "maybe_uninit", since = "1.36.0")] #[inline(always)] pub const fn new(val: T) -> MaybeUninit { MaybeUninit { value: ManuallyDrop::new(val) } @@ -1145,7 +1112,11 @@ impl MaybeUninit { /// /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. /// It is your responsibility to make sure `T` gets dropped if it got initialized. - #[unstable(feature = "maybe_uninit", issue = "53491")] + /// + /// See the [type-level documentation][type] for some examples. + /// + /// [type]: union.MaybeUninit.html + #[stable(feature = "maybe_uninit", since = "1.36.0")] #[inline(always)] pub const fn uninit() -> MaybeUninit { MaybeUninit { uninit: () } @@ -1166,7 +1137,6 @@ impl MaybeUninit { /// fields of the struct can hold the bit-pattern 0 as a valid value. /// /// ```rust - /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// /// let x = MaybeUninit::<(u8, bool)>::zeroed(); @@ -1178,7 +1148,6 @@ impl MaybeUninit { /// cannot hold 0 as a valid value. /// /// ```rust,no_run - /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// /// enum NotZero { One = 1, Two = 2 }; @@ -1188,7 +1157,7 @@ impl MaybeUninit { /// // Inside a pair, we create a `NotZero` that does not have a valid discriminant. /// // This is undefined behavior. /// ``` - #[unstable(feature = "maybe_uninit", issue = "53491")] + #[stable(feature = "maybe_uninit", since = "1.36.0")] #[inline] pub fn zeroed() -> MaybeUninit { let mut u = MaybeUninit::::uninit(); @@ -1202,7 +1171,7 @@ impl MaybeUninit { /// without dropping it, so be careful not to use this twice unless you want to /// skip running the destructor. For your convenience, this also returns a mutable /// reference to the (now safely initialized) contents of `self`. - #[unstable(feature = "maybe_uninit", issue = "53491")] + #[unstable(feature = "maybe_uninit_extra", issue = "53491")] #[inline(always)] pub fn write(&mut self, val: T) -> &mut T { unsafe { @@ -1213,13 +1182,14 @@ impl MaybeUninit { /// Gets a pointer to the contained value. Reading from this pointer or turning it /// into a reference is undefined behavior unless the `MaybeUninit` is initialized. + /// Writing to memory that this pointer (non-transitively) points to is undefined behavior + /// (except inside an `UnsafeCell`). /// /// # Examples /// /// Correct usage of this method: /// /// ```rust - /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::>::uninit(); @@ -1232,7 +1202,6 @@ impl MaybeUninit { /// *Incorrect* usage of this method: /// /// ```rust,no_run - /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// /// let x = MaybeUninit::>::uninit(); @@ -1242,7 +1211,7 @@ impl MaybeUninit { /// /// (Notice that the rules around references to uninitialized data are not finalized yet, but /// until they are, it is advisable to avoid them.) - #[unstable(feature = "maybe_uninit", issue = "53491")] + #[stable(feature = "maybe_uninit", since = "1.36.0")] #[inline(always)] pub fn as_ptr(&self) -> *const T { unsafe { &*self.value as *const T } @@ -1256,7 +1225,6 @@ impl MaybeUninit { /// Correct usage of this method: /// /// ```rust - /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::>::uninit(); @@ -1271,7 +1239,6 @@ impl MaybeUninit { /// *Incorrect* usage of this method: /// /// ```rust,no_run - /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::>::uninit(); @@ -1281,7 +1248,7 @@ impl MaybeUninit { /// /// (Notice that the rules around references to uninitialized data are not finalized yet, but /// until they are, it is advisable to avoid them.) - #[unstable(feature = "maybe_uninit", issue = "53491")] + #[stable(feature = "maybe_uninit", since = "1.36.0")] #[inline(always)] pub fn as_mut_ptr(&mut self) -> *mut T { unsafe { &mut *self.value as *mut T } @@ -1294,15 +1261,17 @@ impl MaybeUninit { /// # Safety /// /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized - /// state. Calling this when the content is not yet fully initialized causes undefined - /// behavior. + /// state. Calling this when the content is not yet fully initialized causes immediate undefined + /// behavior. The [type-level documentation][inv] contains more information about + /// this initialization invariant. + /// + /// [inv]: #initialization-invariant /// /// # Examples /// /// Correct usage of this method: /// /// ```rust - /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::::uninit(); @@ -1314,14 +1283,13 @@ impl MaybeUninit { /// *Incorrect* usage of this method: /// /// ```rust,no_run - /// #![feature(maybe_uninit)] /// use std::mem::MaybeUninit; /// /// let x = MaybeUninit::>::uninit(); /// let x_init = unsafe { x.assume_init() }; /// // `x` had not been initialized yet, so this last line caused undefined behavior. /// ``` - #[unstable(feature = "maybe_uninit", issue = "53491")] + #[stable(feature = "maybe_uninit", since = "1.36.0")] #[inline(always)] pub unsafe fn assume_init(self) -> T { intrinsics::panic_if_uninhabited::(); @@ -1338,13 +1306,15 @@ impl MaybeUninit { /// /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized /// state. Calling this when the content is not yet fully initialized causes undefined - /// behavior. + /// behavior. The [type-level documentation][inv] contains more information about + /// this initialization invariant. /// /// Moreover, this leaves a copy of the same data behind in the `MaybeUninit`. When using /// multiple copies of the data (by calling `read` multiple times, or first /// calling `read` and then [`assume_init`]), it is your responsibility /// to ensure that that data may indeed be duplicated. /// + /// [inv]: #initialization-invariant /// [`assume_init`]: #method.assume_init /// /// # Examples @@ -1352,7 +1322,7 @@ impl MaybeUninit { /// Correct usage of this method: /// /// ```rust - /// #![feature(maybe_uninit)] + /// #![feature(maybe_uninit_extra)] /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::::uninit(); @@ -1373,7 +1343,7 @@ impl MaybeUninit { /// *Incorrect* usage of this method: /// /// ```rust,no_run - /// #![feature(maybe_uninit)] + /// #![feature(maybe_uninit_extra)] /// use std::mem::MaybeUninit; /// /// let mut x = MaybeUninit::>>::uninit(); @@ -1383,7 +1353,7 @@ impl MaybeUninit { /// // We now created two copies of the same vector, leading to a double-free when /// // they both get dropped! /// ``` - #[unstable(feature = "maybe_uninit", issue = "53491")] + #[unstable(feature = "maybe_uninit_extra", issue = "53491")] #[inline(always)] pub unsafe fn read(&self) -> T { intrinsics::panic_if_uninhabited::(); diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 2401946536ff..e044b46e0d07 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -272,7 +272,6 @@ #![feature(libc)] #![feature(link_args)] #![feature(linkage)] -#![feature(maybe_uninit)] #![feature(needs_panic_runtime)] #![feature(never_type)] #![feature(nll)] diff --git a/src/test/codegen/box-maybe-uninit.rs b/src/test/codegen/box-maybe-uninit.rs index 0dd67bb95cca..5004f787cde1 100644 --- a/src/test/codegen/box-maybe-uninit.rs +++ b/src/test/codegen/box-maybe-uninit.rs @@ -1,6 +1,5 @@ // compile-flags: -O #![crate_type="lib"] -#![feature(maybe_uninit)] use std::mem::MaybeUninit; diff --git a/src/test/run-pass/panic-uninitialized-zeroed.rs b/src/test/run-pass/panic-uninitialized-zeroed.rs index 3f6e489bb832..4ca4b407bd4f 100644 --- a/src/test/run-pass/panic-uninitialized-zeroed.rs +++ b/src/test/run-pass/panic-uninitialized-zeroed.rs @@ -2,7 +2,7 @@ // This test checks that instantiating an uninhabited type via `mem::{uninitialized,zeroed}` results // in a runtime panic. -#![feature(never_type, maybe_uninit)] +#![feature(never_type)] use std::{mem, panic}; From 30a43326d026d4b115bc400094efa0b3e13924ce Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 2 May 2019 16:50:56 +0200 Subject: [PATCH 0167/3207] apply feedback --- src/libcore/mem.rs | 64 ++++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 9e23a5e61e4c..92e28dc35ba8 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -471,14 +471,12 @@ pub const fn needs_drop() -> bool { /// There is no guarantee that an all-zero byte-pattern represents a valid value of /// some type `T`. For example, the all-zero byte-pattern is not a valid value /// for reference types (`&T` and `&mut T`). Using `zeroed` on such types -/// causes immediate [undefined behavior][ub]. -/// -/// See the documentation of [`MaybeUninit`] and [`MaybeUninit::zeroed()`][zeroed] -/// for more discussion on how to initialize values. +/// causes immediate [undefined behavior][ub] because [the Rust compiler assumes][inv] +/// that there always is a valid value in a variable it considers initialized. /// /// [zeroed]: union.MaybeUninit.html#method.zeroed -/// [`MaybeUninit`]: union.MaybeUninit.html /// [ub]: ../../reference/behavior-considered-undefined.html +/// [inv]: union.MaybeUninit.html#initialization-invariant /// /// # Examples /// @@ -508,11 +506,21 @@ pub unsafe fn zeroed() -> T { /// Bypasses Rust's normal memory-initialization checks by pretending to /// produce a value of type `T`, while doing nothing at all. /// -/// **This functon is deprecated because it basically cannot be used correctly.** +/// **This functon is deprecated.** Use [`MaybeUninit`] instead. /// -/// Use [`MaybeUninit`] instead. +/// The reason for deprecation is that the function basically cannot be used +/// correctly: [the Rust compiler assumes][inv] that values are properly initialized. +/// As a consequence, calling e.g. `mem::uninitialized::()` causes immediate +/// undefined behavior for returning a `bool` that is not definitely either `true` +/// or `false`. Worse, truly uninitialized memory like what gets returned here +/// is special in that the compiler knows that it does not have a fixed value. +/// This makes it undefined behavior to have uninitialized data in a variable even +/// if that variable has an integer type. +/// (Notice that the rules around uninitialized integers are not finalized yet, but +/// until they are, it is advisable to avoid them.) /// /// [`MaybeUninit`]: union.MaybeUninit.html +/// [inv]: union.MaybeUninit.html#initialization-invariant #[inline] #[rustc_deprecated(since = "1.40.0", reason = "use `mem::MaybeUninit` instead")] #[stable(feature = "rust1", since = "1.0.0")] @@ -1022,21 +1030,23 @@ impl DerefMut for ManuallyDrop { /// use std::mem::{self, MaybeUninit}; /// use std::ptr; /// -/// let data = unsafe { +/// let data = { /// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is /// // safe because the type we are claiming to have initialized here is a /// // bunch of `MaybeUninit`s, which do not require initialization. -/// let mut data: [MaybeUninit>; 1000] = MaybeUninit::uninit().assume_init(); +/// let mut data: [MaybeUninit>; 1000] = unsafe { +/// MaybeUninit::uninit().assume_init() +/// }; /// /// // Dropping a `MaybeUninit` does nothing, so if there is a panic during this loop, /// // we have a memory leak, but there is no memory safety issue. /// for elem in &mut data[..] { -/// ptr::write(elem.as_mut_ptr(), vec![42]); +/// unsafe { ptr::write(elem.as_mut_ptr(), vec![42]); } /// } /// /// // Everything is initialized. Transmute the array to the /// // initialized type. -/// mem::transmute::<_, [Vec; 1000]>(data) +/// unsafe { mem::transmute::<_, [Vec; 1000]>(data) } /// }; /// /// println!("{:?}", &data[0]); @@ -1049,29 +1059,27 @@ impl DerefMut for ManuallyDrop { /// use std::mem::MaybeUninit; /// use std::ptr; /// -/// unsafe { -/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is -/// // safe because the type we are claiming to have initialized here is a -/// // bunch of `MaybeUninit`s, which do not require initialization. -/// let mut data: [MaybeUninit; 1000] = MaybeUninit::uninit().assume_init(); -/// // Count the number of elements we have assigned. -/// let mut data_len: usize = 0; +/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is +/// // safe because the type we are claiming to have initialized here is a +/// // bunch of `MaybeUninit`s, which do not require initialization. +/// let mut data: [MaybeUninit; 1000] = unsafe { MaybeUninit::uninit().assume_init() }; +/// // Count the number of elements we have assigned. +/// let mut data_len: usize = 0; /// -/// for elem in &mut data[0..500] { -/// ptr::write(elem.as_mut_ptr(), String::from("hello")); -/// data_len += 1; -/// } +/// for elem in &mut data[0..500] { +/// unsafe { ptr::write(elem.as_mut_ptr(), String::from("hello")); } +/// data_len += 1; +/// } /// -/// // For each item in the array, drop if we allocated it. -/// for elem in &mut data[0..data_len] { -/// ptr::drop_in_place(elem.as_mut_ptr()); -/// } +/// // For each item in the array, drop if we allocated it. +/// for elem in &mut data[0..data_len] { +/// unsafe { ptr::drop_in_place(elem.as_mut_ptr()); } /// } /// ``` /// /// ## Initializing a struct field-by-field /// -/// There is unfortunately currently no supported way to create a raw pointer or reference +/// There is currently no supported way to create a raw pointer or reference /// to a field of a struct inside `MaybeUninit`. That means it is not possible /// to create a struct by calling `MaybeUninit::uninit::()` and then writing /// to its fields. @@ -1183,7 +1191,7 @@ impl MaybeUninit { /// Gets a pointer to the contained value. Reading from this pointer or turning it /// into a reference is undefined behavior unless the `MaybeUninit` is initialized. /// Writing to memory that this pointer (non-transitively) points to is undefined behavior - /// (except inside an `UnsafeCell`). + /// (except inside an `UnsafeCell`). /// /// # Examples /// From 11fba52c0758659b7238d99251e19d3b65c9119b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 4 May 2019 11:14:58 +0200 Subject: [PATCH 0168/3207] add out-pointer example --- src/libcore/mem.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 92e28dc35ba8..cf5794594918 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -1022,6 +1022,30 @@ impl DerefMut for ManuallyDrop { /// /// The compiler then knows to not make any incorrect assumptions or optimizations on this code. /// +/// ## out-pointers +/// +/// You can use `MaybeUninit` to implement "out-pointers": instead of returning data +/// from a function, pass it a pointer to some (uninitialized) memory to put the +/// result into. This can be useful when it is important for the caller to control +/// how the memory the result is stored in gets allocated, and you want to avoid +/// unnecessary moves. +/// +/// ``` +/// use std::mem::MaybeUninit; +/// +/// unsafe fn make_vec(out: *mut Vec) { +/// // `write` does not drop the old contents, which is important. +/// out.write(vec![1, 2, 3]); +/// } +/// +/// let mut v: MaybeUninit> = MaybeUninit::uninit(); +/// unsafe { make_vec(v.as_mut_ptr()); } +/// // Now we know `v` is initialized! This also makes sure the vector gets +/// // properly dropped. +/// let v = unsafe { v.assume_init() }; +/// assert_eq!(&v, &[1, 2, 3]); +/// ``` +/// /// ## Initializing an array element-by-element /// /// `MaybeUninit` can be used to initialize a large array element-by-element: @@ -1049,7 +1073,7 @@ impl DerefMut for ManuallyDrop { /// unsafe { mem::transmute::<_, [Vec; 1000]>(data) } /// }; /// -/// println!("{:?}", &data[0]); +/// assert_eq!(&data[0], &[42]); /// ``` /// /// You can also work with partially initialized arrays, which could From 4bf500fea7b9c57d0fb20c9bdade3590b80358f0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 8 May 2019 14:24:14 +0200 Subject: [PATCH 0169/3207] elliminate mem::uninitialize from docs in libcore --- src/libcore/mem.rs | 56 ---------------------------------------------- src/libcore/ptr.rs | 8 +++---- 2 files changed, 4 insertions(+), 60 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index cf5794594918..b7af9c0cef9c 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -63,62 +63,6 @@ pub use crate::intrinsics::transmute; /// The practical use cases for `forget` are rather specialized and mainly come /// up in unsafe or FFI code. /// -/// ## Use case 1 -/// -/// You have created an uninitialized value using [`mem::uninitialized`][uninit]. -/// You must either initialize or `forget` it on every computation path before -/// Rust drops it automatically, like at the end of a scope or after a panic. -/// Running the destructor on an uninitialized value would be [undefined behavior][ub]. -/// -/// ``` -/// use std::mem; -/// use std::ptr; -/// -/// # let some_condition = false; -/// unsafe { -/// let mut uninit_vec: Vec = mem::uninitialized(); -/// -/// if some_condition { -/// // Initialize the variable. -/// ptr::write(&mut uninit_vec, Vec::new()); -/// } else { -/// // Forget the uninitialized value so its destructor doesn't run. -/// mem::forget(uninit_vec); -/// } -/// } -/// ``` -/// -/// ## Use case 2 -/// -/// You have duplicated the bytes making up a value, without doing a proper -/// [`Clone`][clone]. You need the value's destructor to run only once, -/// because a double `free` is undefined behavior. -/// -/// An example is a possible implementation of [`mem::swap`][swap]: -/// -/// ``` -/// use std::mem; -/// use std::ptr; -/// -/// # #[allow(dead_code)] -/// fn swap(x: &mut T, y: &mut T) { -/// unsafe { -/// // Give ourselves some scratch space to work with -/// let mut t: T = mem::uninitialized(); -/// -/// // Perform the swap, `&mut` pointers never alias -/// ptr::copy_nonoverlapping(&*x, &mut t, 1); -/// ptr::copy_nonoverlapping(&*y, x, 1); -/// ptr::copy_nonoverlapping(&t, y, 1); -/// -/// // y and t now point to the same thing, but we need to completely -/// // forget `t` because we do not want to run the destructor for `T` -/// // on its value, which is still owned somewhere outside this function. -/// mem::forget(t); -/// } -/// } -/// ``` -/// /// [drop]: fn.drop.html /// [uninit]: fn.uninitialized.html /// [clone]: ../clone/trait.Clone.html diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index ada784e9ce70..dd321dcdfae6 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -155,12 +155,12 @@ pub use crate::intrinsics::write_bytes; /// location first: /// ``` /// use std::ptr; -/// use std::mem; +/// use std::mem::{self, MaybeUninit}; /// /// unsafe fn drop_after_copy(to_drop: *mut T) { -/// let mut copy: T = mem::uninitialized(); -/// ptr::copy(to_drop, &mut copy, 1); -/// drop(copy); +/// let mut copy: MaybeUninit = MaybeUninit::uninit(); +/// ptr::copy(to_drop, copy.as_mut_ptr(), 1); +/// drop(copy.assume_init()); /// } /// /// #[repr(packed, C)] From 2a15dec5a2f7f713ffe176a9c1d766114f85aeef Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Mon, 6 May 2019 17:39:39 -0400 Subject: [PATCH 0170/3207] Document layout guarantee of MaybeUninit --- src/libcore/mem.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index b7af9c0cef9c..24bee6355a7c 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -1053,6 +1053,28 @@ impl DerefMut for ManuallyDrop { /// to its fields. /// /// [ub]: ../../reference/behavior-considered-undefined.html +/// +/// # Layout +/// +/// `MaybeUninit` is guaranteed to have the same size and alignment as `T`: +/// +/// ```rust +/// use std::mem::{MaybeUninit, size_of, align_of}; +/// assert_eq!(size_of::>(), size_of::()); +/// assert_eq!(align_of::>(), align_of::()); +/// ``` +/// +/// However remember that a type *containing* a `MaybeUninit` is not necessarily the same +/// layout; Rust does not in general guarantee that the fields of a `Foo` have the same order as +/// a `Foo` even if `T` and `U` have the same size and alignment. Furthermore because any bit +/// value is valid for a `MaybeUninit` the compiler can't apply non-zero/niche-filling +/// optimizations, potentially resulting in a larger size: +/// +/// ```rust +/// # use std::mem::{MaybeUninit, size_of, align_of}; +/// assert_eq!(size_of::>(), 1); +/// assert_eq!(size_of::>>(), 2); +/// ``` #[allow(missing_debug_implementations)] #[stable(feature = "maybe_uninit", since = "1.36.0")] #[derive(Copy)] From 1916391ea8b97389a9ed690b4df614a2b96069fd Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 20 May 2019 10:54:36 +0200 Subject: [PATCH 0171/3207] update miri --- src/tools/miri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri b/src/tools/miri index 37b2eea7144d..0c85dbf3df0f 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 37b2eea7144d022702f0d2eedcc4c776db15d078 +Subproject commit 0c85dbf3df0f545133dca24eccfc9f0f6107c7f8 From c5d94017569713c12a7e3d260cb4cd0a02b26372 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 6 May 2019 11:47:03 +1000 Subject: [PATCH 0172/3207] Avoid symbol interning in `file_metadata`. This commit changes `created_files` so it uses strings directly as keys, rather than symbols derived from the strings. This avoids the cost of having to do the hash table lookups to produce the symbols from the strings. The commit also uses `entry` to avoid doing a repeated hash table lookup (`get` + `insert`). Note that PR #60467 improved this code somewhat; this is a further improvement. --- .../debuginfo/metadata.rs | 64 +++++++++---------- src/librustc_codegen_llvm/debuginfo/mod.rs | 4 +- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 9bdce37b8bae..e7f54f6609d2 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -38,6 +38,7 @@ use rustc_data_structures::small_c_str::SmallCStr; use rustc_target::abi::HasDataLayout; use libc::{c_uint, c_longlong}; +use std::collections::hash_map::Entry; use std::ffi::CString; use std::fmt::{self, Write}; use std::hash::{Hash, Hasher}; @@ -45,7 +46,7 @@ use std::iter; use std::ptr; use std::path::{Path, PathBuf}; use syntax::ast; -use syntax::symbol::{Interner, InternedString, Symbol}; +use syntax::symbol::{Interner, InternedString}; use syntax_pos::{self, Span, FileName}; impl PartialEq for llvm::Metadata { @@ -787,49 +788,48 @@ pub fn file_metadata(cx: &CodegenCx<'ll, '_>, file_name, defining_crate); - let file_name = &file_name.to_string(); - let file_name_symbol = Symbol::intern(file_name); - if defining_crate == LOCAL_CRATE { - let directory = &cx.sess().working_dir.0.to_string_lossy(); - file_metadata_raw(cx, file_name, Some(file_name_symbol), - directory, Some(Symbol::intern(directory))) + let file_name = Some(file_name.to_string()); + let directory = if defining_crate == LOCAL_CRATE { + Some(cx.sess().working_dir.0.to_string_lossy().to_string()) } else { // If the path comes from an upstream crate we assume it has been made // independent of the compiler's working directory one way or another. - file_metadata_raw(cx, file_name, Some(file_name_symbol), "", None) - } + None + }; + file_metadata_raw(cx, file_name, directory) } pub fn unknown_file_metadata(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile { - file_metadata_raw(cx, "", None, "", None) + file_metadata_raw(cx, None, None) } fn file_metadata_raw(cx: &CodegenCx<'ll, '_>, - file_name: &str, - file_name_symbol: Option, - directory: &str, - directory_symbol: Option) + file_name: Option, + directory: Option) -> &'ll DIFile { - let key = (file_name_symbol, directory_symbol); + let key = (file_name, directory); - if let Some(file_metadata) = debug_context(cx).created_files.borrow().get(&key) { - return *file_metadata; + match debug_context(cx).created_files.borrow_mut().entry(key) { + Entry::Occupied(o) => return o.get(), + Entry::Vacant(v) => { + let (file_name, directory) = v.key(); + debug!("file_metadata: file_name: {:?}, directory: {:?}", file_name, directory); + + let file_name = SmallCStr::new( + if let Some(file_name) = file_name { &file_name } else { "" }); + let directory = SmallCStr::new( + if let Some(directory) = directory { &directory } else { "" }); + + let file_metadata = unsafe { + llvm::LLVMRustDIBuilderCreateFile(DIB(cx), + file_name.as_ptr(), + directory.as_ptr()) + }; + + v.insert(file_metadata); + file_metadata + } } - - debug!("file_metadata: file_name: {}, directory: {}", file_name, directory); - - let file_name = SmallCStr::new(file_name); - let directory = SmallCStr::new(directory); - - let file_metadata = unsafe { - llvm::LLVMRustDIBuilderCreateFile(DIB(cx), - file_name.as_ptr(), - directory.as_ptr()) - }; - - let mut created_files = debug_context(cx).created_files.borrow_mut(); - created_files.insert(key, file_metadata); - file_metadata } fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index f3070a03b4ed..527290392fff 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -37,7 +37,7 @@ use std::ffi::CString; use syntax_pos::{self, Span, Pos}; use syntax::ast; -use syntax::symbol::{Symbol, InternedString}; +use syntax::symbol::InternedString; use rustc::ty::layout::{self, LayoutOf, HasTyCtxt}; use rustc_codegen_ssa::traits::*; @@ -63,7 +63,7 @@ pub struct CrateDebugContext<'a, 'tcx> { llcontext: &'a llvm::Context, llmod: &'a llvm::Module, builder: &'a mut DIBuilder<'a>, - created_files: RefCell, Option), &'a DIFile>>, + created_files: RefCell, Option), &'a DIFile>>, created_enum_disr_types: RefCell>, type_map: RefCell>, From 0a423a70bb303195f09753dfdc5a7c4e149e29ff Mon Sep 17 00:00:00 2001 From: MaulingMonkey Date: Mon, 20 May 2019 02:44:26 -0700 Subject: [PATCH 0173/3207] Fix CDB support tidy check line length failures. --- src/test/debuginfo/pretty-std.rs | 6 +++--- src/tools/compiletest/src/main.rs | 2 +- src/tools/compiletest/src/runtest.rs | 9 +++++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs index f568371d68a1..a684d3b88fd0 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -1,5 +1,5 @@ // ignore-freebsd: gdb package too new -// only-cdb // Test temporarily ignored on GDB/LLDB due to debuginfo tests being disabled, see PR 47155 +// only-cdb // "Temporarily" ignored on GDB/LLDB due to debuginfo tests being disabled, see PR 47155 // ignore-android: FIXME(#10381) // compile-flags:-g // min-gdb-version 7.7 @@ -81,7 +81,7 @@ // cdb-command: dx str_slice // cdb-check:str_slice [...] -// NOTE: While string slices have a .natvis entry that works in VS & VS Code, it fails in CDB 10.0.18362.1 +// NOTE: While string slices have a .natvis entry that works in VS & VS Code, it fails in CDB // cdb-command: dx string // cdb-check:string : "IAMA string!" [Type: [...]::String] @@ -110,7 +110,7 @@ // cdb-command: dx none // cdb-check:none : { None } [Type: [...]::Option] // cdb-command: dx some_string -// cdb-check:some_string : { Some "IAMA optional string!" } [Type: [...]::Option<[...]::String>] +// cdb-check:some_string : { Some "IAMA optional string!" } [[...]::Option<[...]::String>] #![allow(unused_variables)] use std::ffi::OsString; diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 631ed067c341..48ecd5a91422 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -873,7 +873,7 @@ fn find_cdb(target: &String) -> Option { let mut path = PathBuf::with_capacity(64); path.push(pf86); - path.push(r"Windows Kits\10\Debuggers"); // We could check more known install locations (8.1?) + path.push(r"Windows Kits\10\Debuggers"); // We could check 8.1 etc. too? path.push(cdb_arch); path.push(r"cdb.exe"); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index c0dedccdff8a..c940e2de665a 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -3,7 +3,8 @@ use crate::common::CompareMode; use crate::common::{expected_output_path, UI_EXTENSIONS, UI_FIXED, UI_STDERR, UI_STDOUT}; use crate::common::{output_base_dir, output_base_name, output_testname_unique}; -use crate::common::{Codegen, CodegenUnits, DebugInfoCdb, DebugInfoGdbLldb, DebugInfoGdb, DebugInfoLldb, Rustdoc}; +use crate::common::{Codegen, CodegenUnits, Rustdoc}; +use crate::common::{DebugInfoCdb, DebugInfoGdbLldb, DebugInfoGdb, DebugInfoLldb}; use crate::common::{CompileFail, Pretty, RunFail, RunPass, RunPassValgrind}; use crate::common::{Config, TestPaths}; use crate::common::{Incremental, MirOpt, RunMake, Ui, JsDocTest, Assembly}; @@ -709,7 +710,7 @@ impl<'test> TestCx<'test> { // https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-commands let mut script_str = String::with_capacity(2048); script_str.push_str("version\n"); // List CDB (and more) version info in test output - script_str.push_str(".nvlist\n"); // List loaded `*.natvis` files (bulk of MSVC debugger customizations) + script_str.push_str(".nvlist\n"); // List loaded `*.natvis` files, bulk of custom MSVC debug // Set breakpoints on every line that contains the string "#break" let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy(); @@ -1968,8 +1969,8 @@ impl<'test> TestCx<'test> { rustc.arg(dir_opt); } - RunFail | RunPassValgrind | Pretty | DebugInfoCdb | DebugInfoGdbLldb | DebugInfoGdb | DebugInfoLldb - | Codegen | Rustdoc | RunMake | CodegenUnits | JsDocTest | Assembly => { + RunFail | RunPassValgrind | Pretty | DebugInfoCdb | DebugInfoGdbLldb | DebugInfoGdb + | DebugInfoLldb | Codegen | Rustdoc | RunMake | CodegenUnits | JsDocTest | Assembly => { // do not use JSON output } } From a7e1431941406eeb341c4e3b7e929c2e65514ac3 Mon Sep 17 00:00:00 2001 From: Brent Kerby Date: Sun, 19 May 2019 09:21:03 -0600 Subject: [PATCH 0174/3207] Update boxed::Box docs on memory layout --- src/liballoc/boxed.rs | 63 ++++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 207359ed6968..90bec03beb07 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -127,24 +127,38 @@ impl Box { /// /// After calling this function, the raw pointer is owned by the /// resulting `Box`. Specifically, the `Box` destructor will call - /// the destructor of `T` and free the allocated memory. Since the - /// way `Box` allocates and releases memory is unspecified, the - /// only valid pointer to pass to this function is the one taken - /// from another `Box` via the [`Box::into_raw`] function. + /// the destructor of `T` and free the allocated memory. For this + /// to be safe, the memory must have been allocated in the precise + /// way that `Box` expects, namely, using the global allocator + /// with the correct [`Layout`] for holding a value of type `T`. In + /// particular, this will be satisfied for a pointer obtained + /// from a previously existing `Box` using [`Box::into_raw`]. + /// + /// # Safety /// /// This function is unsafe because improper use may lead to /// memory problems. For example, a double-free may occur if the /// function is called twice on the same raw pointer. /// - /// [`Box::into_raw`]: struct.Box.html#method.into_raw - /// /// # Examples - /// + /// Recreate a `Box` which was previously converted to a raw pointer using [`Box::into_raw`]: /// ``` /// let x = Box::new(5); /// let ptr = Box::into_raw(x); /// let x = unsafe { Box::from_raw(ptr) }; /// ``` + /// Manually create a `Box` from scratch by using the global allocator: + /// ``` + /// use std::alloc::{Layout, alloc}; + /// + /// let ptr = unsafe{ alloc(Layout::new::()) } as *mut i32; + /// unsafe{ *ptr = 5; } + /// let x = unsafe{ Box::from_raw(ptr) }; + /// ``` + /// + /// [`Layout`]: ../alloc/struct.Layout.html + /// [`Box::into_raw`]: struct.Box.html#method.into_raw + /// #[stable(feature = "box_raw", since = "1.4.0")] #[inline] pub unsafe fn from_raw(raw: *mut T) -> Self { @@ -158,21 +172,34 @@ impl Box { /// After calling this function, the caller is responsible for the /// memory previously managed by the `Box`. In particular, the /// caller should properly destroy `T` and release the memory. The - /// proper way to do so is to convert the raw pointer back into a - /// `Box` with the [`Box::from_raw`] function. + /// easiest way to do so is to convert the raw pointer back into a `Box` + /// with the [`Box::from_raw`] function. /// /// Note: this is an associated function, which means that you have /// to call it as `Box::into_raw(b)` instead of `b.into_raw()`. This /// is so that there is no conflict with a method on the inner type. /// + /// # Examples + /// Converting the raw pointer back into a `Box` with [`Box::from_raw`] + /// for automatic cleanup: + /// ``` + /// let x = Box::new(String::from("Hello")); + /// let ptr = Box::into_raw(x); + /// let x = unsafe{ Box::from_raw(ptr) }; + /// ``` + /// Manual cleanup by running the destructor and deallocating the memory: + /// ``` + /// use std::alloc::{Layout, dealloc}; + /// use std::ptr; + /// + /// let x = Box::new(String::from("Hello")); + /// let p = Box::into_raw(x); + /// unsafe{ ptr::drop_in_place(p); } + /// unsafe{ dealloc(p as *mut u8, Layout::new::()); } + /// ``` + /// /// [`Box::from_raw`]: struct.Box.html#method.from_raw /// - /// # Examples - /// - /// ``` - /// let x = Box::new(5); - /// let ptr = Box::into_raw(x); - /// ``` #[stable(feature = "box_raw", since = "1.4.0")] #[inline] pub fn into_raw(b: Box) -> *mut T { @@ -184,7 +211,7 @@ impl Box { /// After calling this function, the caller is responsible for the /// memory previously managed by the `Box`. In particular, the /// caller should properly destroy `T` and release the memory. The - /// proper way to do so is to convert the `NonNull` pointer + /// easiest way to do so is to convert the `NonNull` pointer /// into a raw pointer and back into a `Box` with the [`Box::from_raw`] /// function. /// @@ -203,6 +230,10 @@ impl Box { /// fn main() { /// let x = Box::new(5); /// let ptr = Box::into_raw_non_null(x); + /// + /// // Clean up the memory by converting the NonNull pointer back + /// // into a Box and letting the Box be dropped. + /// let x = unsafe{ Box::from_raw(ptr.as_ptr()) }; /// } /// ``` #[unstable(feature = "box_into_raw_non_null", issue = "47336")] From 178b753a4a202ad96ccbd10e037194d15ca8f805 Mon Sep 17 00:00:00 2001 From: Brent Kerby Date: Sun, 19 May 2019 17:47:18 -0600 Subject: [PATCH 0175/3207] Remove trailing whitespaces to satisfy tidy --- src/liballoc/boxed.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 90bec03beb07..4e712a946b85 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -130,9 +130,9 @@ impl Box { /// the destructor of `T` and free the allocated memory. For this /// to be safe, the memory must have been allocated in the precise /// way that `Box` expects, namely, using the global allocator - /// with the correct [`Layout`] for holding a value of type `T`. In + /// with the correct [`Layout`] for holding a value of type `T`. In /// particular, this will be satisfied for a pointer obtained - /// from a previously existing `Box` using [`Box::into_raw`]. + /// from a previously existing `Box` using [`Box::into_raw`]. /// /// # Safety /// @@ -172,7 +172,7 @@ impl Box { /// After calling this function, the caller is responsible for the /// memory previously managed by the `Box`. In particular, the /// caller should properly destroy `T` and release the memory. The - /// easiest way to do so is to convert the raw pointer back into a `Box` + /// easiest way to do so is to convert the raw pointer back into a `Box` /// with the [`Box::from_raw`] function. /// /// Note: this is an associated function, which means that you have @@ -180,7 +180,7 @@ impl Box { /// is so that there is no conflict with a method on the inner type. /// /// # Examples - /// Converting the raw pointer back into a `Box` with [`Box::from_raw`] + /// Converting the raw pointer back into a `Box` with [`Box::from_raw`] /// for automatic cleanup: /// ``` /// let x = Box::new(String::from("Hello")); @@ -191,7 +191,7 @@ impl Box { /// ``` /// use std::alloc::{Layout, dealloc}; /// use std::ptr; - /// + /// /// let x = Box::new(String::from("Hello")); /// let p = Box::into_raw(x); /// unsafe{ ptr::drop_in_place(p); } From 16ef2957705392abd6a7d9ac46619863ac339ef1 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Mon, 29 Apr 2019 03:54:03 +0100 Subject: [PATCH 0176/3207] Accumulation of various drive-by cosmetic changes. --- src/librustc/query/mod.rs | 42 +++++++++---------- src/librustc/traits/util.rs | 14 +++---- src/librustc/ty/mod.rs | 10 ++--- src/librustc/ty/query/mod.rs | 3 +- .../borrow_check/error_reporting.rs | 1 - src/librustc_typeck/astconv.rs | 14 +++---- src/librustc_typeck/collect.rs | 12 +++--- 7 files changed, 45 insertions(+), 51 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 2fff4c3f109b..d043a32f06bd 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -168,7 +168,7 @@ rustc_queries! { query predicates_defined_on(_: DefId) -> Lrc> {} - /// Returns the predicates written explicit by the user. + /// Returns the predicates written explicitly by the user. query explicit_predicates_of(_: DefId) -> Lrc> {} @@ -216,9 +216,9 @@ rustc_queries! { _: DefId ) -> Result, NoSolution> {} - /// True if this is a const fn, use the `is_const_fn` to know whether your crate actually - /// sees it as const fn (e.g., the const-fn-ness might be unstable and you might not have - /// the feature gate active) + /// Returns `true` if this is a const fn, use the `is_const_fn` to know whether your crate + /// actually sees it as const fn (e.g., the const-fn-ness might be unstable and you might + /// not have the feature gate active). /// /// **Do not call this function manually.** It is only meant to cache the base data for the /// `is_const_fn` function. @@ -226,7 +226,7 @@ rustc_queries! { desc { |tcx| "checking if item is const fn: `{}`", tcx.def_path_str(key) } } - /// Returns true if calls to the function may be promoted + /// Returns `true` if calls to the function may be promoted. /// /// This is either because the function is e.g., a tuple-struct or tuple-variant /// constructor, or because it has the `#[rustc_promotable]` attribute. The attribute should @@ -237,25 +237,23 @@ rustc_queries! { query const_fn_is_allowed_fn_ptr(_: DefId) -> bool {} - /// True if this is a foreign item (i.e., linked via `extern { ... }`). + /// Returns `true` if this is a foreign item (i.e., linked via `extern { ... }`). query is_foreign_item(_: DefId) -> bool {} /// Returns `Some(mutability)` if the node pointed to by `def_id` is a static item. query static_mutability(_: DefId) -> Option {} - /// Get a map with the variance of every item; use `item_variance` - /// instead. + /// Gets a map with the variance of every item; use `item_variance` instead. query crate_variances(_: CrateNum) -> Lrc> { desc { "computing the variances for items in this crate" } } - /// Maps from def-id of a type or region parameter to its - /// (inferred) variance. + /// Maps from def-ID of a type or region parameter to its (inferred) variance. query variances_of(_: DefId) -> &'tcx [ty::Variance] {} } TypeChecking { - /// Maps from def-id of a type to its (inferred) outlives. + /// Maps from def-ID of a type to its (inferred) outlives. query inferred_outlives_crate(_: CrateNum) -> Lrc> { desc { "computing the inferred outlives predicates for items in this crate" } @@ -263,10 +261,10 @@ rustc_queries! { } Other { - /// Maps from an impl/trait def-id to a list of the def-ids of its items + /// Maps from an impl/trait def-ID to a list of the def-ids of its items. query associated_item_def_ids(_: DefId) -> Lrc> {} - /// Maps from a trait item to the trait item "descriptor" + /// Maps from a trait item to the trait item "descriptor". query associated_item(_: DefId) -> ty::AssociatedItem {} query impl_trait_ref(_: DefId) -> Option> {} @@ -276,7 +274,7 @@ rustc_queries! { } TypeChecking { - /// Maps a DefId of a type to a list of its inherent impls. + /// Maps a def-ID of a type to a list of its inherent impls. /// Contains implementations of methods that are inherent to a type. /// Methods in these implementations don't need to be exported. query inherent_impls(_: DefId) -> Lrc> { @@ -300,7 +298,7 @@ rustc_queries! { desc { |tcx| "linting {}", key.describe_as_module(tcx) } } - /// Checks the attributes in the module + /// Checks the attributes in the module. query check_mod_attrs(key: DefId) -> () { desc { |tcx| "checking attributes in {}", key.describe_as_module(tcx) } } @@ -309,7 +307,7 @@ rustc_queries! { desc { |tcx| "checking for unstable API usage in {}", key.describe_as_module(tcx) } } - /// Checks the loops in the module + /// Checks the loops in the module. query check_mod_loops(key: DefId) -> () { desc { |tcx| "checking loops in {}", key.describe_as_module(tcx) } } @@ -338,7 +336,7 @@ rustc_queries! { desc { |tcx| "collecting item types in {}", key.describe_as_module(tcx) } } - /// Caches CoerceUnsized kinds for impls on custom types. + /// Caches `CoerceUnsized` kinds for impls on custom types. query coerce_unsized_info(_: DefId) -> ty::adjustment::CoerceUnsizedInfo {} } @@ -375,7 +373,7 @@ rustc_queries! { BorrowChecking { query borrowck(_: DefId) -> Lrc {} - /// Borrow checks the function body. If this is a closure, returns + /// Borrow-checks the function body. If this is a closure, returns /// additional requirements that the closure's creator must verify. query mir_borrowck(_: DefId) -> mir::BorrowCheckResult<'tcx> {} } @@ -401,11 +399,11 @@ rustc_queries! { } Other { - /// Evaluate a constant without running sanity checks + /// Evaluates a constant without running sanity checks. /// /// **Do not use this** outside const eval. Const eval uses this to break query cycles /// during validation. Please add a comment to every use site explaining why using - /// `const_eval` isn't sufficient + /// `const_eval` isn't sufficient. query const_eval_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) -> ConstEvalRawResult<'tcx> { no_force @@ -660,12 +658,12 @@ rustc_queries! { } Linking { - // The DefIds of all non-generic functions and statics in the given crate + // The `DefId`s of all non-generic functions and statics in the given crate // that can be reached from outside the crate. // // We expect this items to be available for being linked to. // - // This query can also be called for LOCAL_CRATE. In this case it will + // This query can also be called for `LOCAL_CRATE`. In this case it will // compute which items will be reachable to other crates, taking into account // the kind of crate that is currently compiled. Crates with only a // C interface have fewer reachable things. diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index be29ea5701b2..578d8bbedf39 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -123,12 +123,10 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> { // Predicates declared on the trait. let predicates = tcx.super_predicates_of(data.def_id()); - let mut predicates: Vec<_> = - predicates.predicates - .iter() - .map(|(p, _)| p.subst_supertrait(tcx, &data.to_poly_trait_ref())) - .collect(); - + let mut predicates: Vec<_> = predicates.predicates + .iter() + .map(|(pred, _)| pred.subst_supertrait(tcx, &data.to_poly_trait_ref())) + .collect(); debug!("super_predicates: data={:?} predicates={:?}", data, predicates); @@ -150,8 +148,8 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> { // predicates. } ty::Predicate::Subtype(..) => { - // Currently, we do not "elaborate" predicates like `X - // <: Y`, though conceivably we might. + // Currently, we do not "elaborate" predicates like `X <: Y`, + // though conceivably we might. } ty::Predicate::Projection(..) => { // Nothing to elaborate in a projection predicate. diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index e1c432d5b6da..c55e508c8b52 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1075,25 +1075,25 @@ impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> { #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] pub enum Predicate<'tcx> { - /// Corresponds to `where Foo: Bar`. `Foo` here would be + /// Corresponds to `where Foo: Bar`. `Foo` here would be /// the `Self` type of the trait reference and `A`, `B`, and `C` /// would be the type parameters. Trait(PolyTraitPredicate<'tcx>), - /// where `'a: 'b` + /// `where 'a: 'b` RegionOutlives(PolyRegionOutlivesPredicate<'tcx>), - /// where `T: 'a` + /// `where T: 'a` TypeOutlives(PolyTypeOutlivesPredicate<'tcx>), - /// where `::Name == X`, approximately. + /// `where ::Name == X`, approximately. /// See the `ProjectionPredicate` struct for details. Projection(PolyProjectionPredicate<'tcx>), /// no syntax: `T` well-formed WellFormed(Ty<'tcx>), - /// trait must be object-safe + /// Trait must be object-safe. ObjectSafe(DefId), /// No direct syntax. May be thought of as `where T: FnFoo<...>` diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 18d575f73645..be52b7e64519 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -100,8 +100,7 @@ pub use self::on_disk_cache::OnDiskCache; rustc_query_append! { [define_queries!][ <'tcx> Other { - /// Run analysis passes on the crate + /// Runs analysis passes on the crate. [] fn analysis: Analysis(CrateNum) -> Result<(), ErrorReported>, - }, ]} diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 1a1000f0bb41..32d182edfdcd 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -1502,7 +1502,6 @@ enum StorageDeadOrDrop<'tcx> { } impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { - /// Adds a suggestion when a closure is invoked twice with a moved variable or when a closure /// is moved after being invoked. /// diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 4b052aec5fc2..06605695630f 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -702,7 +702,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } /// Instantiates the path for the given trait reference, assuming that it's - /// bound to a valid trait type. Returns the def_id for the defining trait. + /// bound to a valid trait type. Returns the def-ID for the defining trait. /// The type _cannot_ be a type other than a trait type. /// /// If the `projections` argument is `None`, then assoc type bindings like `Foo` @@ -1035,7 +1035,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { pred.skip_binder().ty.walk().any(|t| t == dummy_self); // If the projection output contains `Self`, force the user to - // elaborate it explicitly to avoid a bunch of complexity. + // elaborate it explicitly to avoid a lot of complexity. // // The "classicaly useful" case is the following: // ``` @@ -1044,14 +1044,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { // } // ``` // - // Here, the user could theoretically write `dyn MyTrait`, + // Here, the user could theoretically write `dyn MyTrait`, // but actually supporting that would "expand" to an infinitely-long type - // `fix $ τ → dyn MyTrait::MyOutput`. + // `fix $ τ → dyn MyTrait::MyOutput`. // - // Instead, we force the user to write `dyn MyTrait`, + // Instead, we force the user to write `dyn MyTrait`, // which is uglier but works. See the discussion in #56288 for alternatives. if !references_self { - // Include projections defined on supertraits, + // Include projections defined on supertraits. projection_bounds.push((pred, DUMMY_SP)) } } @@ -2138,7 +2138,7 @@ impl<'a, 'gcx, 'tcx> Bounds<'tcx> { pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, param_ty: Ty<'tcx>) -> Vec<(ty::Predicate<'tcx>, Span)> { - // If it could be sized, and is, add the sized predicate. + // If it could be sized, and is, add the `Sized` predicate. let sized_predicate = self.implicitly_sized.and_then(|span| { tcx.lang_items().sized_trait().map(|sized| { let trait_ref = ty::TraitRef { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 711d79f95f53..104c8e25d138 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -684,9 +684,9 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad tcx.alloc_adt_def(def_id, kind, variants, repr) } -/// Ensures that the super-predicates of the trait with `DefId` -/// trait_def_id are converted and stored. This also ensures that -/// the transitive super-predicates are converted; +/// Ensures that the super-predicates of the trait with a `DefId` +/// of `trait_def_id` are converted and stored. This also ensures that +/// the transitive super-predicates are converted. fn super_predicates_of<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_def_id: DefId, @@ -707,14 +707,14 @@ fn super_predicates_of<'a, 'tcx>( let icx = ItemCtxt::new(tcx, trait_def_id); - // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo : Bar + Zed`. + // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`. let self_param_ty = tcx.mk_self_type(); let superbounds1 = compute_bounds(&icx, self_param_ty, bounds, SizedByDefault::No, item.span); let superbounds1 = superbounds1.predicates(tcx, self_param_ty); - // Convert any explicit superbounds in the where clause, - // e.g., `trait Foo where Self : Bar`. + // Convert any explicit superbounds in the wheree-clause, + // e.g., `trait Foo where Self: Bar`. // In the case of trait aliases, however, we include all bounds in the where clause, // so e.g., `trait Foo = where u32: PartialEq` would include `u32: PartialEq` // as one of its "superpredicates". From 9f800457dda7ee9b8579394d1c07761f3008e573 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Tue, 26 Mar 2019 17:34:32 +0000 Subject: [PATCH 0177/3207] Ban multi-trait objects via trait aliases. --- src/liballoc/slice.rs | 8 +- src/librustc/hir/map/mod.rs | 2 +- src/librustc/hir/mod.rs | 8 +- src/librustc/infer/outlives/verify.rs | 4 +- src/librustc/traits/mod.rs | 3 +- src/librustc/traits/select.rs | 3 +- src/librustc/traits/util.rs | 209 +++++++++++++++------ src/librustc/ty/mod.rs | 4 +- src/librustc_save_analysis/dump_visitor.rs | 6 +- src/librustc_typeck/astconv.rs | 85 ++++----- src/librustc_typeck/check/method/probe.rs | 2 +- src/librustc_typeck/check/wfcheck.rs | 2 +- src/libsyntax/ast.rs | 4 +- 13 files changed, 211 insertions(+), 129 deletions(-) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 6eac84874010..8768f1ff081c 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -123,12 +123,12 @@ pub use core::slice::{RChunks, RChunksMut, RChunksExact, RChunksExactMut}; //////////////////////////////////////////////////////////////////////////////// // HACK(japaric) needed for the implementation of `vec!` macro during testing -// NB see the hack module in this file for more details +// N.B., see the `hack` module in this file for more details. #[cfg(test)] pub use hack::into_vec; // HACK(japaric) needed for the implementation of `Vec::clone` during testing -// NB see the hack module in this file for more details +// N.B., see the `hack` module in this file for more details. #[cfg(test)] pub use hack::to_vec; @@ -376,7 +376,7 @@ impl [T] { pub fn to_vec(&self) -> Vec where T: Clone { - // NB see hack module in this file + // N.B., see the `hack` module in this file for more details. hack::to_vec(self) } @@ -397,7 +397,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn into_vec(self: Box) -> Vec { - // NB see hack module in this file + // N.B., see the `hack` module in this file for more details. hack::into_vec(self) } diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 4b94f772554e..23f4d2085713 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -957,7 +957,7 @@ impl<'hir> Map<'hir> { } } - /// Returns the name associated with the given NodeId's AST. + /// Returns the name associated with the given `NodeId`'s AST. pub fn name(&self, id: NodeId) -> Name { let hir_id = self.node_to_hir_id(id); self.name_by_hir_id(hir_id) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 22312e7459be..fafe1cf85a3e 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2143,11 +2143,11 @@ pub enum UseKind { ListStem, } -/// TraitRef's appear in impls. +/// `TraitRef` are references to traits in impls. /// -/// resolve maps each TraitRef's ref_id to its defining trait; that's all -/// that the ref_id is for. Note that ref_id's value is not the NodeId of the -/// trait being referred to but just a unique NodeId that serves as a key +/// `resolve` maps each `TraitRef`'s `ref_id` to its defining trait; that's all +/// that the `ref_id` is for. Note that `ref_id`'s value is not the `NodeId` of the +/// trait being referred to but just a unique `NodeId` that serves as a key /// within the resolution map. #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct TraitRef { diff --git a/src/librustc/infer/outlives/verify.rs b/src/librustc/infer/outlives/verify.rs index e1ad5aeea19f..5b8d89c865a5 100644 --- a/src/librustc/infer/outlives/verify.rs +++ b/src/librustc/infer/outlives/verify.rs @@ -141,9 +141,9 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> { } fn recursive_type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> { - let mut bounds = ty.walk_shallow() + let mut bounds: Vec<_> = ty.walk_shallow() .map(|subty| self.type_bound(subty)) - .collect::>(); + .collect(); let mut regions = smallvec![]; ty.push_regions(&mut regions); diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 846924fb591e..627f923399b5 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -62,6 +62,7 @@ pub use self::engine::{TraitEngine, TraitEngineExt}; pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs}; pub use self::util::{supertraits, supertrait_def_ids, transitive_bounds, Supertraits, SupertraitDefIds}; +pub use self::util::{expand_trait_refs, TraitRefExpander}; pub use self::chalk_fulfill::{ CanonicalGoal as ChalkCanonicalGoal, @@ -1043,7 +1044,7 @@ fn vtable_methods<'a, 'tcx>( ) } -impl<'tcx,O> Obligation<'tcx,O> { +impl<'tcx, O> Obligation<'tcx,O> { pub fn new(cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, predicate: O) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index c4be85050dbc..ec5e127a5ec4 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1772,7 +1772,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { bounds ); - let matching_bound = util::elaborate_predicates(self.tcx(), bounds.predicates) + let elaborated_predicates = util::elaborate_predicates(self.tcx(), bounds.predicates); + let matching_bound = elaborated_predicates .filter_to_traits() .find(|bound| { self.infcx.probe(|_| { diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 578d8bbedf39..897681e538e3 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -1,3 +1,5 @@ +use syntax_pos::Span; + use crate::hir; use crate::hir::def_id::DefId; use crate::traits::specialize::specialization_graph::NodeItem; @@ -41,7 +43,6 @@ fn anonymize_predicate<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, } } - struct PredicateSet<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, set: FxHashSet>, @@ -73,12 +74,11 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> { /// "Elaboration" is the process of identifying all the predicates that /// are implied by a source predicate. Currently this basically means -/// walking the "supertraits" and other similar assumptions. For -/// example, if we know that `T : Ord`, the elaborator would deduce -/// that `T : PartialOrd` holds as well. Similarly, if we have `trait -/// Foo : 'static`, and we know that `T : Foo`, then we know that `T : -/// 'static`. -pub struct Elaborator<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { +/// walking the "supertraits" and other similar assumptions. For example, +/// if we know that `T: Ord`, the elaborator would deduce that `T: PartialOrd` +/// holds as well. Similarly, if we have `trait Foo: 'static`, and we know that +/// `T: Foo`, then we know that `T: 'static`. +pub struct Elaborator<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { stack: Vec>, visited: PredicateSet<'a, 'gcx, 'tcx>, } @@ -96,8 +96,7 @@ pub fn elaborate_trait_refs<'cx, 'gcx, 'tcx>( trait_refs: impl Iterator>) -> Elaborator<'cx, 'gcx, 'tcx> { - let predicates = trait_refs.map(|trait_ref| trait_ref.to_predicate()) - .collect(); + let predicates = trait_refs.map(|trait_ref| trait_ref.to_predicate()).collect(); elaborate_predicates(tcx, predicates) } @@ -120,7 +119,7 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> { let tcx = self.visited.tcx; match *predicate { ty::Predicate::Trait(ref data) => { - // Predicates declared on the trait. + // Get predicates declared on the trait. let predicates = tcx.super_predicates_of(data.def_id()); let mut predicates: Vec<_> = predicates.predicates @@ -130,12 +129,11 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> { debug!("super_predicates: data={:?} predicates={:?}", data, predicates); - // Only keep those bounds that we haven't already - // seen. This is necessary to prevent infinite - // recursion in some cases. One common case is when - // people define `trait Sized: Sized { }` rather than `trait - // Sized { }`. - predicates.retain(|r| self.visited.insert(r)); + // Only keep those bounds that we haven't already seen. + // This is necessary to prevent infinite recursion in some + // cases. One common case is when people define + // `trait Sized: Sized { }` rather than `trait Sized { }`. + predicates.retain(|p| self.visited.insert(p)); self.stack.extend(predicates); } @@ -161,11 +159,9 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> { // Currently, we do not elaborate const-evaluatable // predicates. } - ty::Predicate::RegionOutlives(..) => { // Nothing to elaborate from `'a: 'b`. } - ty::Predicate::TypeOutlives(ref data) => { // We know that `T: 'a` for some type `T`. We can // often elaborate this. For example, if we know that @@ -192,34 +188,35 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> { tcx.push_outlives_components(ty_max, &mut components); self.stack.extend( components - .into_iter() - .filter_map(|component| match component { - Component::Region(r) => if r.is_late_bound() { - None - } else { - Some(ty::Predicate::RegionOutlives( - ty::Binder::dummy(ty::OutlivesPredicate(r, r_min)))) - }, + .into_iter() + .filter_map(|component| match component { + Component::Region(r) => if r.is_late_bound() { + None + } else { + Some(ty::Predicate::RegionOutlives( + ty::Binder::dummy(ty::OutlivesPredicate(r, r_min)))) + } - Component::Param(p) => { - let ty = tcx.mk_ty_param(p.index, p.name); - Some(ty::Predicate::TypeOutlives( - ty::Binder::dummy(ty::OutlivesPredicate(ty, r_min)))) - }, + Component::Param(p) => { + let ty = tcx.mk_ty_param(p.index, p.name); + Some(ty::Predicate::TypeOutlives( + ty::Binder::dummy(ty::OutlivesPredicate(ty, r_min)))) + } - Component::UnresolvedInferenceVariable(_) => { - None - }, + Component::UnresolvedInferenceVariable(_) => { + None + } - Component::Projection(_) | - Component::EscapingProjection(_) => { - // We can probably do more here. This - // corresponds to a case like `>::U: 'b`. - None - }, - }) - .filter(|p| visited.insert(p))); + Component::Projection(_) | + Component::EscapingProjection(_) => { + // We can probably do more here. This + // corresponds to a case like `>::U: 'b`. + None + } + }) + .filter(|p| visited.insert(p)) + ); } } } @@ -233,16 +230,10 @@ impl<'cx, 'gcx, 'tcx> Iterator for Elaborator<'cx, 'gcx, 'tcx> { } fn next(&mut self) -> Option> { - // Extract next item from top-most stack frame, if any. - let next_predicate = match self.stack.pop() { - Some(predicate) => predicate, - None => { - // No more stack frames. Done. - return None; - } - }; - self.push(&next_predicate); - return Some(next_predicate); + self.stack.pop().map(|item| { + self.push(&item); + item + }) } } @@ -254,20 +245,124 @@ pub type Supertraits<'cx, 'gcx, 'tcx> = FilterToTraits(tcx: TyCtxt<'cx, 'gcx, 'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) - -> Supertraits<'cx, 'gcx, 'tcx> -{ + -> Supertraits<'cx, 'gcx, 'tcx> { elaborate_trait_ref(tcx, trait_ref).filter_to_traits() } pub fn transitive_bounds<'cx, 'gcx, 'tcx>(tcx: TyCtxt<'cx, 'gcx, 'tcx>, bounds: impl Iterator>) - -> Supertraits<'cx, 'gcx, 'tcx> -{ + -> Supertraits<'cx, 'gcx, 'tcx> { elaborate_trait_refs(tcx, bounds).filter_to_traits() } +/////////////////////////////////////////////////////////////////////////// +// `TraitRefExpander` iterator +/////////////////////////////////////////////////////////////////////////// + +/// "Trait reference expansion" is the process of expanding a sequence of trait +/// references into another sequence by transitively following all trait +/// aliases. e.g. If you have bounds like `Foo + Send`, a trait alias +/// `trait Foo = Bar + Sync;`, and another trait alias +/// `trait Bar = Read + Write`, then the bounds would expand to +/// `Read + Write + Sync + Send`. +pub struct TraitRefExpander<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { + stack: Vec>, + visited: PredicateSet<'a, 'gcx, 'tcx>, +} + +#[derive(Debug, Clone)] +pub struct TraitRefExpansionInfo<'tcx> { + pub top_level_trait_ref: ty::PolyTraitRef<'tcx>, + pub top_level_span: Span, + pub trait_ref: ty::PolyTraitRef<'tcx>, + pub span: Span, +} + +pub fn expand_trait_refs<'cx, 'gcx, 'tcx>( + tcx: TyCtxt<'cx, 'gcx, 'tcx>, + trait_refs: impl IntoIterator, Span)> +) -> TraitRefExpander<'cx, 'gcx, 'tcx> { + let mut visited = PredicateSet::new(tcx); + let mut items: Vec<_> = + trait_refs + .into_iter() + .map(|(tr, sp)| TraitRefExpansionInfo { + top_level_trait_ref: tr.clone(), + top_level_span: sp, + trait_ref: tr, + span: sp, + }) + .collect(); + items.retain(|item| visited.insert(&item.trait_ref.to_predicate())); + TraitRefExpander { stack: items, visited: visited, } +} + +impl<'cx, 'gcx, 'tcx> TraitRefExpander<'cx, 'gcx, 'tcx> { + // Returns `true` if `item` refers to a trait. + fn push(&mut self, item: &TraitRefExpansionInfo<'tcx>) -> bool { + let tcx = self.visited.tcx; + + if !tcx.is_trait_alias(item.trait_ref.def_id()) { + return true; + } + + // Get predicates declared on the trait. + let predicates = tcx.super_predicates_of(item.trait_ref.def_id()); + + let mut items: Vec<_> = predicates.predicates + .iter() + .rev() + .filter_map(|(pred, sp)| { + pred.subst_supertrait(tcx, &item.trait_ref) + .to_opt_poly_trait_ref() + .map(|trait_ref| + TraitRefExpansionInfo { + trait_ref, + span: *sp, + ..*item + } + ) + }) + .collect(); + + debug!("expand_trait_refs: trait_ref={:?} items={:?}", + item.trait_ref, items); + + // Only keep those items that we haven't already seen. + items.retain(|i| self.visited.insert(&i.trait_ref.to_predicate())); + + self.stack.extend(items); + false + } +} + +impl<'cx, 'gcx, 'tcx> Iterator for TraitRefExpander<'cx, 'gcx, 'tcx> { + type Item = TraitRefExpansionInfo<'tcx>; + + fn size_hint(&self) -> (usize, Option) { + (self.stack.len(), None) + } + + fn next(&mut self) -> Option> { + loop { + let item = self.stack.pop(); + match item { + Some(item) => { + if self.push(&item) { + return Some(item); + } + } + None => { + return None; + } + } + } + } +} + /////////////////////////////////////////////////////////////////////////// // Iterator over def-ids of supertraits +/////////////////////////////////////////////////////////////////////////// pub struct SupertraitDefIds<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index c55e508c8b52..6020a737853e 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1234,7 +1234,7 @@ impl<'tcx> TraitPredicate<'tcx> { self.trait_ref.def_id } - pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator> + 'a { + pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator> + 'a { self.trait_ref.input_types() } @@ -2400,7 +2400,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { pub fn discriminants( &'a self, tcx: TyCtxt<'a, 'gcx, 'tcx>, - ) -> impl Iterator)> + Captures<'gcx> + 'a { + ) -> impl Iterator)> + Captures<'gcx> + 'a { let repr_type = self.repr.discr_type(); let initial = repr_type.initial_discriminant(tcx.global_tcx()); let mut prev_discr = None::>; diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 1e65f868ebac..5f184bf4a7d4 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1177,13 +1177,13 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { ); } ast::ImplItemKind::Type(ref ty) => { - // FIXME uses of the assoc type should ideally point to this + // FIXME: uses of the assoc type should ideally point to this // 'def' and the name here should be a ref to the def in the // trait. self.visit_ty(ty) } ast::ImplItemKind::Existential(ref bounds) => { - // FIXME uses of the assoc type should ideally point to this + // FIXME: uses of the assoc type should ideally point to this // 'def' and the name here should be a ref to the def in the // trait. for bound in bounds.iter() { @@ -1216,7 +1216,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { let hir_id = self.tcx.hir().node_to_hir_id(id); let access = access_from!(self.save_ctxt, root_item, hir_id); - // The parent def id of a given use tree is always the enclosing item. + // The parent def-ID of a given use tree is always the enclosing item. let parent = self.save_ctxt.tcx.hir().opt_local_def_id(id) .and_then(|id| self.save_ctxt.tcx.parent(id)) .map(id_from_def_id); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 06605695630f..fc6edc2627bc 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -975,12 +975,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { if trait_bounds.is_empty() { span_err!(tcx.sess, span, E0224, - "at least one non-builtin trait is required for an object type"); + "at least one non-builtin trait is required for an object type"); return tcx.types.err; } let mut projection_bounds = Vec::new(); let dummy_self = self.tcx().types.trait_object_dummy_self; + let mut bound_trait_refs = Vec::with_capacity(trait_bounds.len()); let (principal, potential_assoc_types) = self.instantiate_poly_trait_ref( &trait_bounds[0], dummy_self, @@ -988,22 +989,29 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { ); debug!("principal: {:?}", principal); - for trait_bound in trait_bounds[1..].iter() { - // sanity check for non-principal trait bounds - self.instantiate_poly_trait_ref(trait_bound, - dummy_self, - &mut vec![]); + for trait_bound in trait_bounds[1..].iter().rev() { + // Sanity check for non-principal trait bounds. + let (tr, _) = self.instantiate_poly_trait_ref( + trait_bound, + dummy_self, + &mut Vec::new() + ); + bound_trait_refs.push((tr, trait_bound.span)); } + bound_trait_refs.push((principal, trait_bounds[0].span)); - let (mut auto_traits, trait_bounds) = split_auto_traits(tcx, &trait_bounds[1..]); - - if !trait_bounds.is_empty() { - let b = &trait_bounds[0]; - let span = b.trait_ref.path.span; - struct_span_err!(self.tcx().sess, span, E0225, - "only auto traits can be used as additional traits in a trait object") - .span_label(span, "non-auto additional trait") - .emit(); + let expanded_traits = traits::expand_trait_refs(tcx, bound_trait_refs); + let (auto_traits, regular_traits): (Vec<_>, Vec<_>) = + expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref.def_id())); + if regular_traits.len() > 1 { + let extra_trait = ®ular_traits[1]; + let mut err = struct_span_err!(tcx.sess, extra_trait.top_level_span, E0225, + "only auto traits can be used as additional traits in a trait object"); + err.span_label(extra_trait.span, "non-auto additional trait"); + if extra_trait.span != extra_trait.top_level_span { + err.span_label(extra_trait.top_level_span, "expanded from this alias"); + } + err.emit(); } // Check that there are no gross object safety violations; @@ -1024,9 +1032,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", tr); match tr { ty::Predicate::Trait(pred) => { - associated_types.extend(tcx.associated_items(pred.def_id()) - .filter(|item| item.kind == ty::AssociatedKind::Type) - .map(|item| item.def_id)); + associated_types + .extend(tcx.associated_items(pred.def_id()) + .filter(|item| item.kind == ty::AssociatedKind::Type) + .map(|item| item.def_id)); } ty::Predicate::Projection(pred) => { // A `Self` within the original bound will be substituted with a @@ -1145,11 +1154,15 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { }) }); - // Dedup auto traits so that `dyn Trait + Send + Send` is the same as `dyn Trait + Send`. + // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as + // `dyn Trait + Send`. + let mut auto_traits: Vec<_> = + auto_traits.into_iter().map(|i| i.trait_ref.def_id()).collect(); auto_traits.sort(); auto_traits.dedup(); + debug!("auto_traits: {:?}", auto_traits); - // Calling `skip_binder` is okay, because the predicates are re-bound. + // Calling `skip_binder` is okay because the predicates are re-bound. let principal = if tcx.trait_is_auto(existential_principal.def_id()) { ty::ExistentialPredicate::AutoTrait(existential_principal.def_id()) } else { @@ -1175,14 +1188,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } else { self.re_infer(span, None).unwrap_or_else(|| { span_err!(tcx.sess, span, E0228, - "the lifetime bound for this object type cannot be deduced \ - from context; please supply an explicit bound"); + "the lifetime bound for this object type cannot be deduced \ + from context; please supply an explicit bound"); tcx.lifetimes.re_static }) } }) }; - debug!("region_bound: {:?}", region_bound); let ty = tcx.mk_dynamic(existential_predicates, region_bound); @@ -2097,33 +2109,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } } -/// Divides a list of general trait bounds into two groups: auto traits (e.g., Sync and Send) and -/// the remaining general trait bounds. -fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - trait_bounds: &'b [hir::PolyTraitRef]) - -> (Vec, Vec<&'b hir::PolyTraitRef>) -{ - let (auto_traits, trait_bounds): (Vec<_>, _) = trait_bounds.iter().partition(|bound| { - // Checks whether `trait_did` is an auto trait and adds it to `auto_traits` if so. - match bound.trait_ref.path.res { - Res::Def(DefKind::Trait, trait_did) if tcx.trait_is_auto(trait_did) => { - true - } - _ => false - } - }); - - let auto_traits = auto_traits.into_iter().map(|tr| { - if let Res::Def(DefKind::Trait, trait_did) = tr.trait_ref.path.res { - trait_did - } else { - unreachable!() - } - }).collect::>(); - - (auto_traits, trait_bounds) -} - // A helper struct for conveniently grouping a set of bounds which we pass to // and return from functions in multiple places. #[derive(PartialEq, Eq, Clone, Debug)] diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 251400e65f38..590ae9d46e8d 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -758,7 +758,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { } fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) { - // FIXME -- Do we want to commit to this behavior for param bounds? + // FIXME: do we want to commit to this behavior for param bounds? let bounds = self.param_env .caller_bounds diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index b009c8ea6dce..7e7a8d592667 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -1019,7 +1019,7 @@ fn check_false_global_bounds<'a, 'gcx, 'tcx>( .iter() .map(|(p, _)| *p) .collect(); - // Check elaborated bounds + // Check elaborated bounds. let implied_obligations = traits::elaborate_predicates(fcx.tcx, predicates); for pred in implied_obligations { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d12240655e62..e299518af0be 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2133,10 +2133,10 @@ pub struct TraitRef { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct PolyTraitRef { - /// The `'a` in `<'a> Foo<&'a T>` + /// The `'a` in `<'a> Foo<&'a T>`. pub bound_generic_params: Vec, - /// The `Foo<&'a T>` in `<'a> Foo<&'a T>` + /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`. pub trait_ref: TraitRef, pub span: Span, From 72e5e8bfa731a3b7e5a9363eced44e76d962c794 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Tue, 26 Mar 2019 17:23:09 +0000 Subject: [PATCH 0178/3207] Update tests. --- src/test/ui/error-codes/E0225.rs | 6 ++++++ src/test/ui/error-codes/E0225.stderr | 13 +++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/test/ui/error-codes/E0225.rs b/src/test/ui/error-codes/E0225.rs index 1789be1559d8..e3ac680f4415 100644 --- a/src/test/ui/error-codes/E0225.rs +++ b/src/test/ui/error-codes/E0225.rs @@ -1,4 +1,10 @@ +#![feature(trait_alias)] + +trait Foo = std::io::Read + std::io::Write; + fn main() { let _: Box; //~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + let _: Box; + //~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] } diff --git a/src/test/ui/error-codes/E0225.stderr b/src/test/ui/error-codes/E0225.stderr index 85a04708cb25..c8d8f07db8ae 100644 --- a/src/test/ui/error-codes/E0225.stderr +++ b/src/test/ui/error-codes/E0225.stderr @@ -1,9 +1,18 @@ error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/E0225.rs:2:32 + --> $DIR/E0225.rs:6:32 | LL | let _: Box; | ^^^^^^^^^^^^^^ non-auto additional trait -error: aborting due to previous error +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/E0225.rs:8:16 + | +LL | trait Foo = std::io::Read + std::io::Write; + | -------------- non-auto additional trait +... +LL | let _: Box; + | ^^^ expanded from this alias + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0225`. From 16692f7b1ad8623f784d3d3b60814ebfa468fe62 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Wed, 27 Mar 2019 15:14:41 +0000 Subject: [PATCH 0179/3207] Addressed review points. --- src/librustc/traits/mod.rs | 2 +- src/librustc/traits/util.rs | 45 +++++++++++++++------------------- src/librustc_typeck/astconv.rs | 4 +-- 3 files changed, 23 insertions(+), 28 deletions(-) diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 627f923399b5..a792c439f5b8 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -1044,7 +1044,7 @@ fn vtable_methods<'a, 'tcx>( ) } -impl<'tcx, O> Obligation<'tcx,O> { +impl<'tcx, O> Obligation<'tcx, O> { pub fn new(cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, predicate: O) diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 897681e538e3..4cb3f551123d 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -107,7 +107,7 @@ pub fn elaborate_predicates<'cx, 'gcx, 'tcx>( { let mut visited = PredicateSet::new(tcx); predicates.retain(|pred| visited.insert(pred)); - Elaborator { stack: predicates, visited: visited } + Elaborator { stack: predicates, visited } } impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> { @@ -286,19 +286,21 @@ pub fn expand_trait_refs<'cx, 'gcx, 'tcx>( let mut items: Vec<_> = trait_refs .into_iter() - .map(|(tr, sp)| TraitRefExpansionInfo { - top_level_trait_ref: tr.clone(), - top_level_span: sp, - trait_ref: tr, - span: sp, + .map(|(trait_ref, span)| TraitRefExpansionInfo { + top_level_trait_ref: trait_ref.clone(), + top_level_span: span, + trait_ref, + span, }) .collect(); items.retain(|item| visited.insert(&item.trait_ref.to_predicate())); - TraitRefExpander { stack: items, visited: visited, } + TraitRefExpander { stack: items, visited } } impl<'cx, 'gcx, 'tcx> TraitRefExpander<'cx, 'gcx, 'tcx> { - // Returns `true` if `item` refers to a trait. + /// If `item` refers to a trait alias, adds the components of the trait alias to the stack, + /// and returns `false`. + /// If `item` refers to an ordinary trait, simply returns `true`. fn push(&mut self, item: &TraitRefExpansionInfo<'tcx>) -> bool { let tcx = self.visited.tcx; @@ -306,27 +308,27 @@ impl<'cx, 'gcx, 'tcx> TraitRefExpander<'cx, 'gcx, 'tcx> { return true; } - // Get predicates declared on the trait. + // Get components of the trait alias. let predicates = tcx.super_predicates_of(item.trait_ref.def_id()); let mut items: Vec<_> = predicates.predicates .iter() .rev() - .filter_map(|(pred, sp)| { + .filter_map(|(pred, span)| { pred.subst_supertrait(tcx, &item.trait_ref) .to_opt_poly_trait_ref() .map(|trait_ref| TraitRefExpansionInfo { trait_ref, - span: *sp, + span: *span, ..*item } ) }) .collect(); - debug!("expand_trait_refs: trait_ref={:?} items={:?}", - item.trait_ref, items); + debug!("trait_ref_expander: trait_ref={:?} items={:?}", + item.trait_ref, items); // Only keep those items that we haven't already seen. items.retain(|i| self.visited.insert(&i.trait_ref.to_predicate())); @@ -344,24 +346,17 @@ impl<'cx, 'gcx, 'tcx> Iterator for TraitRefExpander<'cx, 'gcx, 'tcx> { } fn next(&mut self) -> Option> { - loop { - let item = self.stack.pop(); - match item { - Some(item) => { - if self.push(&item) { - return Some(item); - } - } - None => { - return None; - } + while let Some(item) = self.stack.pop() { + if self.push(&item) { + return Some(item); } } + None } } /////////////////////////////////////////////////////////////////////////// -// Iterator over def-ids of supertraits +// Iterator over def-IDs of supertraits /////////////////////////////////////////////////////////////////////////// pub struct SupertraitDefIds<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index fc6edc2627bc..e5410defb7aa 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -981,7 +981,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { let mut projection_bounds = Vec::new(); let dummy_self = self.tcx().types.trait_object_dummy_self; - let mut bound_trait_refs = Vec::with_capacity(trait_bounds.len()); let (principal, potential_assoc_types) = self.instantiate_poly_trait_ref( &trait_bounds[0], dummy_self, @@ -989,6 +988,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { ); debug!("principal: {:?}", principal); + let mut bound_trait_refs = Vec::with_capacity(trait_bounds.len()); for trait_bound in trait_bounds[1..].iter().rev() { // Sanity check for non-principal trait bounds. let (tr, _) = self.instantiate_poly_trait_ref( @@ -1009,7 +1009,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { "only auto traits can be used as additional traits in a trait object"); err.span_label(extra_trait.span, "non-auto additional trait"); if extra_trait.span != extra_trait.top_level_span { - err.span_label(extra_trait.top_level_span, "expanded from this alias"); + err.span_label(extra_trait.top_level_span, "expanded from this trait alias"); } err.emit(); } From 5f6c2127d792b0f2f2eb82e160e02cae3b238f14 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Thu, 28 Mar 2019 01:29:31 +0000 Subject: [PATCH 0180/3207] Factored out part of `conv_object_ty_poly_trait_ref` method. --- src/librustc_typeck/astconv.rs | 40 +++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index e5410defb7aa..e1dc0b10c9f9 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -965,6 +965,30 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { ty::ExistentialTraitRef::erase_self_ty(self.tcx(), trait_ref) } + fn expand_trait_refs(&self, + trait_refs: impl IntoIterator, Span)> + ) -> Vec { + let tcx = self.tcx(); + + // Expand trait aliases recursively and check that only one regular (non-auto) trait + // is used. + let expanded_traits = traits::expand_trait_refs(tcx, trait_refs); + let (auto_traits, regular_traits): (Vec<_>, Vec<_>) = + expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref.def_id())); + if regular_traits.len() > 1 { + let extra_trait = ®ular_traits[1]; + let mut err = struct_span_err!(tcx.sess, extra_trait.top_level_span, E0225, + "only auto traits can be used as additional traits in a trait object"); + err.span_label(extra_trait.span, "non-auto additional trait"); + if extra_trait.span != extra_trait.top_level_span { + err.span_label(extra_trait.top_level_span, "expanded from this trait alias"); + } + err.emit(); + } + + auto_traits.into_iter().map(|i| i.trait_ref.def_id()).collect() + } + fn conv_object_ty_poly_trait_ref(&self, span: Span, trait_bounds: &[hir::PolyTraitRef], @@ -1000,19 +1024,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } bound_trait_refs.push((principal, trait_bounds[0].span)); - let expanded_traits = traits::expand_trait_refs(tcx, bound_trait_refs); - let (auto_traits, regular_traits): (Vec<_>, Vec<_>) = - expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref.def_id())); - if regular_traits.len() > 1 { - let extra_trait = ®ular_traits[1]; - let mut err = struct_span_err!(tcx.sess, extra_trait.top_level_span, E0225, - "only auto traits can be used as additional traits in a trait object"); - err.span_label(extra_trait.span, "non-auto additional trait"); - if extra_trait.span != extra_trait.top_level_span { - err.span_label(extra_trait.top_level_span, "expanded from this trait alias"); - } - err.emit(); - } + let mut auto_traits = self.expand_trait_refs(bound_trait_refs); // Check that there are no gross object safety violations; // most importantly, that the supertraits don't contain `Self`, @@ -1156,8 +1168,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as // `dyn Trait + Send`. - let mut auto_traits: Vec<_> = - auto_traits.into_iter().map(|i| i.trait_ref.def_id()).collect(); auto_traits.sort(); auto_traits.dedup(); debug!("auto_traits: {:?}", auto_traits); From aea954b74de16888f09ff003ebfdf97f9f7ef001 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Mon, 29 Apr 2019 03:58:24 +0100 Subject: [PATCH 0181/3207] Fixed detection of multiple non-auto traits. --- src/librustc/traits/mod.rs | 9 +- src/librustc/traits/util.rs | 197 +++++++++++++++++--------- src/librustc_passes/ast_validation.rs | 1 - src/librustc_typeck/astconv.rs | 157 ++++++++++---------- 4 files changed, 210 insertions(+), 154 deletions(-) diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index a792c439f5b8..d950746f6e6d 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -60,9 +60,12 @@ pub use self::specialize::specialization_graph::FutureCompatOverlapError; pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind; pub use self::engine::{TraitEngine, TraitEngineExt}; pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs}; -pub use self::util::{supertraits, supertrait_def_ids, transitive_bounds, - Supertraits, SupertraitDefIds}; -pub use self::util::{expand_trait_refs, TraitRefExpander}; +pub use self::util::{ + supertraits, supertrait_def_ids, transitive_bounds, Supertraits, SupertraitDefIds, +}; +pub use self::util::{ + expand_trait_aliases, TraitAliasExpander, TraitAliasExpansionInfoDignosticBuilder, +}; pub use self::chalk_fulfill::{ CanonicalGoal as ChalkCanonicalGoal, diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 4cb3f551123d..d765827e3d56 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -1,3 +1,5 @@ +use errors::DiagnosticBuilder; +use smallvec::SmallVec; use syntax_pos::Span; use crate::hir; @@ -43,7 +45,7 @@ fn anonymize_predicate<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, } } -struct PredicateSet<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { +struct PredicateSet<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, set: FxHashSet>, } @@ -53,6 +55,10 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> { PredicateSet { tcx: tcx, set: Default::default() } } + fn contains(&mut self, pred: &ty::Predicate<'tcx>) -> bool { + self.set.contains(&anonymize_predicate(self.tcx, pred)) + } + fn insert(&mut self, pred: &ty::Predicate<'tcx>) -> bool { // We have to be careful here because we want // @@ -66,6 +72,18 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> { // regions before we throw things into the underlying set. self.set.insert(anonymize_predicate(self.tcx, pred)) } + + fn remove(&mut self, pred: &ty::Predicate<'tcx>) -> bool { + self.set.remove(&anonymize_predicate(self.tcx, pred)) + } +} + +impl<'a, 'gcx, 'tcx, T: AsRef>> Extend for PredicateSet<'a, 'gcx, 'tcx> { + fn extend>(&mut self, iter: I) { + for pred in iter.into_iter() { + self.insert(pred.as_ref()); + } + } } /////////////////////////////////////////////////////////////////////////// @@ -230,10 +248,16 @@ impl<'cx, 'gcx, 'tcx> Iterator for Elaborator<'cx, 'gcx, 'tcx> { } fn next(&mut self) -> Option> { - self.stack.pop().map(|item| { - self.push(&item); - item - }) + // Extract next item from top-most stack frame, if any. + let next_predicate = match self.stack.pop() { + Some(predicate) => predicate, + None => { + // No more stack frames. Done. + return None; + } + }; + self.push(&next_predicate); + return Some(next_predicate); } } @@ -256,96 +280,140 @@ pub fn transitive_bounds<'cx, 'gcx, 'tcx>(tcx: TyCtxt<'cx, 'gcx, 'tcx>, } /////////////////////////////////////////////////////////////////////////// -// `TraitRefExpander` iterator +// `TraitAliasExpander` iterator /////////////////////////////////////////////////////////////////////////// -/// "Trait reference expansion" is the process of expanding a sequence of trait +/// "Trait alias expansion" is the process of expanding a sequence of trait /// references into another sequence by transitively following all trait /// aliases. e.g. If you have bounds like `Foo + Send`, a trait alias /// `trait Foo = Bar + Sync;`, and another trait alias /// `trait Bar = Read + Write`, then the bounds would expand to /// `Read + Write + Sync + Send`. -pub struct TraitRefExpander<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { - stack: Vec>, +pub struct TraitAliasExpander<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { + stack: Vec>, + /// The set of predicates visited from the root directly to the current point in the + /// expansion tree. visited: PredicateSet<'a, 'gcx, 'tcx>, } #[derive(Debug, Clone)] -pub struct TraitRefExpansionInfo<'tcx> { - pub top_level_trait_ref: ty::PolyTraitRef<'tcx>, - pub top_level_span: Span, - pub trait_ref: ty::PolyTraitRef<'tcx>, - pub span: Span, +pub struct TraitAliasExpansionInfo<'tcx> { + pub items: SmallVec<[(ty::PolyTraitRef<'tcx>, Span); 4]>, } -pub fn expand_trait_refs<'cx, 'gcx, 'tcx>( +impl<'tcx> TraitAliasExpansionInfo<'tcx> { + fn new(trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> TraitAliasExpansionInfo<'tcx> { + TraitAliasExpansionInfo { + items: smallvec![(trait_ref, span)] + } + } + + fn push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> TraitAliasExpansionInfo<'tcx> { + let mut items = self.items.clone(); + items.push((trait_ref, span)); + + TraitAliasExpansionInfo { + items + } + } + + pub fn trait_ref(&self) -> &ty::PolyTraitRef<'tcx> { + &self.top().0 + } + + pub fn top(&self) -> &(ty::PolyTraitRef<'tcx>, Span) { + self.items.last().unwrap() + } + + pub fn bottom(&self) -> &(ty::PolyTraitRef<'tcx>, Span) { + self.items.first().unwrap() + } +} + +pub trait TraitAliasExpansionInfoDignosticBuilder { + fn label_with_exp_info<'tcx>(&mut self, + info: &TraitAliasExpansionInfo<'tcx>, + top_label: &str + ) -> &mut Self; +} + +impl<'a> TraitAliasExpansionInfoDignosticBuilder for DiagnosticBuilder<'a> { + fn label_with_exp_info<'tcx>(&mut self, + info: &TraitAliasExpansionInfo<'tcx>, + top_label: &str + ) -> &mut Self { + self.span_label(info.top().1, top_label); + if info.items.len() > 1 { + for (_, sp) in info.items[1..(info.items.len() - 1)].iter().rev() { + self.span_label(*sp, "referenced here"); + } + } + self + } +} + +pub fn expand_trait_aliases<'cx, 'gcx, 'tcx>( tcx: TyCtxt<'cx, 'gcx, 'tcx>, trait_refs: impl IntoIterator, Span)> -) -> TraitRefExpander<'cx, 'gcx, 'tcx> { - let mut visited = PredicateSet::new(tcx); - let mut items: Vec<_> = - trait_refs - .into_iter() - .map(|(trait_ref, span)| TraitRefExpansionInfo { - top_level_trait_ref: trait_ref.clone(), - top_level_span: span, - trait_ref, - span, - }) - .collect(); - items.retain(|item| visited.insert(&item.trait_ref.to_predicate())); - TraitRefExpander { stack: items, visited } +) -> TraitAliasExpander<'cx, 'gcx, 'tcx> { + let items: Vec<_> = trait_refs + .into_iter() + .map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span)) + .collect(); + TraitAliasExpander { stack: items, visited: PredicateSet::new(tcx) } } -impl<'cx, 'gcx, 'tcx> TraitRefExpander<'cx, 'gcx, 'tcx> { - /// If `item` refers to a trait alias, adds the components of the trait alias to the stack, - /// and returns `false`. - /// If `item` refers to an ordinary trait, simply returns `true`. - fn push(&mut self, item: &TraitRefExpansionInfo<'tcx>) -> bool { +impl<'cx, 'gcx, 'tcx> TraitAliasExpander<'cx, 'gcx, 'tcx> { + /// If `item` is a trait alias and its predicate has not yet been visited, then expands `item` + /// to the definition and pushes the resulting expansion onto `self.stack`, and returns `false`. + /// Otherwise, immediately returns `true` if `item` is a regular trait and `false` if it is a + /// trait alias. + /// The return value indicates whether `item` should not be yielded to the user. + fn push(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool { let tcx = self.visited.tcx; + let trait_ref = item.trait_ref(); + let pred = trait_ref.to_predicate(); - if !tcx.is_trait_alias(item.trait_ref.def_id()) { - return true; + debug!("expand_trait_aliases: trait_ref={:?}", trait_ref); + + self.visited.remove(&pred); + + let is_alias = tcx.is_trait_alias(trait_ref.def_id()); + if !is_alias || self.visited.contains(&pred) { + return !is_alias; } - // Get components of the trait alias. - let predicates = tcx.super_predicates_of(item.trait_ref.def_id()); + // Get components of trait alias. + let predicates = tcx.super_predicates_of(trait_ref.def_id()); - let mut items: Vec<_> = predicates.predicates + let items: Vec<_> = predicates.predicates .iter() .rev() .filter_map(|(pred, span)| { - pred.subst_supertrait(tcx, &item.trait_ref) + pred.subst_supertrait(tcx, &trait_ref) .to_opt_poly_trait_ref() - .map(|trait_ref| - TraitRefExpansionInfo { - trait_ref, - span: *span, - ..*item - } - ) + .map(|trait_ref| item.push(trait_ref, *span)) }) .collect(); - - debug!("trait_ref_expander: trait_ref={:?} items={:?}", - item.trait_ref, items); - - // Only keep those items that we haven't already seen. - items.retain(|i| self.visited.insert(&i.trait_ref.to_predicate())); + debug!("expand_trait_aliases: items={:?}", items); self.stack.extend(items); + + // Record predicate into set of already-visited. + self.visited.insert(&pred); + false } } -impl<'cx, 'gcx, 'tcx> Iterator for TraitRefExpander<'cx, 'gcx, 'tcx> { - type Item = TraitRefExpansionInfo<'tcx>; +impl<'cx, 'gcx, 'tcx> Iterator for TraitAliasExpander<'cx, 'gcx, 'tcx> { + type Item = TraitAliasExpansionInfo<'tcx>; fn size_hint(&self) -> (usize, Option) { (self.stack.len(), None) } - fn next(&mut self) -> Option> { + fn next(&mut self) -> Option> { while let Some(item) = self.stack.pop() { if self.push(&item) { return Some(item); @@ -386,8 +454,8 @@ impl<'cx, 'gcx, 'tcx> Iterator for SupertraitDefIds<'cx, 'gcx, 'tcx> { self.stack.extend( predicates.predicates .iter() - .filter_map(|(p, _)| p.to_opt_poly_trait_ref()) - .map(|t| t.def_id()) + .filter_map(|(pred, _)| pred.to_opt_poly_trait_ref()) + .map(|trait_ref| trait_ref.def_id()) .filter(|&super_def_id| visited.insert(super_def_id))); Some(def_id) } @@ -413,17 +481,12 @@ impl<'tcx, I: Iterator>> Iterator for FilterToTraits< type Item = ty::PolyTraitRef<'tcx>; fn next(&mut self) -> Option> { - loop { - match self.base_iterator.next() { - None => { - return None; - } - Some(ty::Predicate::Trait(data)) => { - return Some(data.to_poly_trait_ref()); - } - Some(_) => {} + while let Some(pred) = self.base_iterator.next() { + if let ty::Predicate::Trait(data) = pred { + return Some(data.to_poly_trait_ref()); } } + None } fn size_hint(&self) -> (usize, Option) { diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 2bea1db841ae..d70c81854955 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -504,7 +504,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { any_lifetime_bounds = true; } } - self.no_questions_in_bounds(bounds, "trait object types", false); } TyKind::ImplTrait(_, ref bounds) => { if self.is_impl_trait_banned { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index e1dc0b10c9f9..428fa66101ac 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -11,7 +11,7 @@ use crate::lint; use crate::middle::resolve_lifetime as rl; use crate::namespace::Namespace; use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; -use rustc::traits; +use rustc::traits::{self, TraitAliasExpansionInfoDignosticBuilder}; use rustc::ty::{self, DefIdTree, Ty, TyCtxt, ToPredicate, TypeFoldable}; use rustc::ty::{GenericParamDef, GenericParamDefKind}; use rustc::ty::subst::{Kind, Subst, InternalSubsts, SubstsRef}; @@ -965,30 +965,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { ty::ExistentialTraitRef::erase_self_ty(self.tcx(), trait_ref) } - fn expand_trait_refs(&self, - trait_refs: impl IntoIterator, Span)> - ) -> Vec { - let tcx = self.tcx(); - - // Expand trait aliases recursively and check that only one regular (non-auto) trait - // is used. - let expanded_traits = traits::expand_trait_refs(tcx, trait_refs); - let (auto_traits, regular_traits): (Vec<_>, Vec<_>) = - expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref.def_id())); - if regular_traits.len() > 1 { - let extra_trait = ®ular_traits[1]; - let mut err = struct_span_err!(tcx.sess, extra_trait.top_level_span, E0225, - "only auto traits can be used as additional traits in a trait object"); - err.span_label(extra_trait.span, "non-auto additional trait"); - if extra_trait.span != extra_trait.top_level_span { - err.span_label(extra_trait.top_level_span, "expanded from this trait alias"); - } - err.emit(); - } - - auto_traits.into_iter().map(|i| i.trait_ref.def_id()).collect() - } - fn conv_object_ty_poly_trait_ref(&self, span: Span, trait_bounds: &[hir::PolyTraitRef], @@ -997,52 +973,69 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { { let tcx = self.tcx(); - if trait_bounds.is_empty() { + let mut projection_bounds = Vec::new(); + let mut potential_assoc_types = Vec::new(); + let dummy_self = self.tcx().types.trait_object_dummy_self; + let bound_trait_refs: Vec<_> = trait_bounds + .iter() + .rev() + .map(|trait_bound| { + let (trait_ref, cur_potential_assoc_types) = self.instantiate_poly_trait_ref( + trait_bound, + dummy_self, + &mut projection_bounds + ); + potential_assoc_types.extend(cur_potential_assoc_types.into_iter().flatten()); + (trait_ref, trait_bound.span) + }).collect(); + + // Expand trait aliases recursively and check that only one regular (non-auto) trait + // is used and no 'maybe' bounds are used. + let expanded_traits = traits::expand_trait_aliases(tcx, bound_trait_refs.clone()); + let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = + expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); + if regular_traits.len() > 1 { + let extra_trait = ®ular_traits[1]; + let mut err = struct_span_err!(tcx.sess, extra_trait.bottom().1, E0225, + "only auto traits can be used as additional traits in a trait object"); + err.label_with_exp_info(extra_trait, "additional non-auto trait"); + err.span_label(regular_traits[0].top().1, "first non-auto trait"); + err.emit(); + } + + if regular_traits.is_empty() && auto_traits.is_empty() { span_err!(tcx.sess, span, E0224, "at least one non-builtin trait is required for an object type"); return tcx.types.err; } - let mut projection_bounds = Vec::new(); - let dummy_self = self.tcx().types.trait_object_dummy_self; - let (principal, potential_assoc_types) = self.instantiate_poly_trait_ref( - &trait_bounds[0], - dummy_self, - &mut projection_bounds, - ); - debug!("principal: {:?}", principal); - - let mut bound_trait_refs = Vec::with_capacity(trait_bounds.len()); - for trait_bound in trait_bounds[1..].iter().rev() { - // Sanity check for non-principal trait bounds. - let (tr, _) = self.instantiate_poly_trait_ref( - trait_bound, - dummy_self, - &mut Vec::new() - ); - bound_trait_refs.push((tr, trait_bound.span)); - } - bound_trait_refs.push((principal, trait_bounds[0].span)); - - let mut auto_traits = self.expand_trait_refs(bound_trait_refs); - // Check that there are no gross object safety violations; // most importantly, that the supertraits don't contain `Self`, // to avoid ICEs. - let object_safety_violations = - tcx.global_tcx().astconv_object_safety_violations(principal.def_id()); - if !object_safety_violations.is_empty() { - tcx.report_object_safety_error(span, principal.def_id(), object_safety_violations) - .map(|mut err| err.emit()); - return tcx.types.err; + for item in ®ular_traits { + let object_safety_violations = + tcx.global_tcx().astconv_object_safety_violations(item.trait_ref().def_id()); + if !object_safety_violations.is_empty() { + tcx.report_object_safety_error( + span, + item.trait_ref().def_id(), + object_safety_violations + ) + .map(|mut err| err.emit()); + return tcx.types.err; + } } // Use a `BTreeSet` to keep output in a more consistent order. let mut associated_types = BTreeSet::default(); - for tr in traits::elaborate_trait_ref(tcx, principal) { - debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", tr); - match tr { + let regular_traits_refs = bound_trait_refs + .into_iter() + .filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id())) + .map(|(trait_ref, _)| trait_ref); + for trait_ref in traits::elaborate_trait_refs(tcx, regular_traits_refs) { + debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", trait_ref); + match trait_ref { ty::Predicate::Trait(pred) => { associated_types .extend(tcx.associated_items(pred.def_id()) @@ -1102,20 +1095,18 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { if associated_types.len() == 1 { "" } else { "s" }, names, ); - let mut suggest = false; - let mut potential_assoc_types_spans = vec![]; - if let Some(potential_assoc_types) = potential_assoc_types { + let (suggest, potential_assoc_types_spans) = if potential_assoc_types.len() == associated_types.len() { - // Only suggest when the amount of missing associated types is equals to the + // Only suggest when the amount of missing associated types equals the number of // extra type arguments present, as that gives us a relatively high confidence // that the user forgot to give the associtated type's name. The canonical // example would be trying to use `Iterator` instead of - // `Iterator`. - suggest = true; - potential_assoc_types_spans = potential_assoc_types; - } - } - let mut suggestions = vec![]; + // `Iterator`. + (true, potential_assoc_types) + } else { + (false, Vec::new()) + }; + let mut suggestions = Vec::new(); for (i, item_def_id) in associated_types.iter().enumerate() { let assoc_item = tcx.associated_item(*item_def_id); err.span_label( @@ -1151,9 +1142,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { err.emit(); } + // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as + // `dyn Trait + Send`. + auto_traits.sort_by_key(|i| i.trait_ref().def_id()); + auto_traits.dedup_by_key(|i| i.trait_ref().def_id()); + debug!("regular_traits: {:?}", regular_traits); + debug!("auto_traits: {:?}", auto_traits); + // Erase the `dummy_self` (`trait_object_dummy_self`) used above. - let existential_principal = principal.map_bound(|trait_ref| { - self.trait_ref_to_existential(trait_ref) + let existential_trait_refs = regular_traits.iter().map(|i| { + i.trait_ref().map_bound(|trait_ref| self.trait_ref_to_existential(trait_ref)) }); let existential_projections = projection_bounds.iter().map(|(bound, _)| { bound.map_bound(|b| { @@ -1166,21 +1164,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { }) }); - // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as - // `dyn Trait + Send`. - auto_traits.sort(); - auto_traits.dedup(); - debug!("auto_traits: {:?}", auto_traits); - // Calling `skip_binder` is okay because the predicates are re-bound. - let principal = if tcx.trait_is_auto(existential_principal.def_id()) { - ty::ExistentialPredicate::AutoTrait(existential_principal.def_id()) - } else { - ty::ExistentialPredicate::Trait(*existential_principal.skip_binder()) - }; + let regular_trait_predicates = existential_trait_refs.map( + |trait_ref| ty::ExistentialPredicate::Trait(*trait_ref.skip_binder())); + let auto_trait_predicates = auto_traits.into_iter().map( + |trait_ref| ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id())); let mut v = - iter::once(principal) - .chain(auto_traits.into_iter().map(ty::ExistentialPredicate::AutoTrait)) + regular_trait_predicates + .chain(auto_trait_predicates) .chain(existential_projections .map(|x| ty::ExistentialPredicate::Projection(*x.skip_binder()))) .collect::>(); From fd7c253accd46ea8340feb79ecaf18d99f518bb8 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Sat, 30 Mar 2019 22:06:09 +0000 Subject: [PATCH 0182/3207] Update tests. --- ...sociated-types-overridden-binding-2.stderr | 2 +- src/test/ui/bad/bad-sized.stderr | 4 +- src/test/ui/error-codes/E0225.stderr | 10 +- src/test/ui/issues/issue-22560.stderr | 30 +- src/test/ui/issues/issue-32963.stderr | 4 +- src/test/ui/maybe-bounds.rs | 4 +- src/test/ui/maybe-bounds.stderr | 14 +- .../ui/parser/trait-object-trait-parens.rs | 4 +- .../parser/trait-object-trait-parens.stderr | 16 +- src/test/ui/traits/trait-alias-object.rs | 9 - .../auxiliary/trait_alias.rs | 0 .../traits/trait-alias}/trait-alias-bounds.rs | 2 + .../trait-alias-cross-crate.rs | 0 .../trait-alias-cross-crate.stderr | 0 .../{ => trait-alias}/trait-alias-impl.rs | 0 .../{ => trait-alias}/trait-alias-impl.stderr | 0 .../trait-alias/trait-alias-maybe-bound.rs | 27 ++ .../trait-alias-maybe-bound.stderr | 14 + .../trait-alias/trait-alias-no-duplicates.rs | 126 ++++++ .../trait-alias-no-duplicates.stderr | 358 +++++++++++++++++ .../trait-alias-no-extra-traits.rs | 121 ++++++ .../trait-alias-no-extra-traits.stderr | 371 ++++++++++++++++++ .../trait-alias/trait-alias-object-fail.rs | 11 + .../trait-alias-object-fail.stderr} | 8 +- .../trait-alias/trait-alias-object-wf.rs | 71 ++++ .../traits/trait-alias}/trait-alias-object.rs | 2 + .../trait-alias-syntax-fail.rs} | 0 .../trait-alias-syntax-fail.stderr} | 4 +- .../traits/trait-alias}/trait-alias-syntax.rs | 2 + .../{ => trait-alias}/trait-alias-wf.rs | 0 .../{ => trait-alias}/trait-alias-wf.stderr | 0 .../trait-alias}/trait-alias.rs | 1 + .../traits-static-outlives-a-where-clause.rs | 0 .../ui/traits/wf-trait-object-maybe-bound.rs | 13 + .../traits/wf-trait-object-maybe-bound.stderr | 8 + .../traits/wf-trait-object-no-duplicates.rs | 33 ++ .../wf-trait-object-no-duplicates.stderr | 43 ++ .../traits/wf-trait-object-reverse-order.rs | 15 + 38 files changed, 1263 insertions(+), 64 deletions(-) delete mode 100644 src/test/ui/traits/trait-alias-object.rs rename src/test/ui/traits/{ => trait-alias}/auxiliary/trait_alias.rs (100%) rename src/test/{run-pass/traits => ui/traits/trait-alias}/trait-alias-bounds.rs (98%) rename src/test/ui/traits/{ => trait-alias}/trait-alias-cross-crate.rs (100%) rename src/test/ui/traits/{ => trait-alias}/trait-alias-cross-crate.stderr (100%) rename src/test/ui/traits/{ => trait-alias}/trait-alias-impl.rs (100%) rename src/test/ui/traits/{ => trait-alias}/trait-alias-impl.stderr (100%) create mode 100644 src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs create mode 100644 src/test/ui/traits/trait-alias/trait-alias-maybe-bound.stderr create mode 100644 src/test/ui/traits/trait-alias/trait-alias-no-duplicates.rs create mode 100644 src/test/ui/traits/trait-alias/trait-alias-no-duplicates.stderr create mode 100644 src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.rs create mode 100644 src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.stderr create mode 100644 src/test/ui/traits/trait-alias/trait-alias-object-fail.rs rename src/test/ui/traits/{trait-alias-object.stderr => trait-alias/trait-alias-object-fail.stderr} (70%) create mode 100644 src/test/ui/traits/trait-alias/trait-alias-object-wf.rs rename src/test/{run-pass/traits => ui/traits/trait-alias}/trait-alias-object.rs (96%) rename src/test/ui/traits/{trait-alias-syntax.rs => trait-alias/trait-alias-syntax-fail.rs} (100%) rename src/test/ui/traits/{trait-alias-syntax.stderr => trait-alias/trait-alias-syntax-fail.stderr} (77%) rename src/test/{run-pass/traits => ui/traits/trait-alias}/trait-alias-syntax.rs (97%) rename src/test/ui/traits/{ => trait-alias}/trait-alias-wf.rs (100%) rename src/test/ui/traits/{ => trait-alias}/trait-alias-wf.stderr (100%) rename src/test/ui/{run-pass/traits => traits/trait-alias}/trait-alias.rs (98%) rename src/test/ui/{run-pass => }/traits/traits-static-outlives-a-where-clause.rs (100%) create mode 100644 src/test/ui/traits/wf-trait-object-maybe-bound.rs create mode 100644 src/test/ui/traits/wf-trait-object-maybe-bound.stderr create mode 100644 src/test/ui/traits/wf-trait-object-no-duplicates.rs create mode 100644 src/test/ui/traits/wf-trait-object-no-duplicates.stderr create mode 100644 src/test/ui/traits/wf-trait-object-reverse-order.rs diff --git a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr index ad0b6515490b..85724cb7c6e8 100644 --- a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr +++ b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr @@ -6,7 +6,7 @@ LL | let _: &I32Iterator = &vec![42].into_iter(); | = note: expected type `u32` found type `i32` - = note: required for the cast to the object type `dyn I32Iterator` + = note: required for the cast to the object type `dyn std::iter::Iterator` error: aborting due to previous error diff --git a/src/test/ui/bad/bad-sized.stderr b/src/test/ui/bad/bad-sized.stderr index 321f97541587..671840acdbfe 100644 --- a/src/test/ui/bad/bad-sized.stderr +++ b/src/test/ui/bad/bad-sized.stderr @@ -2,7 +2,9 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec --> $DIR/bad-sized.rs:4:24 | LL | let x: Vec = Vec::new(); - | ^^^^^ non-auto additional trait + | ----- ^^^^^ additional non-auto trait + | | + | first non-auto trait error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time --> $DIR/bad-sized.rs:4:12 diff --git a/src/test/ui/error-codes/E0225.stderr b/src/test/ui/error-codes/E0225.stderr index c8d8f07db8ae..183cf0aad643 100644 --- a/src/test/ui/error-codes/E0225.stderr +++ b/src/test/ui/error-codes/E0225.stderr @@ -2,16 +2,20 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec --> $DIR/E0225.rs:6:32 | LL | let _: Box; - | ^^^^^^^^^^^^^^ non-auto additional trait + | ------------- ^^^^^^^^^^^^^^ additional non-auto trait + | | + | first non-auto trait error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/E0225.rs:8:16 | LL | trait Foo = std::io::Read + std::io::Write; - | -------------- non-auto additional trait + | ------------- -------------- additional non-auto trait + | | + | first non-auto trait ... LL | let _: Box; - | ^^^ expanded from this alias + | ^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-22560.stderr b/src/test/ui/issues/issue-22560.stderr index 5a056dff590f..2c6f4d9d45f7 100644 --- a/src/test/ui/issues/issue-22560.stderr +++ b/src/test/ui/issues/issue-22560.stderr @@ -1,3 +1,11 @@ +error[E0393]: the type parameter `Rhs` must be explicitly specified + --> $DIR/issue-22560.rs:6:13 + | +LL | Sub; + | ^^^ missing reference to `Rhs` + | + = note: because of the default `Self` reference, type parameters must be specified on object types + error[E0393]: the type parameter `Rhs` must be explicitly specified --> $DIR/issue-22560.rs:3:13 | @@ -6,29 +14,29 @@ LL | type Test = Add + | = note: because of the default `Self` reference, type parameters must be specified on object types -error[E0393]: the type parameter `Rhs` must be explicitly specified - --> $DIR/issue-22560.rs:6:13 - | -LL | Sub; - | ^^^ missing reference to `Rhs` - | - = note: because of the default `Self` reference, type parameters must be specified on object types - error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/issue-22560.rs:6:13 | +LL | type Test = Add + + | --- first non-auto trait +... LL | Sub; - | ^^^ non-auto additional trait + | ^^^ additional non-auto trait -error[E0191]: the value of the associated type `Output` (from the trait `std::ops::Add`) must be specified +error[E0191]: the value of the associated types `Output` (from the trait `std::ops::Add`), `Output` (from the trait `std::ops::Sub`) must be specified --> $DIR/issue-22560.rs:3:13 | LL | type Test = Add + | _____________^ + | |_____________| + | | LL | | LL | | LL | | Sub; - | |_______________^ associated type `Output` must be specified + | | ^ + | |_______________| + | |_______________associated type `Output` must be specified + | associated type `Output` must be specified error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-32963.stderr b/src/test/ui/issues/issue-32963.stderr index 70fda313170d..381ccdbeb999 100644 --- a/src/test/ui/issues/issue-32963.stderr +++ b/src/test/ui/issues/issue-32963.stderr @@ -2,7 +2,9 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec --> $DIR/issue-32963.rs:8:25 | LL | size_of_copy::(); - | ^^^^ non-auto additional trait + | ---- ^^^^ additional non-auto trait + | | + | first non-auto trait error[E0277]: the trait bound `dyn Misc: std::marker::Copy` is not satisfied --> $DIR/issue-32963.rs:8:5 diff --git a/src/test/ui/maybe-bounds.rs b/src/test/ui/maybe-bounds.rs index 3e07026fb7d7..7defd8d3943b 100644 --- a/src/test/ui/maybe-bounds.rs +++ b/src/test/ui/maybe-bounds.rs @@ -1,6 +1,6 @@ trait Tr: ?Sized {} //~ ERROR `?Trait` is not permitted in supertraits -type A1 = Tr + (?Sized); //~ ERROR `?Trait` is not permitted in trait object types -type A2 = for<'a> Tr + (?Sized); //~ ERROR `?Trait` is not permitted in trait object types +type A1 = Tr + (?Sized); +type A2 = for<'a> Tr + (?Sized); fn main() {} diff --git a/src/test/ui/maybe-bounds.stderr b/src/test/ui/maybe-bounds.stderr index 20446c257df0..d8c2adfc61c5 100644 --- a/src/test/ui/maybe-bounds.stderr +++ b/src/test/ui/maybe-bounds.stderr @@ -6,17 +6,5 @@ LL | trait Tr: ?Sized {} | = note: traits are `?Sized` by default -error: `?Trait` is not permitted in trait object types - --> $DIR/maybe-bounds.rs:3:16 - | -LL | type A1 = Tr + (?Sized); - | ^^^^^^^^ - -error: `?Trait` is not permitted in trait object types - --> $DIR/maybe-bounds.rs:4:24 - | -LL | type A2 = for<'a> Tr + (?Sized); - | ^^^^^^^^ - -error: aborting due to 3 previous errors +error: aborting due to previous error diff --git a/src/test/ui/parser/trait-object-trait-parens.rs b/src/test/ui/parser/trait-object-trait-parens.rs index 2bbc5800015b..49373564f673 100644 --- a/src/test/ui/parser/trait-object-trait-parens.rs +++ b/src/test/ui/parser/trait-object-trait-parens.rs @@ -4,9 +4,7 @@ fn f Trait<'a>)>() {} fn main() { let _: Box<(Copy) + (?Sized) + (for<'a> Trait<'a>)>; - //~^ ERROR `?Trait` is not permitted in trait object types let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Copy)>; let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>; - //~^ ERROR `?Trait` is not permitted in trait object types - //~| ERROR use of undeclared lifetime name `'a` + //~^ ERROR use of undeclared lifetime name `'a` } diff --git a/src/test/ui/parser/trait-object-trait-parens.stderr b/src/test/ui/parser/trait-object-trait-parens.stderr index 36494b765394..1cf40b30406c 100644 --- a/src/test/ui/parser/trait-object-trait-parens.stderr +++ b/src/test/ui/parser/trait-object-trait-parens.stderr @@ -1,21 +1,9 @@ -error: `?Trait` is not permitted in trait object types - --> $DIR/trait-object-trait-parens.rs:6:25 - | -LL | let _: Box<(Copy) + (?Sized) + (for<'a> Trait<'a>)>; - | ^^^^^^^^ - -error: `?Trait` is not permitted in trait object types - --> $DIR/trait-object-trait-parens.rs:9:47 - | -LL | let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>; - | ^^^^^^^^ - error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/trait-object-trait-parens.rs:9:31 + --> $DIR/trait-object-trait-parens.rs:8:31 | LL | let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>; | ^^ undeclared lifetime -error: aborting due to 3 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0261`. diff --git a/src/test/ui/traits/trait-alias-object.rs b/src/test/ui/traits/trait-alias-object.rs deleted file mode 100644 index 379637401179..000000000000 --- a/src/test/ui/traits/trait-alias-object.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(trait_alias)] - -trait EqAlias = Eq; -trait IteratorAlias = Iterator; - -fn main() { - let _: &dyn EqAlias = &123; //~ ERROR `EqAlias` cannot be made into an object - let _: &dyn IteratorAlias = &vec![123].into_iter(); //~ ERROR must be specified -} diff --git a/src/test/ui/traits/auxiliary/trait_alias.rs b/src/test/ui/traits/trait-alias/auxiliary/trait_alias.rs similarity index 100% rename from src/test/ui/traits/auxiliary/trait_alias.rs rename to src/test/ui/traits/trait-alias/auxiliary/trait_alias.rs diff --git a/src/test/run-pass/traits/trait-alias-bounds.rs b/src/test/ui/traits/trait-alias/trait-alias-bounds.rs similarity index 98% rename from src/test/run-pass/traits/trait-alias-bounds.rs rename to src/test/ui/traits/trait-alias/trait-alias-bounds.rs index d3dd5cee0c33..428ce5102bad 100644 --- a/src/test/run-pass/traits/trait-alias-bounds.rs +++ b/src/test/ui/traits/trait-alias/trait-alias-bounds.rs @@ -1,3 +1,5 @@ +// run-pass + #![feature(trait_alias)] use std::marker::PhantomData; diff --git a/src/test/ui/traits/trait-alias-cross-crate.rs b/src/test/ui/traits/trait-alias/trait-alias-cross-crate.rs similarity index 100% rename from src/test/ui/traits/trait-alias-cross-crate.rs rename to src/test/ui/traits/trait-alias/trait-alias-cross-crate.rs diff --git a/src/test/ui/traits/trait-alias-cross-crate.stderr b/src/test/ui/traits/trait-alias/trait-alias-cross-crate.stderr similarity index 100% rename from src/test/ui/traits/trait-alias-cross-crate.stderr rename to src/test/ui/traits/trait-alias/trait-alias-cross-crate.stderr diff --git a/src/test/ui/traits/trait-alias-impl.rs b/src/test/ui/traits/trait-alias/trait-alias-impl.rs similarity index 100% rename from src/test/ui/traits/trait-alias-impl.rs rename to src/test/ui/traits/trait-alias/trait-alias-impl.rs diff --git a/src/test/ui/traits/trait-alias-impl.stderr b/src/test/ui/traits/trait-alias/trait-alias-impl.stderr similarity index 100% rename from src/test/ui/traits/trait-alias-impl.stderr rename to src/test/ui/traits/trait-alias/trait-alias-impl.stderr diff --git a/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs b/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs new file mode 100644 index 000000000000..f444dba5d289 --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs @@ -0,0 +1,27 @@ +// Test that `dyn ... + ?Sized + ...` resulting from the expansion of trait aliases is okay. + +#![feature(trait_alias)] + +trait S = ?Sized; + +// Nest a couple of levels deep: +trait _0 = S; +trait _1 = _0; + +// Straight list expansion: +type _T0 = dyn _1; +//~^ ERROR at least one non-builtin trait is required for an object type [E0224] + +// In second position: +type _T1 = dyn Copy + _1; + +// ... and with an auto trait: +type _T2 = dyn Copy + Send + _1; + +// Twice: +trait _2 = _1 + _1; + +type _T3 = dyn _2; +//~^ ERROR at least one non-builtin trait is required for an object type [E0224] + +fn main() {} diff --git a/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.stderr b/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.stderr new file mode 100644 index 000000000000..52e90c00c374 --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.stderr @@ -0,0 +1,14 @@ +error[E0224]: at least one non-builtin trait is required for an object type + --> $DIR/trait-alias-maybe-bound.rs:12:12 + | +LL | type _T0 = dyn _1; + | ^^^^^^ + +error[E0224]: at least one non-builtin trait is required for an object type + --> $DIR/trait-alias-maybe-bound.rs:24:12 + | +LL | type _T3 = dyn _2; + | ^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.rs b/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.rs new file mode 100644 index 000000000000..95525883c643 --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.rs @@ -0,0 +1,126 @@ +// The purpose of this test is to demonstrate that duplicating object safe traits +// that are not auto traits is rejected with trait aliases even though one could +// reasonably accept this. + +#![feature(trait_alias)] + +use std::marker::Unpin; + +// Some arbitray object-safe trait: +trait Obj {} + +// Nest a few levels deep: +trait _0 = Obj; +trait _1 = _0; + +type _T00 = dyn _0 + _0; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T01 = dyn _1 + _0; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T02 = dyn _1 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T03 = dyn Obj + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T04 = dyn _1 + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Nest some more and in weird ways: + +trait _2 = _0 + _1; +trait _3 = Obj; +trait _4 = _3; + +type _T10 = dyn _2 + _3; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T11 = dyn _3 + _2; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T12 = dyn Obj + _2; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T13 = dyn _2 + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T14 = dyn _1 + _3; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T15 = dyn _3 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T16 = dyn _1 + _4; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T17 = dyn _4 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Include auto traits: + +trait _5 = Obj + Send; + +type _T20 = dyn _5 + _5; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T21 = dyn Obj + _5; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T22 = dyn _5 + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T23 = dyn _5 + Send + Sync + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Also nest: + +trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send + +type _T30 = dyn _6; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T31 = dyn _6 + Send; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T32 = dyn Send + _6; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Nest some more: + +trait _7 = _5 + Sync; +trait _8 = Unpin + _7; + +type _T40 = dyn _8 + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T41 = dyn Obj + _8; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T42 = dyn _8 + _4; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T43 = dyn _4 + _8; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T44 = dyn _4 + Send + Sync + _8; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Take higher ranked types into account. + +// Note that `'a` and `'b` are intentionally different to make sure we consider +// them semantically the same. +trait ObjL<'l> {} +trait _9 = for<'a> ObjL<'a>; +trait _10 = for<'b> ObjL<'b>; +type _T50 = _9 + _10; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +trait ObjT {} +trait _11 = ObjT fn(&'a u8)>; +trait _12 = ObjT fn(&'b u8)>; +type _T60 = _11 + _12; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +fn main() {} diff --git a/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.stderr b/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.stderr new file mode 100644 index 000000000000..3cdf1582ab9c --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.stderr @@ -0,0 +1,358 @@ +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:16:22 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +... +LL | type _T00 = dyn _0 + _0; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:19:22 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +... +LL | type _T01 = dyn _1 + _0; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:22:22 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _1 = _0; + | -- referenced here +... +LL | type _T02 = dyn _1 + _1; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:25:23 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here +... +LL | type _T03 = dyn Obj + _1; + | --- ^^ + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:28:22 + | +LL | trait _0 = Obj; + | --- first non-auto trait +... +LL | type _T04 = dyn _1 + Obj; + | ^^^ additional non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:37:17 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _1 = _0; + | -- referenced here +... +LL | trait _2 = _0 + _1; + | -- referenced here +... +LL | type _T10 = dyn _2 + _3; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:40:22 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +... +LL | trait _2 = _0 + _1; + | -- referenced here +LL | trait _3 = Obj; + | --- first non-auto trait +... +LL | type _T11 = dyn _3 + _2; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:43:23 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +... +LL | trait _2 = _0 + _1; + | -- referenced here +... +LL | type _T12 = dyn Obj + _2; + | --- ^^ + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:46:17 + | +LL | trait _0 = Obj; + | --- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _1 = _0; + | -- referenced here +... +LL | trait _2 = _0 + _1; + | -- referenced here +... +LL | type _T13 = dyn _2 + Obj; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:49:22 + | +LL | trait _0 = Obj; + | --- first non-auto trait +... +LL | trait _3 = Obj; + | --- additional non-auto trait +... +LL | type _T14 = dyn _1 + _3; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:52:22 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here +... +LL | trait _3 = Obj; + | --- first non-auto trait +... +LL | type _T15 = dyn _3 + _1; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:55:22 + | +LL | trait _0 = Obj; + | --- first non-auto trait +... +LL | trait _3 = Obj; + | --- additional non-auto trait +LL | trait _4 = _3; + | -- referenced here +... +LL | type _T16 = dyn _1 + _4; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:58:22 + | +LL | trait _0 = Obj; + | --- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here +... +LL | trait _3 = Obj; + | --- first non-auto trait +... +LL | type _T17 = dyn _4 + _1; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:65:22 + | +LL | trait _5 = Obj + Send; + | --- + | | + | additional non-auto trait + | first non-auto trait +LL | +LL | type _T20 = dyn _5 + _5; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:68:23 + | +LL | trait _5 = Obj + Send; + | --- additional non-auto trait +... +LL | type _T21 = dyn Obj + _5; + | --- ^^ + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:71:22 + | +LL | trait _5 = Obj + Send; + | --- first non-auto trait +... +LL | type _T22 = dyn _5 + Obj; + | ^^^ additional non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:74:36 + | +LL | trait _5 = Obj + Send; + | --- first non-auto trait +... +LL | type _T23 = dyn _5 + Send + Sync + Obj; + | ^^^ additional non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:81:17 + | +LL | trait _5 = Obj + Send; + | --- + | | + | additional non-auto trait + | first non-auto trait +... +LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send + | -- referenced here +LL | +LL | type _T30 = dyn _6; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:84:17 + | +LL | trait _5 = Obj + Send; + | --- + | | + | additional non-auto trait + | first non-auto trait +... +LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send + | -- referenced here +... +LL | type _T31 = dyn _6 + Send; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:87:24 + | +LL | trait _5 = Obj + Send; + | --- + | | + | additional non-auto trait + | first non-auto trait +... +LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send + | -- referenced here +... +LL | type _T32 = dyn Send + _6; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:95:22 + | +LL | trait _5 = Obj + Send; + | --- first non-auto trait +... +LL | type _T40 = dyn _8 + Obj; + | ^^^ additional non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:98:23 + | +LL | trait _5 = Obj + Send; + | --- additional non-auto trait +... +LL | trait _7 = _5 + Sync; + | -- referenced here +LL | trait _8 = Unpin + _7; + | -- referenced here +... +LL | type _T41 = dyn Obj + _8; + | --- ^^ + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:101:22 + | +LL | trait _3 = Obj; + | --- additional non-auto trait +LL | trait _4 = _3; + | -- referenced here +... +LL | trait _5 = Obj + Send; + | --- first non-auto trait +... +LL | type _T42 = dyn _8 + _4; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:104:22 + | +LL | trait _3 = Obj; + | --- first non-auto trait +... +LL | trait _5 = Obj + Send; + | --- additional non-auto trait +... +LL | trait _7 = _5 + Sync; + | -- referenced here +LL | trait _8 = Unpin + _7; + | -- referenced here +... +LL | type _T43 = dyn _4 + _8; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:107:36 + | +LL | trait _3 = Obj; + | --- first non-auto trait +... +LL | trait _5 = Obj + Send; + | --- additional non-auto trait +... +LL | trait _7 = _5 + Sync; + | -- referenced here +LL | trait _8 = Unpin + _7; + | -- referenced here +... +LL | type _T44 = dyn _4 + Send + Sync + _8; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:117:18 + | +LL | trait _9 = for<'a> ObjL<'a>; + | ---------------- first non-auto trait +LL | trait _10 = for<'b> ObjL<'b>; + | ---------------- additional non-auto trait +LL | type _T50 = _9 + _10; + | ^^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-duplicates.rs:123:19 + | +LL | trait _11 = ObjT fn(&'a u8)>; + | ------------------------ first non-auto trait +LL | trait _12 = ObjT fn(&'b u8)>; + | ------------------------ additional non-auto trait +LL | type _T60 = _11 + _12; + | ^^^ + +error: aborting due to 27 previous errors + +For more information about this error, try `rustc --explain E0225`. diff --git a/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.rs b/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.rs new file mode 100644 index 000000000000..54c177f0db80 --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.rs @@ -0,0 +1,121 @@ +// The purpose of this test is to demonstrate that trait alias expansion +// preserves the rule that `dyn Trait` may only reference one non-auto trait. + +#![feature(trait_alias)] + +use std::marker::Unpin; + +// Some arbitray object-safe traits: +trait ObjA {} +trait ObjB {} + +// Nest a few levels deep: +trait _0 = ObjA; +trait _1 = _0; + +type _T00 = dyn _0 + ObjB; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T01 = dyn ObjB + _0; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T02 = dyn ObjB + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T03 = dyn _1 + ObjB; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Nest some more and in weird ways: + +trait _2 = ObjB; +trait _3 = _2; +trait _4 = _3; + +type _T10 = dyn _2 + _3; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T11 = dyn _3 + _2; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T12 = dyn _2 + _4; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T13 = dyn _4 + _2; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Include auto traits: + +trait _5 = Sync + ObjB + Send; + +type _T20 = dyn _5 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T21 = dyn _1 + _5; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T22 = dyn _5 + ObjA; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T23 = dyn ObjA + _5; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T24 = dyn Send + _5 + _1 + Sync; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T25 = dyn _1 + Sync + _5 + Send; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T26 = dyn Sync + Send + _5 + ObjA; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T27 = dyn Send + Sync + ObjA + _5; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Also nest: + +trait _6 = _1 + _5; +trait _7 = _6; +trait _8 = _7; + +type _T30 = dyn _6; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T31 = dyn _6 + Send; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T32 = dyn Send + _6; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T33 = dyn _8; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T34 = dyn _8 + Send; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T35 = dyn Send + _8; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Nest some more: + +trait _9 = _5 + Sync; +trait _10 = Unpin + _9; + +type _T40 = dyn _10 + ObjA; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T41 = dyn ObjA + _10; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T42 = dyn _10 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T43 = dyn Send + _10 + Sync + ObjA; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T44 = dyn ObjA + _10 + Send + Sync; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _T45 = dyn Sync + Send + _10 + _1; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +fn main() {} diff --git a/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.stderr b/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.stderr new file mode 100644 index 000000000000..d73667a07097 --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.stderr @@ -0,0 +1,371 @@ +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:16:22 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +... +LL | type _T00 = dyn _0 + ObjB; + | ^^^^ additional non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:19:24 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +... +LL | type _T01 = dyn ObjB + _0; + | ---- ^^ + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:22:24 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here +... +LL | type _T02 = dyn ObjB + _1; + | ---- ^^ + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:25:22 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +... +LL | type _T03 = dyn _1 + ObjB; + | ^^^^ additional non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:34:22 + | +LL | trait _2 = ObjB; + | ---- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _3 = _2; + | -- referenced here +... +LL | type _T10 = dyn _2 + _3; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:37:22 + | +LL | trait _2 = ObjB; + | ---- + | | + | additional non-auto trait + | first non-auto trait +... +LL | type _T11 = dyn _3 + _2; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:40:22 + | +LL | trait _2 = ObjB; + | ---- + | | + | additional non-auto trait + | first non-auto trait +LL | trait _3 = _2; + | -- referenced here +LL | trait _4 = _3; + | -- referenced here +... +LL | type _T12 = dyn _2 + _4; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:43:22 + | +LL | trait _2 = ObjB; + | ---- + | | + | additional non-auto trait + | first non-auto trait +... +LL | type _T13 = dyn _4 + _2; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:50:22 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here +... +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +LL | +LL | type _T20 = dyn _5 + _1; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:53:22 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | type _T21 = dyn _1 + _5; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:56:22 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | type _T22 = dyn _5 + ObjA; + | ^^^^ additional non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:59:24 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | type _T23 = dyn ObjA + _5; + | ---- ^^ + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:62:29 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here +... +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | type _T24 = dyn Send + _5 + _1 + Sync; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:65:29 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | type _T25 = dyn _1 + Sync + _5 + Send; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:68:36 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | type _T26 = dyn Sync + Send + _5 + ObjA; + | ^^^^ additional non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:71:38 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | type _T27 = dyn Send + Sync + ObjA + _5; + | ---- ^^ + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:80:17 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- referenced here +... +LL | type _T30 = dyn _6; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:83:17 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- referenced here +... +LL | type _T31 = dyn _6 + Send; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:86:24 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- referenced here +... +LL | type _T32 = dyn Send + _6; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:89:17 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- referenced here +LL | trait _7 = _6; + | -- referenced here +LL | trait _8 = _7; + | -- referenced here +... +LL | type _T33 = dyn _8; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:92:17 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- referenced here +LL | trait _7 = _6; + | -- referenced here +LL | trait _8 = _7; + | -- referenced here +... +LL | type _T34 = dyn _8 + Send; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:95:24 + | +LL | trait _0 = ObjA; + | ---- first non-auto trait +... +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _6 = _1 + _5; + | -- referenced here +LL | trait _7 = _6; + | -- referenced here +LL | trait _8 = _7; + | -- referenced here +... +LL | type _T35 = dyn Send + _8; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:103:23 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | type _T40 = dyn _10 + ObjA; + | ^^^^ additional non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:106:24 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _9 = _5 + Sync; + | -- referenced here +LL | trait _10 = Unpin + _9; + | -- referenced here +... +LL | type _T41 = dyn ObjA + _10; + | ---- ^^^ + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:109:23 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here +... +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | type _T42 = dyn _10 + _1; + | ^^ + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:112:37 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | type _T43 = dyn Send + _10 + Sync + ObjA; + | ^^^^ additional non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:115:24 + | +LL | trait _5 = Sync + ObjB + Send; + | ---- additional non-auto trait +... +LL | trait _9 = _5 + Sync; + | -- referenced here +LL | trait _10 = Unpin + _9; + | -- referenced here +... +LL | type _T44 = dyn ObjA + _10 + Send + Sync; + | ---- ^^^ + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/trait-alias-no-extra-traits.rs:118:37 + | +LL | trait _0 = ObjA; + | ---- additional non-auto trait +LL | trait _1 = _0; + | -- referenced here +... +LL | trait _5 = Sync + ObjB + Send; + | ---- first non-auto trait +... +LL | type _T45 = dyn Sync + Send + _10 + _1; + | ^^ + +error: aborting due to 28 previous errors + +For more information about this error, try `rustc --explain E0225`. diff --git a/src/test/ui/traits/trait-alias/trait-alias-object-fail.rs b/src/test/ui/traits/trait-alias/trait-alias-object-fail.rs new file mode 100644 index 000000000000..d62fd7e59c92 --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-object-fail.rs @@ -0,0 +1,11 @@ +#![feature(trait_alias)] + +trait EqAlias = Eq; +trait IteratorAlias = Iterator; + +fn main() { + let _: &dyn EqAlias = &123; + //~^ ERROR the trait `std::cmp::Eq` cannot be made into an object [E0038] + let _: &dyn IteratorAlias = &vec![123].into_iter(); + //~^ ERROR must be specified +} diff --git a/src/test/ui/traits/trait-alias-object.stderr b/src/test/ui/traits/trait-alias/trait-alias-object-fail.stderr similarity index 70% rename from src/test/ui/traits/trait-alias-object.stderr rename to src/test/ui/traits/trait-alias/trait-alias-object-fail.stderr index 353aea311e90..9a9b91770308 100644 --- a/src/test/ui/traits/trait-alias-object.stderr +++ b/src/test/ui/traits/trait-alias/trait-alias-object-fail.stderr @@ -1,13 +1,13 @@ -error[E0038]: the trait `EqAlias` cannot be made into an object - --> $DIR/trait-alias-object.rs:7:13 +error[E0038]: the trait `std::cmp::Eq` cannot be made into an object + --> $DIR/trait-alias-object-fail.rs:7:13 | LL | let _: &dyn EqAlias = &123; - | ^^^^^^^^^^^ the trait `EqAlias` cannot be made into an object + | ^^^^^^^^^^^ the trait `std::cmp::Eq` cannot be made into an object | = note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses error[E0191]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified - --> $DIR/trait-alias-object.rs:8:13 + --> $DIR/trait-alias-object-fail.rs:9:13 | LL | let _: &dyn IteratorAlias = &vec![123].into_iter(); | ^^^^^^^^^^^^^^^^^ associated type `Item` must be specified diff --git a/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs b/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs new file mode 100644 index 000000000000..6383e8b6e10f --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs @@ -0,0 +1,71 @@ +// run-pass + +// This test checks that trait objects involving trait aliases are well-formed. + +#![feature(trait_alias)] + +trait Obj {} + +trait _0 = Send + Sync; + +// Just auto traits: + +trait _1 = _0 + Send + Sync; + +use std::marker::Unpin; + +type _T01 = dyn _0; +type _T02 = dyn _1; +type _T03 = dyn Unpin + _1 + Send + Sync; + +// Include object safe traits: + +type _T10 = dyn Obj + _0; +type _T11 = dyn Obj + _1; +type _T12 = dyn Obj + _1 + _0; + +// And when the object safe trait is in a trait alias: + +trait _2 = Obj; + +type _T20 = dyn _2 + _0; +type _T21 = dyn _2 + _1; +type _T22 = dyn _2 + _1 + _0; + +// And it should also work when that trait is has auto traits to the right of it. + +trait _3 = Obj + Unpin; + +type _T30 = dyn _3 + _0; +type _T31 = dyn _3 + _1; +type _T32 = dyn _3 + _1 + _0; + +// Nest the trait deeply: + +trait _4 = _3; +trait _5 = _4 + Sync + _0 + Send; +trait _6 = _5 + Send + _1 + Sync; + +type _T60 = dyn _6 + _0; +type _T61 = dyn _6 + _1; +type _T62 = dyn _6 + _1 + _0; + +// Just nest the trait alone: + +trait _7 = _2; +trait _8 = _7; +trait _9 = _8; + +type _T9 = dyn _9; + +// First bound is auto trait: + +trait _10 = Send + Obj; +trait _11 = Obj + Send; +trait _12 = Sync + _11; +trait _13 = Send + _12; + +type _T70 = dyn _0; +type _T71 = dyn _3; + +fn main() {} diff --git a/src/test/run-pass/traits/trait-alias-object.rs b/src/test/ui/traits/trait-alias/trait-alias-object.rs similarity index 96% rename from src/test/run-pass/traits/trait-alias-object.rs rename to src/test/ui/traits/trait-alias/trait-alias-object.rs index 1cf9e34edf30..12177cd827fd 100644 --- a/src/test/run-pass/traits/trait-alias-object.rs +++ b/src/test/ui/traits/trait-alias/trait-alias-object.rs @@ -1,3 +1,5 @@ +// run-pass + #![feature(trait_alias)] trait Foo = PartialEq + Send; diff --git a/src/test/ui/traits/trait-alias-syntax.rs b/src/test/ui/traits/trait-alias/trait-alias-syntax-fail.rs similarity index 100% rename from src/test/ui/traits/trait-alias-syntax.rs rename to src/test/ui/traits/trait-alias/trait-alias-syntax-fail.rs diff --git a/src/test/ui/traits/trait-alias-syntax.stderr b/src/test/ui/traits/trait-alias/trait-alias-syntax-fail.stderr similarity index 77% rename from src/test/ui/traits/trait-alias-syntax.stderr rename to src/test/ui/traits/trait-alias/trait-alias-syntax-fail.stderr index f99cc45d8ae9..f456a2d778c2 100644 --- a/src/test/ui/traits/trait-alias-syntax.stderr +++ b/src/test/ui/traits/trait-alias/trait-alias-syntax-fail.stderr @@ -1,11 +1,11 @@ error: trait aliases cannot be `auto` - --> $DIR/trait-alias-syntax.rs:4:19 + --> $DIR/trait-alias-syntax-fail.rs:4:19 | LL | auto trait A = Foo; | ^ trait aliases cannot be `auto` error: trait aliases cannot be `unsafe` - --> $DIR/trait-alias-syntax.rs:5:21 + --> $DIR/trait-alias-syntax-fail.rs:5:21 | LL | unsafe trait B = Foo; | ^ trait aliases cannot be `unsafe` diff --git a/src/test/run-pass/traits/trait-alias-syntax.rs b/src/test/ui/traits/trait-alias/trait-alias-syntax.rs similarity index 97% rename from src/test/run-pass/traits/trait-alias-syntax.rs rename to src/test/ui/traits/trait-alias/trait-alias-syntax.rs index 7cdd9184d3f5..17557a51aa72 100644 --- a/src/test/run-pass/traits/trait-alias-syntax.rs +++ b/src/test/ui/traits/trait-alias/trait-alias-syntax.rs @@ -1,3 +1,5 @@ +// run-pass + #![feature(trait_alias)] trait SimpleAlias = Default; diff --git a/src/test/ui/traits/trait-alias-wf.rs b/src/test/ui/traits/trait-alias/trait-alias-wf.rs similarity index 100% rename from src/test/ui/traits/trait-alias-wf.rs rename to src/test/ui/traits/trait-alias/trait-alias-wf.rs diff --git a/src/test/ui/traits/trait-alias-wf.stderr b/src/test/ui/traits/trait-alias/trait-alias-wf.stderr similarity index 100% rename from src/test/ui/traits/trait-alias-wf.stderr rename to src/test/ui/traits/trait-alias/trait-alias-wf.stderr diff --git a/src/test/ui/run-pass/traits/trait-alias.rs b/src/test/ui/traits/trait-alias/trait-alias.rs similarity index 98% rename from src/test/ui/run-pass/traits/trait-alias.rs rename to src/test/ui/traits/trait-alias/trait-alias.rs index 9be5664869e0..d8168f2990c4 100644 --- a/src/test/ui/run-pass/traits/trait-alias.rs +++ b/src/test/ui/traits/trait-alias/trait-alias.rs @@ -1,4 +1,5 @@ // run-pass + #![feature(trait_alias)] pub trait Foo {} diff --git a/src/test/ui/run-pass/traits/traits-static-outlives-a-where-clause.rs b/src/test/ui/traits/traits-static-outlives-a-where-clause.rs similarity index 100% rename from src/test/ui/run-pass/traits/traits-static-outlives-a-where-clause.rs rename to src/test/ui/traits/traits-static-outlives-a-where-clause.rs diff --git a/src/test/ui/traits/wf-trait-object-maybe-bound.rs b/src/test/ui/traits/wf-trait-object-maybe-bound.rs new file mode 100644 index 000000000000..68f0155faf9b --- /dev/null +++ b/src/test/ui/traits/wf-trait-object-maybe-bound.rs @@ -0,0 +1,13 @@ +// The purpose of this test is to demonstrate that `?Sized` is allowed in trait objects +// (thought it has no effect). + +type _0 = dyn ?Sized; +//~^ ERROR at least one non-builtin trait is required for an object type [E0224] + +type _1 = dyn Clone + ?Sized; + +type _2 = dyn Clone + ?Sized + ?Sized; + +type _3 = dyn ?Sized + Clone; + +fn main() {} diff --git a/src/test/ui/traits/wf-trait-object-maybe-bound.stderr b/src/test/ui/traits/wf-trait-object-maybe-bound.stderr new file mode 100644 index 000000000000..ba24b8342118 --- /dev/null +++ b/src/test/ui/traits/wf-trait-object-maybe-bound.stderr @@ -0,0 +1,8 @@ +error[E0224]: at least one non-builtin trait is required for an object type + --> $DIR/wf-trait-object-maybe-bound.rs:4:11 + | +LL | type _0 = dyn ?Sized; + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/traits/wf-trait-object-no-duplicates.rs b/src/test/ui/traits/wf-trait-object-no-duplicates.rs new file mode 100644 index 000000000000..dd6d73619bce --- /dev/null +++ b/src/test/ui/traits/wf-trait-object-no-duplicates.rs @@ -0,0 +1,33 @@ +// The purpose of this test is to demonstrate that duplicating object safe traits +// that are not auto-traits is rejected even though one could reasonably accept this. + +// Some arbitray object-safe trait: +trait Obj {} + +// Demonstrate that recursive expansion of trait aliases doesn't affect stable behavior: +type _0 = dyn Obj + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +// Some variations: + +type _1 = dyn Send + Obj + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _2 = dyn Obj + Send + Obj; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +type _3 = dyn Obj + Send + Send; // But it is OK to duplicate auto traits. + +// Take higher ranked types into account. + +// Note that `'a` and `'b` are intentionally different to make sure we consider +// them semantically the same. +trait ObjL<'l> {} +type _4 = dyn for<'a> ObjL<'a> + for<'b> ObjL<'b>; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +trait ObjT {} +type _5 = dyn ObjT fn(&'a u8)> + ObjT fn(&'b u8)>; +//~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] + +fn main() {} diff --git a/src/test/ui/traits/wf-trait-object-no-duplicates.stderr b/src/test/ui/traits/wf-trait-object-no-duplicates.stderr new file mode 100644 index 000000000000..75dacb2e1565 --- /dev/null +++ b/src/test/ui/traits/wf-trait-object-no-duplicates.stderr @@ -0,0 +1,43 @@ +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/wf-trait-object-no-duplicates.rs:8:21 + | +LL | type _0 = dyn Obj + Obj; + | --- ^^^ additional non-auto trait + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/wf-trait-object-no-duplicates.rs:13:28 + | +LL | type _1 = dyn Send + Obj + Obj; + | --- ^^^ additional non-auto trait + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/wf-trait-object-no-duplicates.rs:16:28 + | +LL | type _2 = dyn Obj + Send + Obj; + | --- ^^^ additional non-auto trait + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/wf-trait-object-no-duplicates.rs:26:34 + | +LL | type _4 = dyn for<'a> ObjL<'a> + for<'b> ObjL<'b>; + | ---------------- ^^^^^^^^^^^^^^^^ additional non-auto trait + | | + | first non-auto trait + +error[E0225]: only auto traits can be used as additional traits in a trait object + --> $DIR/wf-trait-object-no-duplicates.rs:30:42 + | +LL | type _5 = dyn ObjT fn(&'a u8)> + ObjT fn(&'b u8)>; + | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^ additional non-auto trait + | | + | first non-auto trait + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0225`. diff --git a/src/test/ui/traits/wf-trait-object-reverse-order.rs b/src/test/ui/traits/wf-trait-object-reverse-order.rs new file mode 100644 index 000000000000..f9c584ace5b2 --- /dev/null +++ b/src/test/ui/traits/wf-trait-object-reverse-order.rs @@ -0,0 +1,15 @@ +// run-pass + +// Ensure that `dyn $($AutoTrait) + ObjSafe` is well-formed. + +use std::marker::Unpin; + +// Some arbitray object-safe trait: +trait Obj {} + +type _0 = Unpin; +type _1 = Send + Obj; +type _2 = Send + Unpin + Obj; +type _3 = Send + Unpin + Sync + Obj; + +fn main() {} From 20096628c6ce13654e79970b8c56baf1efcbff8e Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Thu, 2 May 2019 02:21:20 +0100 Subject: [PATCH 0183/3207] Addressed points raised in review. --- src/librustc/traits/util.rs | 33 ++++++++---- src/librustc_typeck/astconv.rs | 11 ++-- src/test/ui/error-codes/E0225.rs | 4 +- src/test/ui/maybe-bounds.rs | 4 +- .../trait-alias/trait-alias-maybe-bound.rs | 14 ++--- .../trait-alias/trait-alias-no-duplicates.rs | 2 +- .../trait-alias-no-extra-traits.rs | 2 +- .../trait-alias/trait-alias-object-wf.rs | 52 ++++++++++++------- .../trait-alias-only-maybe-bound.rs | 22 ++++++++ ...rr => trait-alias-only-maybe-bound.stderr} | 0 .../ui/traits/wf-trait-object-maybe-bound.rs | 16 +++--- .../traits/wf-trait-object-no-duplicates.rs | 2 +- .../wf-trait-object-only-maybe-bound.rs | 6 +++ ...> wf-trait-object-only-maybe-bound.stderr} | 0 .../traits/wf-trait-object-reverse-order.rs | 12 ++--- 15 files changed, 119 insertions(+), 61 deletions(-) create mode 100644 src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.rs rename src/test/ui/traits/trait-alias/{trait-alias-maybe-bound.stderr => trait-alias-only-maybe-bound.stderr} (100%) create mode 100644 src/test/ui/traits/wf-trait-object-only-maybe-bound.rs rename src/test/ui/traits/{wf-trait-object-maybe-bound.stderr => wf-trait-object-only-maybe-bound.stderr} (100%) diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index d765827e3d56..4e5aa6b915b5 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -56,6 +56,7 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> { } fn contains(&mut self, pred: &ty::Predicate<'tcx>) -> bool { + // See the `insert` method for why we use `anonymize_predicate` here. self.set.contains(&anonymize_predicate(self.tcx, pred)) } @@ -74,13 +75,14 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> { } fn remove(&mut self, pred: &ty::Predicate<'tcx>) -> bool { + // See the `insert` method for why we use `anonymize_predicate` here. self.set.remove(&anonymize_predicate(self.tcx, pred)) } } impl<'a, 'gcx, 'tcx, T: AsRef>> Extend for PredicateSet<'a, 'gcx, 'tcx> { fn extend>(&mut self, iter: I) { - for pred in iter.into_iter() { + for pred in iter { self.insert(pred.as_ref()); } } @@ -289,30 +291,33 @@ pub fn transitive_bounds<'cx, 'gcx, 'tcx>(tcx: TyCtxt<'cx, 'gcx, 'tcx>, /// `trait Foo = Bar + Sync;`, and another trait alias /// `trait Bar = Read + Write`, then the bounds would expand to /// `Read + Write + Sync + Send`. +/// Expansion is done via a DFS (depth-first search), and the `visited` field +/// is used to avoid cycles. pub struct TraitAliasExpander<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { stack: Vec>, /// The set of predicates visited from the root directly to the current point in the - /// expansion tree. + /// expansion tree (only containing trait aliases). visited: PredicateSet<'a, 'gcx, 'tcx>, } +/// Stores information about the expansion of a trait via a path of zero or more trait aliases. #[derive(Debug, Clone)] pub struct TraitAliasExpansionInfo<'tcx> { pub items: SmallVec<[(ty::PolyTraitRef<'tcx>, Span); 4]>, } impl<'tcx> TraitAliasExpansionInfo<'tcx> { - fn new(trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> TraitAliasExpansionInfo<'tcx> { - TraitAliasExpansionInfo { + fn new(trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self { + Self { items: smallvec![(trait_ref, span)] } } - fn push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> TraitAliasExpansionInfo<'tcx> { + fn push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self { let mut items = self.items.clone(); items.push((trait_ref, span)); - TraitAliasExpansionInfo { + Self { items } } @@ -330,6 +335,8 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> { } } +/// Emits diagnostic information relating to the expansion of a trait via trait aliases +/// (see [`TraitAliasExpansionInfo`]). pub trait TraitAliasExpansionInfoDignosticBuilder { fn label_with_exp_info<'tcx>(&mut self, info: &TraitAliasExpansionInfo<'tcx>, @@ -365,10 +372,10 @@ pub fn expand_trait_aliases<'cx, 'gcx, 'tcx>( impl<'cx, 'gcx, 'tcx> TraitAliasExpander<'cx, 'gcx, 'tcx> { /// If `item` is a trait alias and its predicate has not yet been visited, then expands `item` - /// to the definition and pushes the resulting expansion onto `self.stack`, and returns `false`. - /// Otherwise, immediately returns `true` if `item` is a regular trait and `false` if it is a + /// to the definition, pushes the resulting expansion onto `self.stack`, and returns `false`. + /// Otherwise, immediately returns `true` if `item` is a regular trait, or `false` if it is a /// trait alias. - /// The return value indicates whether `item` should not be yielded to the user. + /// The return value indicates whether `item` should be yielded to the user. fn push(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool { let tcx = self.visited.tcx; let trait_ref = item.trait_ref(); @@ -376,13 +383,17 @@ impl<'cx, 'gcx, 'tcx> TraitAliasExpander<'cx, 'gcx, 'tcx> { debug!("expand_trait_aliases: trait_ref={:?}", trait_ref); - self.visited.remove(&pred); - + // Don't recurse unless this bound is a trait alias and isn't currently in the DFS stack of + // already-visited predicates. let is_alias = tcx.is_trait_alias(trait_ref.def_id()); if !is_alias || self.visited.contains(&pred) { return !is_alias; } + // Remove the current predicate from the stack of already-visited ones, since we're doing + // a DFS. + self.visited.remove(&pred); + // Get components of trait alias. let predicates = tcx.super_predicates_of(trait_ref.def_id()); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 428fa66101ac..31aba9ed239c 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -996,11 +996,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); if regular_traits.len() > 1 { let extra_trait = ®ular_traits[1]; - let mut err = struct_span_err!(tcx.sess, extra_trait.bottom().1, E0225, - "only auto traits can be used as additional traits in a trait object"); - err.label_with_exp_info(extra_trait, "additional non-auto trait"); - err.span_label(regular_traits[0].top().1, "first non-auto trait"); - err.emit(); + struct_span_err!(tcx.sess, extra_trait.bottom().1, E0225, + "only auto traits can be used as additional traits in a trait object" + ) + .label_with_exp_info(extra_trait, "additional non-auto trait") + .span_label(regular_traits[0].top().1, "first non-auto trait") + .emit(); } if regular_traits.is_empty() && auto_traits.is_empty() { diff --git a/src/test/ui/error-codes/E0225.rs b/src/test/ui/error-codes/E0225.rs index e3ac680f4415..b50f68e64516 100644 --- a/src/test/ui/error-codes/E0225.rs +++ b/src/test/ui/error-codes/E0225.rs @@ -3,8 +3,8 @@ trait Foo = std::io::Read + std::io::Write; fn main() { - let _: Box; + let _: Box; //~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] - let _: Box; + let _: Box; //~^ ERROR only auto traits can be used as additional traits in a trait object [E0225] } diff --git a/src/test/ui/maybe-bounds.rs b/src/test/ui/maybe-bounds.rs index 7defd8d3943b..95d14f6d1da3 100644 --- a/src/test/ui/maybe-bounds.rs +++ b/src/test/ui/maybe-bounds.rs @@ -1,6 +1,6 @@ trait Tr: ?Sized {} //~ ERROR `?Trait` is not permitted in supertraits -type A1 = Tr + (?Sized); -type A2 = for<'a> Tr + (?Sized); +type A1 = dyn Tr + (?Sized); +type A2 = dyn for<'a> Tr + (?Sized); fn main() {} diff --git a/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs b/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs index f444dba5d289..3dfcf03ce79d 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs +++ b/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.rs @@ -1,7 +1,11 @@ +// compile-pass + // Test that `dyn ... + ?Sized + ...` resulting from the expansion of trait aliases is okay. #![feature(trait_alias)] +trait Foo {} + trait S = ?Sized; // Nest a couple of levels deep: @@ -9,19 +13,17 @@ trait _0 = S; trait _1 = _0; // Straight list expansion: -type _T0 = dyn _1; -//~^ ERROR at least one non-builtin trait is required for an object type [E0224] +type _T0 = dyn _1 + Foo; // In second position: -type _T1 = dyn Copy + _1; +type _T1 = dyn Foo + _1; // ... and with an auto trait: -type _T2 = dyn Copy + Send + _1; +type _T2 = dyn Foo + Send + _1; // Twice: trait _2 = _1 + _1; -type _T3 = dyn _2; -//~^ ERROR at least one non-builtin trait is required for an object type [E0224] +type _T3 = dyn _2 + Foo; fn main() {} diff --git a/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.rs b/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.rs index 95525883c643..afd8400e2305 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.rs +++ b/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.rs @@ -6,7 +6,7 @@ use std::marker::Unpin; -// Some arbitray object-safe trait: +// Some arbitrary object-safe trait: trait Obj {} // Nest a few levels deep: diff --git a/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.rs b/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.rs index 54c177f0db80..4dad8c0f8734 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.rs +++ b/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.rs @@ -5,7 +5,7 @@ use std::marker::Unpin; -// Some arbitray object-safe traits: +// Some arbitrary object-safe traits: trait ObjA {} trait ObjB {} diff --git a/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs b/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs index 6383e8b6e10f..f7c410c6362f 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs +++ b/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs @@ -1,6 +1,6 @@ // run-pass -// This test checks that trait objects involving trait aliases are well-formed. +// This test hecks that trait objects involving trait aliases are well-formed. #![feature(trait_alias)] @@ -14,31 +14,39 @@ trait _1 = _0 + Send + Sync; use std::marker::Unpin; -type _T01 = dyn _0; -type _T02 = dyn _1; -type _T03 = dyn Unpin + _1 + Send + Sync; +fn _f0() { + let _: Box; + let _: Box; + let _: Box; +} // Include object safe traits: -type _T10 = dyn Obj + _0; -type _T11 = dyn Obj + _1; -type _T12 = dyn Obj + _1 + _0; +fn _f1() { + let _: Box; + let _: Box; + let _: Box; +} // And when the object safe trait is in a trait alias: trait _2 = Obj; -type _T20 = dyn _2 + _0; -type _T21 = dyn _2 + _1; -type _T22 = dyn _2 + _1 + _0; +fn _f2() { + let _: Box; + let _: Box; + let _: Box; +} // And it should also work when that trait is has auto traits to the right of it. trait _3 = Obj + Unpin; -type _T30 = dyn _3 + _0; -type _T31 = dyn _3 + _1; -type _T32 = dyn _3 + _1 + _0; +fn _f3() { + let _: Box; + let _: Box; + let _: Box; +} // Nest the trait deeply: @@ -46,9 +54,11 @@ trait _4 = _3; trait _5 = _4 + Sync + _0 + Send; trait _6 = _5 + Send + _1 + Sync; -type _T60 = dyn _6 + _0; -type _T61 = dyn _6 + _1; -type _T62 = dyn _6 + _1 + _0; +fn _f4() { + let _: Box; + let _: Box; + let _: Box; +} // Just nest the trait alone: @@ -56,7 +66,9 @@ trait _7 = _2; trait _8 = _7; trait _9 = _8; -type _T9 = dyn _9; +fn _f5() { + let _: Box; +} // First bound is auto trait: @@ -65,7 +77,9 @@ trait _11 = Obj + Send; trait _12 = Sync + _11; trait _13 = Send + _12; -type _T70 = dyn _0; -type _T71 = dyn _3; +fn f6() { + let _: Box; + let _: Box; +} fn main() {} diff --git a/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.rs b/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.rs new file mode 100644 index 000000000000..d6c611d2a4d9 --- /dev/null +++ b/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.rs @@ -0,0 +1,22 @@ +// Test that `dyn ?Sized` (i.e., a trait object with only a maybe buond) is not allowed, when just +// `?Sized` results from trait alias expansion. + +#![feature(trait_alias)] + +trait S = ?Sized; + +// Nest a couple of levels deep: +trait _0 = S; +trait _1 = _0; + +// Straight list expansion: +type _T0 = dyn _1; +//~^ ERROR at least one non-builtin trait is required for an object type [E0224] + +// Twice: +trait _2 = _1 + _1; + +type _T1 = dyn _2; +//~^ ERROR at least one non-builtin trait is required for an object type [E0224] + +fn main() {} diff --git a/src/test/ui/traits/trait-alias/trait-alias-maybe-bound.stderr b/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr similarity index 100% rename from src/test/ui/traits/trait-alias/trait-alias-maybe-bound.stderr rename to src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr diff --git a/src/test/ui/traits/wf-trait-object-maybe-bound.rs b/src/test/ui/traits/wf-trait-object-maybe-bound.rs index 68f0155faf9b..405104fe0814 100644 --- a/src/test/ui/traits/wf-trait-object-maybe-bound.rs +++ b/src/test/ui/traits/wf-trait-object-maybe-bound.rs @@ -1,13 +1,15 @@ -// The purpose of this test is to demonstrate that `?Sized` is allowed in trait objects -// (thought it has no effect). +// compile-pass -type _0 = dyn ?Sized; -//~^ ERROR at least one non-builtin trait is required for an object type [E0224] +// Test that `dyn ... + ?Sized + ...` is okay (though `?Sized` has no effect in trait objects). -type _1 = dyn Clone + ?Sized; +trait Foo {} -type _2 = dyn Clone + ?Sized + ?Sized; +type _0 = dyn ?Sized + Foo; -type _3 = dyn ?Sized + Clone; +type _1 = dyn Foo + ?Sized; + +type _2 = dyn Foo + ?Sized + ?Sized; + +type _3 = dyn ?Sized + Foo; fn main() {} diff --git a/src/test/ui/traits/wf-trait-object-no-duplicates.rs b/src/test/ui/traits/wf-trait-object-no-duplicates.rs index dd6d73619bce..678ede58296a 100644 --- a/src/test/ui/traits/wf-trait-object-no-duplicates.rs +++ b/src/test/ui/traits/wf-trait-object-no-duplicates.rs @@ -1,7 +1,7 @@ // The purpose of this test is to demonstrate that duplicating object safe traits // that are not auto-traits is rejected even though one could reasonably accept this. -// Some arbitray object-safe trait: +// Some arbitrary object-safe trait: trait Obj {} // Demonstrate that recursive expansion of trait aliases doesn't affect stable behavior: diff --git a/src/test/ui/traits/wf-trait-object-only-maybe-bound.rs b/src/test/ui/traits/wf-trait-object-only-maybe-bound.rs new file mode 100644 index 000000000000..c8e6ac38b5a3 --- /dev/null +++ b/src/test/ui/traits/wf-trait-object-only-maybe-bound.rs @@ -0,0 +1,6 @@ +// Test that `dyn ?Sized` (i.e., a trait object with only a maybe buond) is not allowed. + +type _0 = dyn ?Sized; +//~^ ERROR at least one non-builtin trait is required for an object type [E0224] + +fn main() {} diff --git a/src/test/ui/traits/wf-trait-object-maybe-bound.stderr b/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr similarity index 100% rename from src/test/ui/traits/wf-trait-object-maybe-bound.stderr rename to src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr diff --git a/src/test/ui/traits/wf-trait-object-reverse-order.rs b/src/test/ui/traits/wf-trait-object-reverse-order.rs index f9c584ace5b2..4f676cbe3384 100644 --- a/src/test/ui/traits/wf-trait-object-reverse-order.rs +++ b/src/test/ui/traits/wf-trait-object-reverse-order.rs @@ -1,15 +1,15 @@ // run-pass -// Ensure that `dyn $($AutoTrait) + ObjSafe` is well-formed. +// Ensure that `dyn $($AutoTrait)+ ObjSafe` is well-formed. use std::marker::Unpin; -// Some arbitray object-safe trait: +// Some arbitrary object-safe trait: trait Obj {} -type _0 = Unpin; -type _1 = Send + Obj; -type _2 = Send + Unpin + Obj; -type _3 = Send + Unpin + Sync + Obj; +type _0 = dyn Unpin; +type _1 = dyn Send + Obj; +type _2 = dyn Send + Unpin + Obj; +type _3 = dyn Send + Unpin + Sync + Obj; fn main() {} From 783b713b5d90747dec1aabdbc8bfc348593a00c5 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Thu, 2 May 2019 18:03:29 +0100 Subject: [PATCH 0184/3207] Addressed more points raised in review. --- src/librustc/traits/util.rs | 96 ++++--- src/librustc_typeck/astconv.rs | 30 ++- src/test/ui/bad/bad-sized.stderr | 7 +- src/test/ui/error-codes/E0225.stderr | 22 +- src/test/ui/issues/issue-22560.stderr | 10 +- src/test/ui/issues/issue-32963.stderr | 7 +- .../trait-alias-no-duplicates.stderr | 186 ++++++++++---- .../trait-alias-no-extra-traits.stderr | 234 ++++++++++++++---- .../trait-alias/trait-alias-object-wf.rs | 2 +- .../trait-alias-only-maybe-bound.stderr | 6 +- .../wf-trait-object-no-duplicates.stderr | 35 ++- .../wf-trait-object-only-maybe-bound.stderr | 2 +- 12 files changed, 452 insertions(+), 185 deletions(-) diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 4e5aa6b915b5..77588d713dfc 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -51,13 +51,8 @@ struct PredicateSet<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { } impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> { - fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> PredicateSet<'a, 'gcx, 'tcx> { - PredicateSet { tcx: tcx, set: Default::default() } - } - - fn contains(&mut self, pred: &ty::Predicate<'tcx>) -> bool { - // See the `insert` method for why we use `anonymize_predicate` here. - self.set.contains(&anonymize_predicate(self.tcx, pred)) + fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Self { + Self { tcx: tcx, set: Default::default() } } fn insert(&mut self, pred: &ty::Predicate<'tcx>) -> bool { @@ -73,11 +68,6 @@ impl<'a, 'gcx, 'tcx> PredicateSet<'a, 'gcx, 'tcx> { // regions before we throw things into the underlying set. self.set.insert(anonymize_predicate(self.tcx, pred)) } - - fn remove(&mut self, pred: &ty::Predicate<'tcx>) -> bool { - // See the `insert` method for why we use `anonymize_predicate` here. - self.set.remove(&anonymize_predicate(self.tcx, pred)) - } } impl<'a, 'gcx, 'tcx, T: AsRef>> Extend for PredicateSet<'a, 'gcx, 'tcx> { @@ -135,7 +125,7 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> { FilterToTraits::new(self) } - fn push(&mut self, predicate: &ty::Predicate<'tcx>) { + fn elaborate(&mut self, predicate: &ty::Predicate<'tcx>) { let tcx = self.visited.tcx; match *predicate { ty::Predicate::Trait(ref data) => { @@ -153,7 +143,7 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> { // This is necessary to prevent infinite recursion in some // cases. One common case is when people define // `trait Sized: Sized { }` rather than `trait Sized { }`. - predicates.retain(|p| self.visited.insert(p)); + predicates.retain(|pred| self.visited.insert(pred)); self.stack.extend(predicates); } @@ -251,15 +241,12 @@ impl<'cx, 'gcx, 'tcx> Iterator for Elaborator<'cx, 'gcx, 'tcx> { fn next(&mut self) -> Option> { // Extract next item from top-most stack frame, if any. - let next_predicate = match self.stack.pop() { - Some(predicate) => predicate, - None => { - // No more stack frames. Done. - return None; - } - }; - self.push(&next_predicate); - return Some(next_predicate); + if let Some(pred) = self.stack.pop() { + self.elaborate(&pred); + Some(pred) + } else { + None + } } } @@ -294,31 +281,29 @@ pub fn transitive_bounds<'cx, 'gcx, 'tcx>(tcx: TyCtxt<'cx, 'gcx, 'tcx>, /// Expansion is done via a DFS (depth-first search), and the `visited` field /// is used to avoid cycles. pub struct TraitAliasExpander<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { + tcx: TyCtxt<'a, 'gcx, 'tcx>, stack: Vec>, - /// The set of predicates visited from the root directly to the current point in the - /// expansion tree (only containing trait aliases). - visited: PredicateSet<'a, 'gcx, 'tcx>, } /// Stores information about the expansion of a trait via a path of zero or more trait aliases. #[derive(Debug, Clone)] pub struct TraitAliasExpansionInfo<'tcx> { - pub items: SmallVec<[(ty::PolyTraitRef<'tcx>, Span); 4]>, + pub path: SmallVec<[(ty::PolyTraitRef<'tcx>, Span); 4]>, } impl<'tcx> TraitAliasExpansionInfo<'tcx> { fn new(trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self { Self { - items: smallvec![(trait_ref, span)] + path: smallvec![(trait_ref, span)] } } - fn push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self { - let mut items = self.items.clone(); - items.push((trait_ref, span)); + fn clone_and_push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self { + let mut path = self.path.clone(); + path.push((trait_ref, span)); Self { - items + path } } @@ -327,11 +312,11 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> { } pub fn top(&self) -> &(ty::PolyTraitRef<'tcx>, Span) { - self.items.last().unwrap() + self.path.last().unwrap() } pub fn bottom(&self) -> &(ty::PolyTraitRef<'tcx>, Span) { - self.items.first().unwrap() + self.path.first().unwrap() } } @@ -340,21 +325,25 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> { pub trait TraitAliasExpansionInfoDignosticBuilder { fn label_with_exp_info<'tcx>(&mut self, info: &TraitAliasExpansionInfo<'tcx>, - top_label: &str + top_label: &str, + use_desc: &str ) -> &mut Self; } impl<'a> TraitAliasExpansionInfoDignosticBuilder for DiagnosticBuilder<'a> { fn label_with_exp_info<'tcx>(&mut self, info: &TraitAliasExpansionInfo<'tcx>, - top_label: &str + top_label: &str, + use_desc: &str ) -> &mut Self { self.span_label(info.top().1, top_label); - if info.items.len() > 1 { - for (_, sp) in info.items[1..(info.items.len() - 1)].iter().rev() { - self.span_label(*sp, "referenced here"); + if info.path.len() > 1 { + for (_, sp) in info.path.iter().rev().skip(1).take(info.path.len() - 2) { + self.span_label(*sp, format!("referenced here ({})", use_desc)); } } + self.span_label(info.bottom().1, + format!("trait alias used in trait object type ({})", use_desc)); self } } @@ -367,7 +356,7 @@ pub fn expand_trait_aliases<'cx, 'gcx, 'tcx>( .into_iter() .map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span)) .collect(); - TraitAliasExpander { stack: items, visited: PredicateSet::new(tcx) } + TraitAliasExpander { tcx, stack: items } } impl<'cx, 'gcx, 'tcx> TraitAliasExpander<'cx, 'gcx, 'tcx> { @@ -376,23 +365,25 @@ impl<'cx, 'gcx, 'tcx> TraitAliasExpander<'cx, 'gcx, 'tcx> { /// Otherwise, immediately returns `true` if `item` is a regular trait, or `false` if it is a /// trait alias. /// The return value indicates whether `item` should be yielded to the user. - fn push(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool { - let tcx = self.visited.tcx; + fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool { + let tcx = self.tcx; let trait_ref = item.trait_ref(); let pred = trait_ref.to_predicate(); debug!("expand_trait_aliases: trait_ref={:?}", trait_ref); - // Don't recurse unless this bound is a trait alias and isn't currently in the DFS stack of - // already-visited predicates. + // Don't recurse if this bound is not a trait alias. let is_alias = tcx.is_trait_alias(trait_ref.def_id()); - if !is_alias || self.visited.contains(&pred) { - return !is_alias; + if !is_alias { + return true; } - // Remove the current predicate from the stack of already-visited ones, since we're doing - // a DFS. - self.visited.remove(&pred); + // Don't recurse if this trait alias is already on the stack for the DFS search. + let anon_pred = anonymize_predicate(tcx, &pred); + if item.path.iter().rev().skip(1) + .any(|(tr, _)| anonymize_predicate(tcx, &tr.to_predicate()) == anon_pred) { + return false; + } // Get components of trait alias. let predicates = tcx.super_predicates_of(trait_ref.def_id()); @@ -403,16 +394,13 @@ impl<'cx, 'gcx, 'tcx> TraitAliasExpander<'cx, 'gcx, 'tcx> { .filter_map(|(pred, span)| { pred.subst_supertrait(tcx, &trait_ref) .to_opt_poly_trait_ref() - .map(|trait_ref| item.push(trait_ref, *span)) + .map(|trait_ref| item.clone_and_push(trait_ref, *span)) }) .collect(); debug!("expand_trait_aliases: items={:?}", items); self.stack.extend(items); - // Record predicate into set of already-visited. - self.visited.insert(&pred); - false } } @@ -426,7 +414,7 @@ impl<'cx, 'gcx, 'tcx> Iterator for TraitAliasExpander<'cx, 'gcx, 'tcx> { fn next(&mut self) -> Option> { while let Some(item) = self.stack.pop() { - if self.push(&item) { + if self.expand(&item) { return Some(item); } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 31aba9ed239c..7d4243c4842e 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -648,14 +648,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { // careful! if default_needs_object_self(param) { struct_span_err!(tcx.sess, span, E0393, - "the type parameter `{}` must be explicitly \ - specified", - param.name) - .span_label(span, - format!("missing reference to `{}`", param.name)) - .note(&format!("because of the default `Self` reference, \ - type parameters must be specified on object \ - types")) + "the type parameter `{}` must be explicitly specified", + param.name + ) + .span_label(span, format!( + "missing reference to `{}`", param.name)) + .note(&format!( + "because of the default `Self` reference, type parameters \ + must be specified on object types")) .emit(); tcx.types.err.into() } else { @@ -987,7 +987,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { ); potential_assoc_types.extend(cur_potential_assoc_types.into_iter().flatten()); (trait_ref, trait_bound.span) - }).collect(); + }) + .collect(); // Expand trait aliases recursively and check that only one regular (non-auto) trait // is used and no 'maybe' bounds are used. @@ -995,12 +996,15 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); if regular_traits.len() > 1 { - let extra_trait = ®ular_traits[1]; - struct_span_err!(tcx.sess, extra_trait.bottom().1, E0225, + let first_trait = ®ular_traits[0]; + let additional_trait = ®ular_traits[1]; + struct_span_err!(tcx.sess, additional_trait.bottom().1, E0225, "only auto traits can be used as additional traits in a trait object" ) - .label_with_exp_info(extra_trait, "additional non-auto trait") - .span_label(regular_traits[0].top().1, "first non-auto trait") + .label_with_exp_info(additional_trait, "additional non-auto trait", + "additional use") + .label_with_exp_info(first_trait, "first non-auto trait", + "first use") .emit(); } diff --git a/src/test/ui/bad/bad-sized.stderr b/src/test/ui/bad/bad-sized.stderr index 671840acdbfe..6307af5d725d 100644 --- a/src/test/ui/bad/bad-sized.stderr +++ b/src/test/ui/bad/bad-sized.stderr @@ -2,9 +2,12 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec --> $DIR/bad-sized.rs:4:24 | LL | let x: Vec = Vec::new(); - | ----- ^^^^^ additional non-auto trait - | | + | ----- ^^^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) | first non-auto trait + | trait alias used in trait object type (first use) error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time --> $DIR/bad-sized.rs:4:12 diff --git a/src/test/ui/error-codes/E0225.stderr b/src/test/ui/error-codes/E0225.stderr index 183cf0aad643..c7a66c327f1c 100644 --- a/src/test/ui/error-codes/E0225.stderr +++ b/src/test/ui/error-codes/E0225.stderr @@ -1,21 +1,27 @@ error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/E0225.rs:6:32 + --> $DIR/E0225.rs:6:36 | -LL | let _: Box; - | ------------- ^^^^^^^^^^^^^^ additional non-auto trait - | | - | first non-auto trait +LL | let _: Box; + | ------------- ^^^^^^^^^^^^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) + | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/E0225.rs:8:16 + --> $DIR/E0225.rs:8:20 | LL | trait Foo = std::io::Read + std::io::Write; | ------------- -------------- additional non-auto trait | | | first non-auto trait ... -LL | let _: Box; - | ^^^ +LL | let _: Box; + | ^^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-22560.stderr b/src/test/ui/issues/issue-22560.stderr index 2c6f4d9d45f7..322136d35cad 100644 --- a/src/test/ui/issues/issue-22560.stderr +++ b/src/test/ui/issues/issue-22560.stderr @@ -18,10 +18,16 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec --> $DIR/issue-22560.rs:6:13 | LL | type Test = Add + - | --- first non-auto trait + | --- + | | + | first non-auto trait + | trait alias used in trait object type (first use) ... LL | Sub; - | ^^^ additional non-auto trait + | ^^^ + | | + | additional non-auto trait + | trait alias used in trait object type (additional use) error[E0191]: the value of the associated types `Output` (from the trait `std::ops::Add`), `Output` (from the trait `std::ops::Sub`) must be specified --> $DIR/issue-22560.rs:3:13 diff --git a/src/test/ui/issues/issue-32963.stderr b/src/test/ui/issues/issue-32963.stderr index 381ccdbeb999..cde4123dc3f4 100644 --- a/src/test/ui/issues/issue-32963.stderr +++ b/src/test/ui/issues/issue-32963.stderr @@ -2,9 +2,12 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec --> $DIR/issue-32963.rs:8:25 | LL | size_of_copy::(); - | ---- ^^^^ additional non-auto trait - | | + | ---- ^^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) | first non-auto trait + | trait alias used in trait object type (first use) error[E0277]: the trait bound `dyn Misc: std::marker::Copy` is not satisfied --> $DIR/issue-32963.rs:8:5 diff --git a/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.stderr b/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.stderr index 3cdf1582ab9c..eb667c9522ce 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.stderr +++ b/src/test/ui/traits/trait-alias/trait-alias-no-duplicates.stderr @@ -8,7 +8,9 @@ LL | trait _0 = Obj; | first non-auto trait ... LL | type _T00 = dyn _0 + _0; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:19:22 @@ -18,9 +20,13 @@ LL | trait _0 = Obj; | | | additional non-auto trait | first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | type _T01 = dyn _1 + _0; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:22:22 @@ -31,10 +37,15 @@ LL | trait _0 = Obj; | additional non-auto trait | first non-auto trait LL | trait _1 = _0; - | -- referenced here + | -- + | | + | referenced here (additional use) + | referenced here (first use) ... LL | type _T02 = dyn _1 + _1; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:25:23 @@ -42,21 +53,28 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = Obj; | --- additional non-auto trait LL | trait _1 = _0; - | -- referenced here + | -- referenced here (additional use) ... LL | type _T03 = dyn Obj + _1; - | --- ^^ + | --- ^^ trait alias used in trait object type (additional use) | | | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:28:22 | LL | trait _0 = Obj; | --- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | type _T04 = dyn _1 + Obj; - | ^^^ additional non-auto trait + | -- ^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:37:17 @@ -67,13 +85,18 @@ LL | trait _0 = Obj; | additional non-auto trait | first non-auto trait LL | trait _1 = _0; - | -- referenced here + | -- referenced here (additional use) ... LL | trait _2 = _0 + _1; - | -- referenced here + | -- -- referenced here (additional use) + | | + | referenced here (first use) ... LL | type _T10 = dyn _2 + _3; | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:40:22 @@ -82,12 +105,14 @@ LL | trait _0 = Obj; | --- additional non-auto trait ... LL | trait _2 = _0 + _1; - | -- referenced here + | -- referenced here (additional use) LL | trait _3 = Obj; | --- first non-auto trait ... LL | type _T11 = dyn _3 + _2; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:43:23 @@ -96,12 +121,13 @@ LL | trait _0 = Obj; | --- additional non-auto trait ... LL | trait _2 = _0 + _1; - | -- referenced here + | -- referenced here (additional use) ... LL | type _T12 = dyn Obj + _2; - | --- ^^ + | --- ^^ trait alias used in trait object type (additional use) | | | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:46:17 @@ -112,25 +138,34 @@ LL | trait _0 = Obj; | additional non-auto trait | first non-auto trait LL | trait _1 = _0; - | -- referenced here + | -- referenced here (additional use) ... LL | trait _2 = _0 + _1; - | -- referenced here + | -- -- referenced here (additional use) + | | + | referenced here (first use) ... LL | type _T13 = dyn _2 + Obj; | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:49:22 | LL | trait _0 = Obj; | --- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | trait _3 = Obj; | --- additional non-auto trait ... LL | type _T14 = dyn _1 + _3; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:52:22 @@ -138,27 +173,33 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = Obj; | --- additional non-auto trait LL | trait _1 = _0; - | -- referenced here + | -- referenced here (additional use) ... LL | trait _3 = Obj; | --- first non-auto trait ... LL | type _T15 = dyn _3 + _1; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:55:22 | LL | trait _0 = Obj; | --- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | trait _3 = Obj; | --- additional non-auto trait LL | trait _4 = _3; - | -- referenced here + | -- referenced here (additional use) ... LL | type _T16 = dyn _1 + _4; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:58:22 @@ -166,13 +207,17 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = Obj; | --- additional non-auto trait LL | trait _1 = _0; - | -- referenced here + | -- referenced here (additional use) ... LL | trait _3 = Obj; | --- first non-auto trait +LL | trait _4 = _3; + | -- referenced here (first use) ... LL | type _T17 = dyn _4 + _1; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:65:22 @@ -184,7 +229,9 @@ LL | trait _5 = Obj + Send; | first non-auto trait LL | LL | type _T20 = dyn _5 + _5; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:68:23 @@ -193,9 +240,10 @@ LL | trait _5 = Obj + Send; | --- additional non-auto trait ... LL | type _T21 = dyn Obj + _5; - | --- ^^ + | --- ^^ trait alias used in trait object type (additional use) | | | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:71:22 @@ -204,7 +252,11 @@ LL | trait _5 = Obj + Send; | --- first non-auto trait ... LL | type _T22 = dyn _5 + Obj; - | ^^^ additional non-auto trait + | -- ^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:74:36 @@ -213,7 +265,11 @@ LL | trait _5 = Obj + Send; | --- first non-auto trait ... LL | type _T23 = dyn _5 + Send + Sync + Obj; - | ^^^ additional non-auto trait + | -- ^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:81:17 @@ -225,10 +281,15 @@ LL | trait _5 = Obj + Send; | first non-auto trait ... LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send - | -- referenced here + | -- -- referenced here (additional use) + | | + | referenced here (first use) LL | LL | type _T30 = dyn _6; | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:84:17 @@ -240,10 +301,15 @@ LL | trait _5 = Obj + Send; | first non-auto trait ... LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send - | -- referenced here + | -- -- referenced here (additional use) + | | + | referenced here (first use) ... LL | type _T31 = dyn _6 + Send; | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:87:24 @@ -255,10 +321,15 @@ LL | trait _5 = Obj + Send; | first non-auto trait ... LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send - | -- referenced here + | -- -- referenced here (additional use) + | | + | referenced here (first use) ... LL | type _T32 = dyn Send + _6; | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:95:22 @@ -266,8 +337,17 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _5 = Obj + Send; | --- first non-auto trait ... +LL | trait _7 = _5 + Sync; + | -- referenced here (first use) +LL | trait _8 = Unpin + _7; + | -- referenced here (first use) +LL | LL | type _T40 = dyn _8 + Obj; - | ^^^ additional non-auto trait + | -- ^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:98:23 @@ -276,14 +356,15 @@ LL | trait _5 = Obj + Send; | --- additional non-auto trait ... LL | trait _7 = _5 + Sync; - | -- referenced here + | -- referenced here (additional use) LL | trait _8 = Unpin + _7; - | -- referenced here + | -- referenced here (additional use) ... LL | type _T41 = dyn Obj + _8; - | --- ^^ + | --- ^^ trait alias used in trait object type (additional use) | | | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:101:22 @@ -291,47 +372,62 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _3 = Obj; | --- additional non-auto trait LL | trait _4 = _3; - | -- referenced here + | -- referenced here (additional use) ... LL | trait _5 = Obj + Send; | --- first non-auto trait ... +LL | trait _7 = _5 + Sync; + | -- referenced here (first use) +LL | trait _8 = Unpin + _7; + | -- referenced here (first use) +... LL | type _T42 = dyn _8 + _4; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:104:22 | LL | trait _3 = Obj; | --- first non-auto trait +LL | trait _4 = _3; + | -- referenced here (first use) ... LL | trait _5 = Obj + Send; | --- additional non-auto trait ... LL | trait _7 = _5 + Sync; - | -- referenced here + | -- referenced here (additional use) LL | trait _8 = Unpin + _7; - | -- referenced here + | -- referenced here (additional use) ... LL | type _T43 = dyn _4 + _8; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:107:36 | LL | trait _3 = Obj; | --- first non-auto trait +LL | trait _4 = _3; + | -- referenced here (first use) ... LL | trait _5 = Obj + Send; | --- additional non-auto trait ... LL | trait _7 = _5 + Sync; - | -- referenced here + | -- referenced here (additional use) LL | trait _8 = Unpin + _7; - | -- referenced here + | -- referenced here (additional use) ... LL | type _T44 = dyn _4 + Send + Sync + _8; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:117:18 @@ -341,7 +437,9 @@ LL | trait _9 = for<'a> ObjL<'a>; LL | trait _10 = for<'b> ObjL<'b>; | ---------------- additional non-auto trait LL | type _T50 = _9 + _10; - | ^^^ + | -- ^^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-duplicates.rs:123:19 @@ -351,7 +449,9 @@ LL | trait _11 = ObjT fn(&'a u8)>; LL | trait _12 = ObjT fn(&'b u8)>; | ------------------------ additional non-auto trait LL | type _T60 = _11 + _12; - | ^^^ + | --- ^^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error: aborting due to 27 previous errors diff --git a/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.stderr b/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.stderr index d73667a07097..15685a228833 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.stderr +++ b/src/test/ui/traits/trait-alias/trait-alias-no-extra-traits.stderr @@ -5,7 +5,11 @@ LL | trait _0 = ObjA; | ---- first non-auto trait ... LL | type _T00 = dyn _0 + ObjB; - | ^^^^ additional non-auto trait + | -- ^^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:19:24 @@ -14,9 +18,10 @@ LL | trait _0 = ObjA; | ---- additional non-auto trait ... LL | type _T01 = dyn ObjB + _0; - | ---- ^^ + | ---- ^^ trait alias used in trait object type (additional use) | | | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:22:24 @@ -24,21 +29,28 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = ObjA; | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here + | -- referenced here (additional use) ... LL | type _T02 = dyn ObjB + _1; - | ---- ^^ + | ---- ^^ trait alias used in trait object type (additional use) | | | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:25:22 | LL | trait _0 = ObjA; | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | type _T03 = dyn _1 + ObjB; - | ^^^^ additional non-auto trait + | -- ^^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:34:22 @@ -49,10 +61,12 @@ LL | trait _2 = ObjB; | additional non-auto trait | first non-auto trait LL | trait _3 = _2; - | -- referenced here + | -- referenced here (additional use) ... LL | type _T10 = dyn _2 + _3; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:37:22 @@ -62,9 +76,13 @@ LL | trait _2 = ObjB; | | | additional non-auto trait | first non-auto trait +LL | trait _3 = _2; + | -- referenced here (first use) ... LL | type _T11 = dyn _3 + _2; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:40:22 @@ -75,12 +93,14 @@ LL | trait _2 = ObjB; | additional non-auto trait | first non-auto trait LL | trait _3 = _2; - | -- referenced here + | -- referenced here (additional use) LL | trait _4 = _3; - | -- referenced here + | -- referenced here (additional use) ... LL | type _T12 = dyn _2 + _4; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:43:22 @@ -90,9 +110,15 @@ LL | trait _2 = ObjB; | | | additional non-auto trait | first non-auto trait +LL | trait _3 = _2; + | -- referenced here (first use) +LL | trait _4 = _3; + | -- referenced here (first use) ... LL | type _T13 = dyn _4 + _2; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:50:22 @@ -100,25 +126,31 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = ObjA; | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here + | -- referenced here (additional use) ... LL | trait _5 = Sync + ObjB + Send; | ---- first non-auto trait LL | LL | type _T20 = dyn _5 + _1; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:53:22 | LL | trait _0 = ObjA; | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | type _T21 = dyn _1 + _5; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:56:22 @@ -127,7 +159,11 @@ LL | trait _5 = Sync + ObjB + Send; | ---- first non-auto trait ... LL | type _T22 = dyn _5 + ObjA; - | ^^^^ additional non-auto trait + | -- ^^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:59:24 @@ -136,9 +172,10 @@ LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | type _T23 = dyn ObjA + _5; - | ---- ^^ + | ---- ^^ trait alias used in trait object type (additional use) | | | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:62:29 @@ -146,25 +183,31 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = ObjA; | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here + | -- referenced here (additional use) ... LL | trait _5 = Sync + ObjB + Send; | ---- first non-auto trait ... LL | type _T24 = dyn Send + _5 + _1 + Sync; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:65:29 | LL | trait _0 = ObjA; | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | type _T25 = dyn _1 + Sync + _5 + Send; - | ^^ + | -- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:68:36 @@ -173,7 +216,11 @@ LL | trait _5 = Sync + ObjB + Send; | ---- first non-auto trait ... LL | type _T26 = dyn Sync + Send + _5 + ObjA; - | ^^^^ additional non-auto trait + | -- ^^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:71:38 @@ -182,111 +229,172 @@ LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | type _T27 = dyn Send + Sync + ObjA + _5; - | ---- ^^ + | ---- ^^ trait alias used in trait object type (additional use) | | | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:80:17 | LL | trait _0 = ObjA; | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | trait _6 = _1 + _5; - | -- referenced here + | -- -- referenced here (additional use) + | | + | referenced here (first use) ... LL | type _T30 = dyn _6; | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:83:17 | LL | trait _0 = ObjA; | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | trait _6 = _1 + _5; - | -- referenced here + | -- -- referenced here (additional use) + | | + | referenced here (first use) ... LL | type _T31 = dyn _6 + Send; | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:86:24 | LL | trait _0 = ObjA; | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | trait _6 = _1 + _5; - | -- referenced here + | -- -- referenced here (additional use) + | | + | referenced here (first use) ... LL | type _T32 = dyn Send + _6; | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:89:17 | LL | trait _0 = ObjA; | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | trait _6 = _1 + _5; - | -- referenced here + | -- -- referenced here (additional use) + | | + | referenced here (first use) LL | trait _7 = _6; - | -- referenced here + | -- + | | + | referenced here (additional use) + | referenced here (first use) LL | trait _8 = _7; - | -- referenced here + | -- + | | + | referenced here (additional use) + | referenced here (first use) ... LL | type _T33 = dyn _8; | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:92:17 | LL | trait _0 = ObjA; | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | trait _6 = _1 + _5; - | -- referenced here + | -- -- referenced here (additional use) + | | + | referenced here (first use) LL | trait _7 = _6; - | -- referenced here + | -- + | | + | referenced here (additional use) + | referenced here (first use) LL | trait _8 = _7; - | -- referenced here + | -- + | | + | referenced here (additional use) + | referenced here (first use) ... LL | type _T34 = dyn _8 + Send; | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:95:24 | LL | trait _0 = ObjA; | ---- first non-auto trait +LL | trait _1 = _0; + | -- referenced here (first use) ... LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | trait _6 = _1 + _5; - | -- referenced here + | -- -- referenced here (additional use) + | | + | referenced here (first use) LL | trait _7 = _6; - | -- referenced here + | -- + | | + | referenced here (additional use) + | referenced here (first use) LL | trait _8 = _7; - | -- referenced here + | -- + | | + | referenced here (additional use) + | referenced here (first use) ... LL | type _T35 = dyn Send + _8; | ^^ + | | + | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:103:23 @@ -294,8 +402,17 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _5 = Sync + ObjB + Send; | ---- first non-auto trait ... +LL | trait _9 = _5 + Sync; + | -- referenced here (first use) +LL | trait _10 = Unpin + _9; + | -- referenced here (first use) +LL | LL | type _T40 = dyn _10 + ObjA; - | ^^^^ additional non-auto trait + | --- ^^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:106:24 @@ -304,14 +421,15 @@ LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | trait _9 = _5 + Sync; - | -- referenced here + | -- referenced here (additional use) LL | trait _10 = Unpin + _9; - | -- referenced here + | -- referenced here (additional use) ... LL | type _T41 = dyn ObjA + _10; - | ---- ^^^ + | ---- ^^^ trait alias used in trait object type (additional use) | | | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:109:23 @@ -319,13 +437,20 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = ObjA; | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here + | -- referenced here (additional use) ... LL | trait _5 = Sync + ObjB + Send; | ---- first non-auto trait ... +LL | trait _9 = _5 + Sync; + | -- referenced here (first use) +LL | trait _10 = Unpin + _9; + | -- referenced here (first use) +... LL | type _T42 = dyn _10 + _1; - | ^^ + | --- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:112:37 @@ -333,8 +458,17 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _5 = Sync + ObjB + Send; | ---- first non-auto trait ... +LL | trait _9 = _5 + Sync; + | -- referenced here (first use) +LL | trait _10 = Unpin + _9; + | -- referenced here (first use) +... LL | type _T43 = dyn Send + _10 + Sync + ObjA; - | ^^^^ additional non-auto trait + | --- ^^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:115:24 @@ -343,14 +477,15 @@ LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | trait _9 = _5 + Sync; - | -- referenced here + | -- referenced here (additional use) LL | trait _10 = Unpin + _9; - | -- referenced here + | -- referenced here (additional use) ... LL | type _T44 = dyn ObjA + _10 + Send + Sync; - | ---- ^^^ + | ---- ^^^ trait alias used in trait object type (additional use) | | | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/trait-alias-no-extra-traits.rs:118:37 @@ -358,13 +493,20 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = ObjA; | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here + | -- referenced here (additional use) ... LL | trait _5 = Sync + ObjB + Send; | ---- first non-auto trait ... +LL | trait _9 = _5 + Sync; + | -- referenced here (first use) +LL | trait _10 = Unpin + _9; + | -- referenced here (first use) +... LL | type _T45 = dyn Sync + Send + _10 + _1; - | ^^ + | --- ^^ trait alias used in trait object type (additional use) + | | + | trait alias used in trait object type (first use) error: aborting due to 28 previous errors diff --git a/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs b/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs index f7c410c6362f..fb26b7e2df7c 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs +++ b/src/test/ui/traits/trait-alias/trait-alias-object-wf.rs @@ -1,6 +1,6 @@ // run-pass -// This test hecks that trait objects involving trait aliases are well-formed. +// This test checks that trait objects involving trait aliases are well-formed. #![feature(trait_alias)] diff --git a/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr b/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr index 52e90c00c374..d4f77200fd5a 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr +++ b/src/test/ui/traits/trait-alias/trait-alias-only-maybe-bound.stderr @@ -1,13 +1,13 @@ error[E0224]: at least one non-builtin trait is required for an object type - --> $DIR/trait-alias-maybe-bound.rs:12:12 + --> $DIR/trait-alias-only-maybe-bound.rs:13:12 | LL | type _T0 = dyn _1; | ^^^^^^ error[E0224]: at least one non-builtin trait is required for an object type - --> $DIR/trait-alias-maybe-bound.rs:24:12 + --> $DIR/trait-alias-only-maybe-bound.rs:19:12 | -LL | type _T3 = dyn _2; +LL | type _T1 = dyn _2; | ^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/wf-trait-object-no-duplicates.stderr b/src/test/ui/traits/wf-trait-object-no-duplicates.stderr index 75dacb2e1565..269d92fe43db 100644 --- a/src/test/ui/traits/wf-trait-object-no-duplicates.stderr +++ b/src/test/ui/traits/wf-trait-object-no-duplicates.stderr @@ -2,41 +2,56 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec --> $DIR/wf-trait-object-no-duplicates.rs:8:21 | LL | type _0 = dyn Obj + Obj; - | --- ^^^ additional non-auto trait - | | + | --- ^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/wf-trait-object-no-duplicates.rs:13:28 | LL | type _1 = dyn Send + Obj + Obj; - | --- ^^^ additional non-auto trait - | | + | --- ^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/wf-trait-object-no-duplicates.rs:16:28 | LL | type _2 = dyn Obj + Send + Obj; - | --- ^^^ additional non-auto trait - | | + | --- ^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/wf-trait-object-no-duplicates.rs:26:34 | LL | type _4 = dyn for<'a> ObjL<'a> + for<'b> ObjL<'b>; - | ---------------- ^^^^^^^^^^^^^^^^ additional non-auto trait - | | + | ---------------- ^^^^^^^^^^^^^^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) | first non-auto trait + | trait alias used in trait object type (first use) error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/wf-trait-object-no-duplicates.rs:30:42 | LL | type _5 = dyn ObjT fn(&'a u8)> + ObjT fn(&'b u8)>; - | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^ additional non-auto trait - | | + | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | additional non-auto trait + | | trait alias used in trait object type (additional use) | first non-auto trait + | trait alias used in trait object type (first use) error: aborting due to 5 previous errors diff --git a/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr b/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr index ba24b8342118..7a5080bbd0c0 100644 --- a/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr +++ b/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr @@ -1,5 +1,5 @@ error[E0224]: at least one non-builtin trait is required for an object type - --> $DIR/wf-trait-object-maybe-bound.rs:4:11 + --> $DIR/wf-trait-object-only-maybe-bound.rs:3:11 | LL | type _0 = dyn ?Sized; | ^^^^^^^^^^ From a0a61904f4b38c76fe32c7cda57626be94b9c65a Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Mon, 13 May 2019 19:51:33 +0100 Subject: [PATCH 0185/3207] Addressed more points raised in review. --- src/librustc/traits/mod.rs | 4 +-- src/librustc/traits/util.rs | 66 ++++++++++++++-------------------- src/librustc_typeck/astconv.rs | 18 +++++----- 3 files changed, 38 insertions(+), 50 deletions(-) diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index d950746f6e6d..a4b9ed0a206b 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -63,9 +63,7 @@ pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_ pub use self::util::{ supertraits, supertrait_def_ids, transitive_bounds, Supertraits, SupertraitDefIds, }; -pub use self::util::{ - expand_trait_aliases, TraitAliasExpander, TraitAliasExpansionInfoDignosticBuilder, -}; +pub use self::util::{expand_trait_aliases, TraitAliasExpander}; pub use self::chalk_fulfill::{ CanonicalGoal as ChalkCanonicalGoal, diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 77588d713dfc..5ba23a9c45a4 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -132,18 +132,18 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> { // Get predicates declared on the trait. let predicates = tcx.super_predicates_of(data.def_id()); - let mut predicates: Vec<_> = predicates.predicates + let predicates = predicates.predicates .iter() - .map(|(pred, _)| pred.subst_supertrait(tcx, &data.to_poly_trait_ref())) - .collect(); + .map(|(pred, _)| pred.subst_supertrait(tcx, &data.to_poly_trait_ref())); debug!("super_predicates: data={:?} predicates={:?}", - data, predicates); + data, predicates.clone()); // Only keep those bounds that we haven't already seen. // This is necessary to prevent infinite recursion in some // cases. One common case is when people define // `trait Sized: Sized { }` rather than `trait Sized { }`. - predicates.retain(|pred| self.visited.insert(pred)); + let visited = &mut self.visited; + let predicates = predicates.filter(|pred| visited.insert(pred)); self.stack.extend(predicates); } @@ -298,13 +298,21 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> { } } - fn clone_and_push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self { - let mut path = self.path.clone(); - path.push((trait_ref, span)); - - Self { - path + /// Adds diagnostic labels to `diag` for the expansion path of a trait through all intermediate + /// trait aliases. + pub fn label_with_exp_info(&self, + diag: &mut DiagnosticBuilder<'_>, + top_label: &str, + use_desc: &str + ) { + diag.span_label(self.top().1, top_label); + if self.path.len() > 1 { + for (_, sp) in self.path.iter().rev().skip(1).take(self.path.len() - 2) { + diag.span_label(*sp, format!("referenced here ({})", use_desc)); + } } + diag.span_label(self.bottom().1, + format!("trait alias used in trait object type ({})", use_desc)); } pub fn trait_ref(&self) -> &ty::PolyTraitRef<'tcx> { @@ -318,33 +326,14 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> { pub fn bottom(&self) -> &(ty::PolyTraitRef<'tcx>, Span) { self.path.first().unwrap() } -} -/// Emits diagnostic information relating to the expansion of a trait via trait aliases -/// (see [`TraitAliasExpansionInfo`]). -pub trait TraitAliasExpansionInfoDignosticBuilder { - fn label_with_exp_info<'tcx>(&mut self, - info: &TraitAliasExpansionInfo<'tcx>, - top_label: &str, - use_desc: &str - ) -> &mut Self; -} + fn clone_and_push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self { + let mut path = self.path.clone(); + path.push((trait_ref, span)); -impl<'a> TraitAliasExpansionInfoDignosticBuilder for DiagnosticBuilder<'a> { - fn label_with_exp_info<'tcx>(&mut self, - info: &TraitAliasExpansionInfo<'tcx>, - top_label: &str, - use_desc: &str - ) -> &mut Self { - self.span_label(info.top().1, top_label); - if info.path.len() > 1 { - for (_, sp) in info.path.iter().rev().skip(1).take(info.path.len() - 2) { - self.span_label(*sp, format!("referenced here ({})", use_desc)); - } + Self { + path } - self.span_label(info.bottom().1, - format!("trait alias used in trait object type ({})", use_desc)); - self } } @@ -388,16 +377,15 @@ impl<'cx, 'gcx, 'tcx> TraitAliasExpander<'cx, 'gcx, 'tcx> { // Get components of trait alias. let predicates = tcx.super_predicates_of(trait_ref.def_id()); - let items: Vec<_> = predicates.predicates + let items = predicates.predicates .iter() .rev() .filter_map(|(pred, span)| { pred.subst_supertrait(tcx, &trait_ref) .to_opt_poly_trait_ref() .map(|trait_ref| item.clone_and_push(trait_ref, *span)) - }) - .collect(); - debug!("expand_trait_aliases: items={:?}", items); + }); + debug!("expand_trait_aliases: items={:?}", items.clone()); self.stack.extend(items); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 7d4243c4842e..ce5963e3ce5c 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -11,7 +11,7 @@ use crate::lint; use crate::middle::resolve_lifetime as rl; use crate::namespace::Namespace; use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; -use rustc::traits::{self, TraitAliasExpansionInfoDignosticBuilder}; +use rustc::traits; use rustc::ty::{self, DefIdTree, Ty, TyCtxt, ToPredicate, TypeFoldable}; use rustc::ty::{GenericParamDef, GenericParamDefKind}; use rustc::ty::subst::{Kind, Subst, InternalSubsts, SubstsRef}; @@ -976,6 +976,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { let mut projection_bounds = Vec::new(); let mut potential_assoc_types = Vec::new(); let dummy_self = self.tcx().types.trait_object_dummy_self; + // FIXME: we want to avoid collecting into a `Vec` here, but simply cloning the iterator is + // not straightforward due to the borrow checker. let bound_trait_refs: Vec<_> = trait_bounds .iter() .rev() @@ -998,14 +1000,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { if regular_traits.len() > 1 { let first_trait = ®ular_traits[0]; let additional_trait = ®ular_traits[1]; - struct_span_err!(tcx.sess, additional_trait.bottom().1, E0225, + let mut err = struct_span_err!(tcx.sess, additional_trait.bottom().1, E0225, "only auto traits can be used as additional traits in a trait object" - ) - .label_with_exp_info(additional_trait, "additional non-auto trait", - "additional use") - .label_with_exp_info(first_trait, "first non-auto trait", - "first use") - .emit(); + ); + additional_trait.label_with_exp_info(&mut err, + "additional non-auto trait", "additional use"); + first_trait.label_with_exp_info(&mut err, + "first non-auto trait", "first use"); + err.emit(); } if regular_traits.is_empty() && auto_traits.is_empty() { From ce75a23c0d56764cef7c633139f01b80f040cd25 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Sun, 19 May 2019 22:26:42 +0100 Subject: [PATCH 0186/3207] Reinstated shallow disallowing of maybe bounds in trait objects. --- src/librustc_passes/ast_validation.rs | 1 + src/test/ui/maybe-bounds.rs | 5 ++- src/test/ui/maybe-bounds.stderr | 14 +++++++- .../ui/parser/trait-object-trait-parens.rs | 2 ++ .../parser/trait-object-trait-parens.stderr | 16 ++++++++-- .../ui/traits/wf-trait-object-maybe-bound.rs | 7 +++- .../traits/wf-trait-object-maybe-bound.stderr | 32 +++++++++++++++++++ .../wf-trait-object-only-maybe-bound.rs | 1 + .../wf-trait-object-only-maybe-bound.stderr | 8 ++++- 9 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/traits/wf-trait-object-maybe-bound.stderr diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index d70c81854955..2bea1db841ae 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -504,6 +504,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { any_lifetime_bounds = true; } } + self.no_questions_in_bounds(bounds, "trait object types", false); } TyKind::ImplTrait(_, ref bounds) => { if self.is_impl_trait_banned { diff --git a/src/test/ui/maybe-bounds.rs b/src/test/ui/maybe-bounds.rs index 95d14f6d1da3..02ed45c656f1 100644 --- a/src/test/ui/maybe-bounds.rs +++ b/src/test/ui/maybe-bounds.rs @@ -1,6 +1,9 @@ -trait Tr: ?Sized {} //~ ERROR `?Trait` is not permitted in supertraits +trait Tr: ?Sized {} +//~^ ERROR `?Trait` is not permitted in supertraits type A1 = dyn Tr + (?Sized); +//~^ ERROR `?Trait` is not permitted in trait object types type A2 = dyn for<'a> Tr + (?Sized); +//~^ ERROR `?Trait` is not permitted in trait object types fn main() {} diff --git a/src/test/ui/maybe-bounds.stderr b/src/test/ui/maybe-bounds.stderr index d8c2adfc61c5..1d823b6acb28 100644 --- a/src/test/ui/maybe-bounds.stderr +++ b/src/test/ui/maybe-bounds.stderr @@ -6,5 +6,17 @@ LL | trait Tr: ?Sized {} | = note: traits are `?Sized` by default -error: aborting due to previous error +error: `?Trait` is not permitted in trait object types + --> $DIR/maybe-bounds.rs:4:20 + | +LL | type A1 = dyn Tr + (?Sized); + | ^^^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/maybe-bounds.rs:6:28 + | +LL | type A2 = dyn for<'a> Tr + (?Sized); + | ^^^^^^^^ + +error: aborting due to 3 previous errors diff --git a/src/test/ui/parser/trait-object-trait-parens.rs b/src/test/ui/parser/trait-object-trait-parens.rs index 49373564f673..9ac10cd13279 100644 --- a/src/test/ui/parser/trait-object-trait-parens.rs +++ b/src/test/ui/parser/trait-object-trait-parens.rs @@ -4,7 +4,9 @@ fn f Trait<'a>)>() {} fn main() { let _: Box<(Copy) + (?Sized) + (for<'a> Trait<'a>)>; + //~^ ERROR `?Trait` is not permitted in trait object types let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Copy)>; let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>; //~^ ERROR use of undeclared lifetime name `'a` + //~| ERROR `?Trait` is not permitted in trait object types } diff --git a/src/test/ui/parser/trait-object-trait-parens.stderr b/src/test/ui/parser/trait-object-trait-parens.stderr index 1cf40b30406c..36494b765394 100644 --- a/src/test/ui/parser/trait-object-trait-parens.stderr +++ b/src/test/ui/parser/trait-object-trait-parens.stderr @@ -1,9 +1,21 @@ +error: `?Trait` is not permitted in trait object types + --> $DIR/trait-object-trait-parens.rs:6:25 + | +LL | let _: Box<(Copy) + (?Sized) + (for<'a> Trait<'a>)>; + | ^^^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/trait-object-trait-parens.rs:9:47 + | +LL | let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>; + | ^^^^^^^^ + error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/trait-object-trait-parens.rs:8:31 + --> $DIR/trait-object-trait-parens.rs:9:31 | LL | let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>; | ^^ undeclared lifetime -error: aborting due to previous error +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0261`. diff --git a/src/test/ui/traits/wf-trait-object-maybe-bound.rs b/src/test/ui/traits/wf-trait-object-maybe-bound.rs index 405104fe0814..f24c1301c53a 100644 --- a/src/test/ui/traits/wf-trait-object-maybe-bound.rs +++ b/src/test/ui/traits/wf-trait-object-maybe-bound.rs @@ -1,15 +1,20 @@ -// compile-pass +// compile-fail // Test that `dyn ... + ?Sized + ...` is okay (though `?Sized` has no effect in trait objects). trait Foo {} type _0 = dyn ?Sized + Foo; +//~^ ERROR `?Trait` is not permitted in trait object types type _1 = dyn Foo + ?Sized; +//~^ ERROR `?Trait` is not permitted in trait object types type _2 = dyn Foo + ?Sized + ?Sized; +//~^ ERROR `?Trait` is not permitted in trait object types +//~| ERROR `?Trait` is not permitted in trait object types type _3 = dyn ?Sized + Foo; +//~^ ERROR `?Trait` is not permitted in trait object types fn main() {} diff --git a/src/test/ui/traits/wf-trait-object-maybe-bound.stderr b/src/test/ui/traits/wf-trait-object-maybe-bound.stderr new file mode 100644 index 000000000000..11187342d59f --- /dev/null +++ b/src/test/ui/traits/wf-trait-object-maybe-bound.stderr @@ -0,0 +1,32 @@ +error: `?Trait` is not permitted in trait object types + --> $DIR/wf-trait-object-maybe-bound.rs:7:15 + | +LL | type _0 = dyn ?Sized + Foo; + | ^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/wf-trait-object-maybe-bound.rs:10:21 + | +LL | type _1 = dyn Foo + ?Sized; + | ^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/wf-trait-object-maybe-bound.rs:13:21 + | +LL | type _2 = dyn Foo + ?Sized + ?Sized; + | ^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/wf-trait-object-maybe-bound.rs:13:30 + | +LL | type _2 = dyn Foo + ?Sized + ?Sized; + | ^^^^^^ + +error: `?Trait` is not permitted in trait object types + --> $DIR/wf-trait-object-maybe-bound.rs:17:15 + | +LL | type _3 = dyn ?Sized + Foo; + | ^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/traits/wf-trait-object-only-maybe-bound.rs b/src/test/ui/traits/wf-trait-object-only-maybe-bound.rs index c8e6ac38b5a3..1b83d2487f4c 100644 --- a/src/test/ui/traits/wf-trait-object-only-maybe-bound.rs +++ b/src/test/ui/traits/wf-trait-object-only-maybe-bound.rs @@ -2,5 +2,6 @@ type _0 = dyn ?Sized; //~^ ERROR at least one non-builtin trait is required for an object type [E0224] +//~| ERROR ?Trait` is not permitted in trait object types fn main() {} diff --git a/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr b/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr index 7a5080bbd0c0..0cfb389fd899 100644 --- a/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr +++ b/src/test/ui/traits/wf-trait-object-only-maybe-bound.stderr @@ -1,8 +1,14 @@ +error: `?Trait` is not permitted in trait object types + --> $DIR/wf-trait-object-only-maybe-bound.rs:3:15 + | +LL | type _0 = dyn ?Sized; + | ^^^^^^ + error[E0224]: at least one non-builtin trait is required for an object type --> $DIR/wf-trait-object-only-maybe-bound.rs:3:11 | LL | type _0 = dyn ?Sized; | ^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors From ce2ee305f9165c037ecddddb5792588a15ff6c37 Mon Sep 17 00:00:00 2001 From: Alexander Regueiro Date: Mon, 20 May 2019 16:19:34 +0100 Subject: [PATCH 0187/3207] Fixed nits raised in review. --- src/librustc/hir/mod.rs | 2 +- src/librustc/infer/outlives/verify.rs | 4 ++-- src/librustc/query/mod.rs | 8 ++++---- src/librustc_save_analysis/dump_visitor.rs | 2 +- src/librustc_typeck/astconv.rs | 6 +++--- src/librustc_typeck/collect.rs | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index fafe1cf85a3e..fd7a83427efe 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2143,7 +2143,7 @@ pub enum UseKind { ListStem, } -/// `TraitRef` are references to traits in impls. +/// References to traits in impls. /// /// `resolve` maps each `TraitRef`'s `ref_id` to its defining trait; that's all /// that the `ref_id` is for. Note that `ref_id`'s value is not the `NodeId` of the diff --git a/src/librustc/infer/outlives/verify.rs b/src/librustc/infer/outlives/verify.rs index 5b8d89c865a5..e1ad5aeea19f 100644 --- a/src/librustc/infer/outlives/verify.rs +++ b/src/librustc/infer/outlives/verify.rs @@ -141,9 +141,9 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> { } fn recursive_type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> { - let mut bounds: Vec<_> = ty.walk_shallow() + let mut bounds = ty.walk_shallow() .map(|subty| self.type_bound(subty)) - .collect(); + .collect::>(); let mut regions = smallvec![]; ty.push_regions(&mut regions); diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index d043a32f06bd..8825c94cdb81 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -248,12 +248,12 @@ rustc_queries! { desc { "computing the variances for items in this crate" } } - /// Maps from def-ID of a type or region parameter to its (inferred) variance. + /// Maps from the `DefId` of a type or region parameter to its (inferred) variance. query variances_of(_: DefId) -> &'tcx [ty::Variance] {} } TypeChecking { - /// Maps from def-ID of a type to its (inferred) outlives. + /// Maps from thee `DefId` of a type to its (inferred) outlives. query inferred_outlives_crate(_: CrateNum) -> Lrc> { desc { "computing the inferred outlives predicates for items in this crate" } @@ -261,7 +261,7 @@ rustc_queries! { } Other { - /// Maps from an impl/trait def-ID to a list of the def-ids of its items. + /// Maps from an impl/trait `DefId to a list of the `DefId`s of its items. query associated_item_def_ids(_: DefId) -> Lrc> {} /// Maps from a trait item to the trait item "descriptor". @@ -274,7 +274,7 @@ rustc_queries! { } TypeChecking { - /// Maps a def-ID of a type to a list of its inherent impls. + /// Maps a `DefId` of a type to a list of its inherent impls. /// Contains implementations of methods that are inherent to a type. /// Methods in these implementations don't need to be exported. query inherent_impls(_: DefId) -> Lrc> { diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 5f184bf4a7d4..1fdfcc84926f 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1216,7 +1216,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { let hir_id = self.tcx.hir().node_to_hir_id(id); let access = access_from!(self.save_ctxt, root_item, hir_id); - // The parent def-ID of a given use tree is always the enclosing item. + // The parent `DefId` of a given use tree is always the enclosing item. let parent = self.save_ctxt.tcx.hir().opt_local_def_id(id) .and_then(|id| self.save_ctxt.tcx.parent(id)) .map(id_from_def_id); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index ce5963e3ce5c..4110a5584019 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -702,7 +702,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } /// Instantiates the path for the given trait reference, assuming that it's - /// bound to a valid trait type. Returns the def-ID for the defining trait. + /// bound to a valid trait type. Returns the `DefId` of the defining trait. /// The type _cannot_ be a type other than a trait type. /// /// If the `projections` argument is `None`, then assoc type bindings like `Foo` @@ -994,7 +994,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { // Expand trait aliases recursively and check that only one regular (non-auto) trait // is used and no 'maybe' bounds are used. - let expanded_traits = traits::expand_trait_aliases(tcx, bound_trait_refs.clone()); + let expanded_traits = traits::expand_trait_aliases(tcx, bound_trait_refs.iter().cloned()); let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); if regular_traits.len() > 1 { @@ -1240,7 +1240,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } // Search for a bound on a type parameter which includes the associated item - // given by `assoc_name`. `ty_param_def_id` is the `DefId` for the type parameter + // given by `assoc_name`. `ty_param_def_id` is the `DefId` of the type parameter // This function will fail if there are no suitable bounds or there is // any ambiguity. fn find_bound_for_assoc_item(&self, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 104c8e25d138..7adf86a99bd4 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -713,9 +713,9 @@ fn super_predicates_of<'a, 'tcx>( let superbounds1 = superbounds1.predicates(tcx, self_param_ty); - // Convert any explicit superbounds in the wheree-clause, + // Convert any explicit superbounds in the where-clause, // e.g., `trait Foo where Self: Bar`. - // In the case of trait aliases, however, we include all bounds in the where clause, + // In the case of trait aliases, however, we include all bounds in the where-clause, // so e.g., `trait Foo = where u32: PartialEq` would include `u32: PartialEq` // as one of its "superpredicates". let is_trait_alias = tcx.is_trait_alias(trait_def_id); From 79d28c203fbf46739d2e3f1f2f3e62bdf1ac5563 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 20 May 2019 11:27:18 -0700 Subject: [PATCH 0188/3207] Don't bother with `stamp` utility That was just used because Travis doesn't have time stamps on all log lines, but Azure does, so no need to add our own. --- .azure-pipelines/steps/linux.yml | 3 --- .azure-pipelines/steps/macos.yml | 3 --- .azure-pipelines/steps/run-script.yml | 2 +- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/.azure-pipelines/steps/linux.yml b/.azure-pipelines/steps/linux.yml index 36f980cf992d..70327de92e81 100644 --- a/.azure-pipelines/steps/linux.yml +++ b/.azure-pipelines/steps/linux.yml @@ -8,9 +8,6 @@ steps: - bash: | sudo apt install gdb - curl -fo $HOME/stamp https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-03-17-stamp-x86_64-unknown-linux-musl - chmod +x $HOME/stamp - export PATH=$PATH:$HOME/.local/bin:$HOME/Library/Python/2.7/bin/:$HOME echo "##vso[task.prependpath]$HOME/.local/bin" echo "##vso[task.prependpath]$HOME/Library/Python/2.7/bin" diff --git a/.azure-pipelines/steps/macos.yml b/.azure-pipelines/steps/macos.yml index d1adc3403921..5976f31502f7 100644 --- a/.azure-pipelines/steps/macos.yml +++ b/.azure-pipelines/steps/macos.yml @@ -9,9 +9,6 @@ steps: curl -fo /usr/local/bin/sccache https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-02-sccache-x86_64-apple-darwin chmod +x /usr/local/bin/sccache - curl -fo /usr/local/bin/stamp https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-03-17-stamp-x86_64-apple-darwin - chmod +x /usr/local/bin/stamp - export CC=`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang echo "##vso[task.setvariable variable=CC]$CC" diff --git a/.azure-pipelines/steps/run-script.yml b/.azure-pipelines/steps/run-script.yml index bf18518e6b1c..0e6af4d6d12b 100644 --- a/.azure-pipelines/steps/run-script.yml +++ b/.azure-pipelines/steps/run-script.yml @@ -6,7 +6,7 @@ steps: date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true) which sccache - stamp sh -x -c "$RUN_SCRIPT" + "$RUN_SCRIPT" date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true) env: From d320c7ceab4371e6fd508a1f79742be042d97d2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 20 May 2019 11:46:44 -0700 Subject: [PATCH 0189/3207] Do not fail on child without DefId --- src/librustc_metadata/cstore_impl.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 087256a97105..e6710d668dc3 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -355,19 +355,19 @@ pub fn provide<'tcx>(providers: &mut Providers<'tcx>) { return; } - let child = child.res.def_id(); - - match visible_parent_map.entry(child) { - Entry::Occupied(mut entry) => { - // If `child` is defined in crate `cnum`, ensure - // that it is mapped to a parent in `cnum`. - if child.krate == cnum && entry.get().krate != cnum { - entry.insert(parent); + if let Some(child) = child.res.opt_def_id() { + match visible_parent_map.entry(child) { + Entry::Occupied(mut entry) => { + // If `child` is defined in crate `cnum`, ensure + // that it is mapped to a parent in `cnum`. + if child.krate == cnum && entry.get().krate != cnum { + entry.insert(parent); + } + } + Entry::Vacant(entry) => { + entry.insert(parent); + bfs_queue.push_back(child); } - } - Entry::Vacant(entry) => { - entry.insert(parent); - bfs_queue.push_back(child); } } }; From 1be9fe6a449148d2f31b3e82f4d983630442d981 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 20 May 2019 12:21:14 -0700 Subject: [PATCH 0190/3207] Refactor azure pipelines configuration This commit is intended to go through and review/refactor the azure pipelines configuration we have. The major changes are: * The separate `{windows,macos,linux}.yml` files are now all merged into one `run.yml`. This allows a shared "master flow" for all platforms with divergence only where necessary. * Some install steps have been separated as `install-*.yml` scripts, where each script internally matches on the appropriate OS and then delegates accordingly. * Some various bits and pieces of cruft have been removed which were artifacts of Travis's setup or similar. --- .azure-pipelines/auto.yml | 9 +- .azure-pipelines/pr.yml | 3 +- .azure-pipelines/steps/install-clang.yml | 40 +++++++ .azure-pipelines/steps/install-sccache.yml | 21 ++++ ...ows.yml => install-windows-build-deps.yml} | 103 ++++-------------- .azure-pipelines/steps/linux.yml | 32 ------ .azure-pipelines/steps/macos.yml | 44 -------- .azure-pipelines/steps/run-script.yml | 35 ------ .azure-pipelines/steps/run.yml | 89 +++++++++++++++ .azure-pipelines/steps/show-disk-usage.yml | 5 - .../steps/show-environment-variables.yml | 3 - .../steps/verify-publish-toolstate.yml | 9 -- .azure-pipelines/try.yml | 3 +- 13 files changed, 174 insertions(+), 222 deletions(-) create mode 100644 .azure-pipelines/steps/install-clang.yml create mode 100644 .azure-pipelines/steps/install-sccache.yml rename .azure-pipelines/steps/{windows.yml => install-windows-build-deps.yml} (52%) delete mode 100644 .azure-pipelines/steps/linux.yml delete mode 100644 .azure-pipelines/steps/macos.yml delete mode 100644 .azure-pipelines/steps/run-script.yml create mode 100644 .azure-pipelines/steps/run.yml delete mode 100644 .azure-pipelines/steps/show-disk-usage.yml delete mode 100644 .azure-pipelines/steps/show-environment-variables.yml diff --git a/.azure-pipelines/auto.yml b/.azure-pipelines/auto.yml index 05d33e2f9d59..3b6cfed70719 100644 --- a/.azure-pipelines/auto.yml +++ b/.azure-pipelines/auto.yml @@ -11,11 +11,10 @@ variables: jobs: - job: Linux - timeoutInMinutes: 180 pool: vmImage: ubuntu-16.04 steps: - - template: steps/linux.yml + - template: steps/run.yml strategy: matrix: x86_64-gnu-llvm-6.0: @@ -151,13 +150,12 @@ jobs: IMAGE: mingw-check - job: macOS - timeoutInMinutes: 180 pool: vmImage: macos-10.13 steps: - checkout: self fetchDepth: 2 - - template: steps/macos.yml + - template: steps/run.yml strategy: matrix: # OSX builders running tests, these run the full test suite. @@ -216,11 +214,10 @@ jobs: - job: Windows - timeoutInMinutes: 180 pool: vmImage: 'vs2017-win2016' steps: - - template: steps/windows.yml + - template: steps/run.yml strategy: matrix: # # 32/64 bit MSVC tests diff --git a/.azure-pipelines/pr.yml b/.azure-pipelines/pr.yml index fe20e35e344a..84c9454fee57 100644 --- a/.azure-pipelines/pr.yml +++ b/.azure-pipelines/pr.yml @@ -8,11 +8,10 @@ pr: jobs: - job: Linux - timeoutInMinutes: 180 pool: vmImage: ubuntu-16.04 steps: - - template: steps/linux.yml + - template: steps/run.yml strategy: matrix: x86_64-gnu-llvm-6.0: diff --git a/.azure-pipelines/steps/install-clang.yml b/.azure-pipelines/steps/install-clang.yml new file mode 100644 index 000000000000..9e3545ea93cb --- /dev/null +++ b/.azure-pipelines/steps/install-clang.yml @@ -0,0 +1,40 @@ +steps: + +- bash: | + set -e + curl -f http://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz | tar xJf - + + export CC=`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang + echo "##vso[task.setvariable variable=CC]$CC" + + export CXX=`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang++ + echo "##vso[task.setvariable variable=CXX]$CXX" + + # Configure `AR` specifically so rustbuild doesn't try to infer it as + # `clang-ar` by accident. + echo "##vso[task.setvariable variable=AR]ar" + displayName: Install clang (OSX) + condition: eq(variables['Agent.OS'], 'Darwin') + +# If we're compiling for MSVC then we, like most other distribution builders, +# switch to clang as the compiler. This'll allow us eventually to enable LTO +# amongst LLVM and rustc. Note that we only do this on MSVC as I don't think +# clang has an output mode compatible with MinGW that we need. If it does we +# should switch to clang for MinGW as well! +# +# Note that the LLVM installer is an NSIS installer +# +# Original downloaded here came from +# http://releases.llvm.org/7.0.0/LLVM-7.0.0-win64.exe +- script: | + powershell -Command "iwr -outf %TEMP%\LLVM-7.0.0-win64.exe https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/LLVM-7.0.0-win64.exe" + set CLANG_DIR=%CD%\citools\clang-rust + %TEMP%\LLVM-7.0.0-win64.exe /S /NCRC /D=%CLANG_DIR% + set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --set llvm.clang-cl=%CLANG_DIR%\bin\clang-cl.exe + echo ##vso[task.setvariable variable=RUST_CONFIGURE_ARGS]%RUST_CONFIGURE_ARGS% + condition: and(eq(variables['Agent.OS'], 'Darwin'), eq(variables['MINGW_URL'],'')) + displayName: Install clang (Windows) + +# Note that we don't install clang on Linux since its compiler story is just so +# different. Each container has its own toolchain configured appropriately +# already. diff --git a/.azure-pipelines/steps/install-sccache.yml b/.azure-pipelines/steps/install-sccache.yml new file mode 100644 index 000000000000..6933f4e9f279 --- /dev/null +++ b/.azure-pipelines/steps/install-sccache.yml @@ -0,0 +1,21 @@ +steps: + +- bash: | + set -e + curl -fo /usr/local/bin/sccache https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-02-sccache-x86_64-apple-darwin + chmod +x /usr/local/bin/sccache + displayName: Install sccache (OSX) + condition: eq(variables['Agent.OS'], 'Darwin') + +- script: | + md sccache + powershell -Command "iwr -outf sccache\sccache.exe https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-26-sccache-x86_64-pc-windows-msvc" + echo ##vso[task.prependpath]%CD%\sccache + displayName: Install sccache (Windows) + condition: eq(variables['Agent.OS'], 'Windows_NT') + +# Note that we don't install sccache on Linux since it's installed elsewhere +# through all the containers. +# +# FIXME: we should probably install sccache outside the containers and then +# mount it inside the containers so we can centralize all installation here. diff --git a/.azure-pipelines/steps/windows.yml b/.azure-pipelines/steps/install-windows-build-deps.yml similarity index 52% rename from .azure-pipelines/steps/windows.yml rename to .azure-pipelines/steps/install-windows-build-deps.yml index 5fb1da2083f7..4eab460543bb 100644 --- a/.azure-pipelines/steps/windows.yml +++ b/.azure-pipelines/steps/install-windows-build-deps.yml @@ -1,19 +1,17 @@ steps: -- checkout: self - fetchDepth: 2 - -- bash: | - set -x - git submodule - export SUBMODULES_EXCLUDES=$(git submodule | grep -Eow 'src/[^ ]+' | sed 's/\(.*\)/--exclude=\1\/\.git/') - echo "##vso[task.setvariable variable=SUBMODULES_EXCLUDES;]$SUBMODULES_EXCLUDES" - -- script: | - REM echo hack as drive D is too small - IF NOT "%DISABLE_DISK_SPACE_HACK%"=="1" ( - mkdir c:\MORE_SPACE - mklink /J build c:\MORE_SPACE - ) +# FIXME: are these still needed? +# - bash: | +# set -x +# git submodule +# export SUBMODULES_EXCLUDES=$(git submodule | grep -Eow 'src/[^ ]+' | sed 's/\(.*\)/--exclude=\1\/\.git/') +# echo "##vso[task.setvariable variable=SUBMODULES_EXCLUDES;]$SUBMODULES_EXCLUDES" +# +# - script: | +# REM echo hack as drive D is too small +# IF NOT "%DISABLE_DISK_SPACE_HACK%"=="1" ( +# mkdir c:\MORE_SPACE +# mklink /J build c:\MORE_SPACE +# ) - script: | set MSYS_PATH=%CD%\citools\msys64 @@ -31,6 +29,7 @@ steps: echo ##vso[task.setvariable variable=MSYS_PATH]%MSYS_PATH% echo ##vso[task.prependpath]%MSYS_PATH%\usr\bin displayName: Install msys2 + condition: eq(variables['Agent.OS'], 'Windows_NT') # If we need to download a custom MinGW, do so here and set the path # appropriately. @@ -44,28 +43,9 @@ steps: powershell -Command "iwr -outf %MINGW_ARCHIVE% %MINGW_URL%/%MINGW_ARCHIVE%" 7z x -y %MINGW_ARCHIVE% > nul echo ##vso[task.prependpath]%CD%\%MINGW_DIR%\bin - condition: and(succeeded(), ne(variables['MINGW_URL'],'')) + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), ne(variables['MINGW_URL'],'')) displayName: Download custom MinGW -# If we're compiling for MSVC then we, like most other distribution builders, -# switch to clang as the compiler. This'll allow us eventually to enable LTO -# amongst LLVM and rustc. Note that we only do this on MSVC as I don't think -# clang has an output mode compatible with MinGW that we need. If it does we -# should switch to clang for MinGW as well! -# -# Note that the LLVM installer is an NSIS installer -# -# Original downloaded here came from -# http://releases.llvm.org/7.0.0/LLVM-7.0.0-win64.exe -- script: | - powershell -Command "iwr -outf %TEMP%\LLVM-7.0.0-win64.exe https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/LLVM-7.0.0-win64.exe" - set CLANG_DIR=%CD%\citools\clang-rust - %TEMP%\LLVM-7.0.0-win64.exe /S /NCRC /D=%CLANG_DIR% - set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --set llvm.clang-cl=%CLANG_DIR%\bin\clang-cl.exe - echo ##vso[task.setvariable variable=RUST_CONFIGURE_ARGS]%RUST_CONFIGURE_ARGS% - condition: and(succeeded(), eq(variables['MINGW_URL'],'')) - displayName: Download clang - # Here we do a pretty heinous thing which is to mangle the MinGW installation # we just had above. Currently, as of this writing, we're using MinGW-w64 # builds of gcc, and that's currently at 6.3.0. We use 6.3.0 as it appears to @@ -87,28 +67,20 @@ steps: echo ON powershell -Command "iwr -outf 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_URL%/2017-04-20-%MSYS_BITS%bit-gdborig.exe" mv 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_DIR%\bin\gdborig.exe - condition: and(succeeded(), ne(variables['MINGW_URL'],'')) + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), ne(variables['MINGW_URL'],'')) displayName: Override with 6.3.0 gdb with 6.2.0 gdb # Otherwise pull in the MinGW installed on appveyor - script: | - echo Find mingw - set PATH | findstr /i msys - set PATH | findstr /i mingw echo ##vso[task.prependpath]%MSYS_PATH%\mingw%MSYS_BITS%\bin - condition: and(succeeded(), eq(variables['MINGW_URL'],'')) + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), eq(variables['MINGW_URL'],'')) displayName: Add MinGW to path - script: | copy C:\Python27amd64\python.exe C:\Python27amd64\python2.7.exe echo ##vso[task.prependpath]C:\Python27amd64 displayName: Prefer the "native" Python as LLVM has trouble building with MSYS sometimes - -- script: | - md sccache - powershell -Command "iwr -outf sccache\sccache.exe https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-26-sccache-x86_64-pc-windows-msvc" - echo ##vso[task.prependpath]%CD%\sccache - displayName: Download and install sccache + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) # Note that this is originally from the github releases patch of Ninja - script: | @@ -120,41 +92,4 @@ steps: echo ##vso[task.setvariable variable=RUST_CONFIGURE_ARGS]%RUST_CONFIGURE_ARGS% echo ##vso[task.prependpath]%CD%\ninja displayName: Download and install ninja - -- script: | - mkdir handle - powershell -Command "iwr -outf 2017-05-15-Handle.zip https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2017-05-15-Handle.zip" - 7z x -ohandle 2017-05-15-Handle.zip - del 2017-05-15-Handle.zip - set PATH=%PATH%;%CD%\handle - handle.exe -accepteula -help - echo ##vso[task.setvariable variable=PATH]%PATH% - displayName: Help debug handle issues - -- template: show-environment-variables.yml - -- script: | - REM echo force the specific VS version - IF "%VCVARS_BAT%" NEQ "" ( - CALL "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\%VCVARS_BAT%" - ) - - where sccache - where rev - set | findstr /v SCCACHE_AZURE_CONNECTION_STRING - - if not exist D:\cache\rustsrc\NUL mkdir D:\cache\rustsrc - - sh src/ci/init_repo.sh . /d/cache/rustsrc - sh src/ci/run.sh - env: - CI: true - CI_JOB_NAME: $(System.JobDisplayName) - SRC: . - NO_CCACHE: 1 - - # explicitly decrypt secret variables - # see https://docs.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch - AWS_ACCESS_KEY_ID: $(SCCACHE_AWS_ACCESS_KEY_ID) - AWS_SECRET_ACCESS_KEY: $(SCCACHE_AWS_SECRET_ACCESS_KEY) - displayName: Run script + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) diff --git a/.azure-pipelines/steps/linux.yml b/.azure-pipelines/steps/linux.yml deleted file mode 100644 index 70327de92e81..000000000000 --- a/.azure-pipelines/steps/linux.yml +++ /dev/null @@ -1,32 +0,0 @@ -steps: -- checkout: self - fetchDepth: 2 - -- template: show-environment-variables.yml -- template: show-disk-usage.yml - -- bash: | - sudo apt install gdb - - export PATH=$PATH:$HOME/.local/bin:$HOME/Library/Python/2.7/bin/:$HOME - echo "##vso[task.prependpath]$HOME/.local/bin" - echo "##vso[task.prependpath]$HOME/Library/Python/2.7/bin" - echo "##vso[task.prependpath]$HOME" - - mkdir -p $HOME/rustsrc - displayName: Prep - -- bash: | - export RUN_SCRIPT="$BUILD_SOURCESDIRECTORY/src/ci/init_repo.sh . $HOME/rustsrc && src/ci/docker/run.sh $IMAGE" - echo "##vso[task.setvariable variable=IMAGE]$IMAGE" - echo "##vso[task.setvariable variable=RUN_SCRIPT]$RUN_SCRIPT" - displayName: Prepare run script - -- template: show-environment-variables.yml - -- bash: sudo sh -c 'echo "/checkout/obj/cores/core.%p.%E" > /proc/sys/kernel/core_pattern' - displayName: Enable core dump - -- template: verify-publish-toolstate.yml - -- template: run-script.yml diff --git a/.azure-pipelines/steps/macos.yml b/.azure-pipelines/steps/macos.yml deleted file mode 100644 index 5976f31502f7..000000000000 --- a/.azure-pipelines/steps/macos.yml +++ /dev/null @@ -1,44 +0,0 @@ -steps: -- template: show-disk-usage.yml - -- bash: | - export PATH=$PATH:$HOME/.local/bin:$HOME/Library/Python/2.7/bin/ - mkdir -p $HOME/rustsrc - echo "##vso[task.setvariable variable=PATH;]$PATH" - - curl -fo /usr/local/bin/sccache https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-02-sccache-x86_64-apple-darwin - chmod +x /usr/local/bin/sccache - - export CC=`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang - echo "##vso[task.setvariable variable=CC]$CC" - - export CXX=`pwd`/clang+llvm-7.0.0-x86_64-apple-darwin/bin/clang++ - echo "##vso[task.setvariable variable=CXX]$CXX" - - echo "##vso[task.setvariable variable=AR]ar" - displayName: Prep - -- bash: brew install gnu-tar - displayName: install a tar that works well - -- bash: | - curl -f http://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz | tar xJf - - displayName: Download clang - -- bash: | - brew update - brew install xz - brew install swig - condition: and(succeeded(), eq(variables['RUST_CHECK_TARGET'],'dist')) - displayName: Install xz and swigw - -- bash: | - export RUN_SCRIPT="$BUILD_SOURCESDIRECTORY/src/ci/init_repo.sh . $HOME/rustsrc && src/ci/run.sh" - echo "##vso[task.setvariable variable=RUN_SCRIPT]$RUN_SCRIPT" - displayName: Prepare run script (init and run) - -- template: show-environment-variables.yml - -- template: verify-publish-toolstate.yml - -- template: run-script.yml diff --git a/.azure-pipelines/steps/run-script.yml b/.azure-pipelines/steps/run-script.yml deleted file mode 100644 index 0e6af4d6d12b..000000000000 --- a/.azure-pipelines/steps/run-script.yml +++ /dev/null @@ -1,35 +0,0 @@ -steps: - -- bash: | - # Log time information from this machine and an external machine for insight into possible - # clock drift. Timezones don't matter since relative deltas give all the necessary info. - date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true) - - which sccache - "$RUN_SCRIPT" - - date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true) - env: - CI: true - CI_JOB_NAME: $(IMAGE) - SRC: . - - # Explicitly decrypt secret variables - # See https://docs.microsoft.com/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch#secret-variables - AWS_ACCESS_KEY_ID: $(SCCACHE_AWS_ACCESS_KEY_ID) - AWS_SECRET_ACCESS_KEY: $(SCCACHE_AWS_SECRET_ACCESS_KEY) - displayName: Run script - -- bash: | - deploy_dir=rustc-builds - if [ "$DEPLOY_ALT" == "1" ]; then - deploy_dir=rustc-builds-alt - fi - aws s3 cp --no-progress --recursive --acl public-read ./deploy s3://$DEPLOY_BUCKET/$deploy_dir - env: - # Explicitly decrypt secret variables - # See https://docs.microsoft.com/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch#secret-variables - AWS_ACCESS_KEY_ID: $(SCCACHE_AWS_ACCESS_KEY_ID) - AWS_SECRET_ACCESS_KEY: $(SCCACHE_AWS_SECRET_ACCESS_KEY) - condition: and(succeeded(), or(eq(variables.DEPLOY, '1'), eq(variables.DEPLOY_ALT, '1'))) - displayName: Upload artifacts diff --git a/.azure-pipelines/steps/run.yml b/.azure-pipelines/steps/run.yml new file mode 100644 index 000000000000..06bb8eb4dc8e --- /dev/null +++ b/.azure-pipelines/steps/run.yml @@ -0,0 +1,89 @@ +# FIXME(linux): need to configure core dumps, enable them, and then dump +# backtraces on failure from all core dumps: +# +# - bash: sudo apt install gdb +# - bash: sudo sh -c 'echo "/checkout/obj/cores/core.%p.%E" > /proc/sys/kernel/core_pattern' +# +# Check travis config for `gdb --batch` command to print all crash logs + +steps: +- checkout: self + fetchDepth: 2 + +- bash: printenv | sort + displayName: Show environment variables + +- bash: | + set -e + df -h + du . | sort -nr | head -n100 + displayName: Show disk usage + # FIXME: this hasn't been tested, but maybe it works on Windows? Should test! + condition: ne(variables['Agent.OS'], 'Windows_NT') + +- template: install-sccache.yml +- template: install-clang.yml + +# Install some dependencies needed to build LLDB/Clang, currently only needed +# during the `dist` target +- bash: | + set -e + brew update + brew install xz + brew install swig + displayName: Install build dependencies (OSX) + condition: and(eq(variables['Agent.OS'], 'Darwin'), eq(variables['RUST_CHECK_TARGET'],'dist')) + +- template: install-windows-build-deps.yml + +# Check out all our submodules, but more quickly than using git by using one of +# our custom scripts +- bash: | + set -e + mkdir -p $HOME/rustsrc + $BUILD_SOURCESDIRECTORY/src/ci/init_repo.sh . $HOME/rustsrc + condition: ne(variables['Agent.OS'], 'Windows_NT') + displayName: Check out submodules (Unix) +- script: | + if not exist D:\cache\rustsrc\NUL mkdir D:\cache\rustsrc + sh src/ci/init_repo.sh . /d/cache/rustsrc + condition: eq(variables['Agent.OS'], 'Windows_NT') + displayName: Check out submodules (Windows) + +# Configure our CI_JOB_NAME variable which log analyzers can use for the main +# step to see what's going on. +- bash: echo "##vso[task.setvariable variable=CI_JOB_NAME]$SYSTEM_JOBNAME" + condition: eq(variables['Agent.OS'], 'Windows_NT') + displayName: Configure Job Name (Windows) + +# As a quick smoke check on the otherwise very fast mingw-check linux builder +# check our own internal scripts. +- bash: | + set -e + git clone --depth=1 https://github.com/rust-lang-nursery/rust-toolstate.git + cd rust-toolstate + python2.7 "$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" "$(git log --format=%s -n1 HEAD)" "" "" + cd .. + rm -rf rust-toolstate + condition: and(succeeded(), eq(variables['IMAGE'], 'mingw-check')) + displayName: Verify the publish_toolstate script works + +- script: sh src/ci/run.sh + timeoutInMinutes: 180 + env: + CI: true + SRC: . + AWS_SECRET_ACCESS_KEY: $(SCCACHE_AWS_SECRET_ACCESS_KEY) + displayName: Run build + +- bash: | + set -e + deploy_dir=rustc-builds + if [ "$DEPLOY_ALT" == "1" ]; then + deploy_dir=rustc-builds-alt + fi + aws s3 cp --no-progress --recursive --acl public-read ./deploy s3://$DEPLOY_BUCKET/$deploy_dir + env: + AWS_SECRET_ACCESS_KEY: $(SCCACHE_AWS_SECRET_ACCESS_KEY) + condition: and(succeeded(), or(eq(variables.DEPLOY, '1'), eq(variables.DEPLOY_ALT, '1'))) + displayName: Upload artifacts diff --git a/.azure-pipelines/steps/show-disk-usage.yml b/.azure-pipelines/steps/show-disk-usage.yml deleted file mode 100644 index 902d80364717..000000000000 --- a/.azure-pipelines/steps/show-disk-usage.yml +++ /dev/null @@ -1,5 +0,0 @@ -steps: -- bash: | - df -h - du . | sort -nr | head -n100 - displayName: Show disk usage diff --git a/.azure-pipelines/steps/show-environment-variables.yml b/.azure-pipelines/steps/show-environment-variables.yml deleted file mode 100644 index f6ed063ec6be..000000000000 --- a/.azure-pipelines/steps/show-environment-variables.yml +++ /dev/null @@ -1,3 +0,0 @@ -steps: -- bash: printenv | sort - displayName: Show environment variables \ No newline at end of file diff --git a/.azure-pipelines/steps/verify-publish-toolstate.yml b/.azure-pipelines/steps/verify-publish-toolstate.yml index 5531c90e090a..e69de29bb2d1 100644 --- a/.azure-pipelines/steps/verify-publish-toolstate.yml +++ b/.azure-pipelines/steps/verify-publish-toolstate.yml @@ -1,9 +0,0 @@ -steps: -- bash: | - git clone --depth=1 https://github.com/rust-lang-nursery/rust-toolstate.git - cd rust-toolstate - python2.7 "$BUILD_SOURCESDIRECTORY/src/tools/publish_toolstate.py" "$(git rev-parse HEAD)" "$(git log --format=%s -n1 HEAD)" "" "" - cd .. - rm -rf rust-toolstate - condition: and(succeeded(), eq(variables['IMAGE'], 'mingw-check')) - displayName: Verify the publish_toolstate script works diff --git a/.azure-pipelines/try.yml b/.azure-pipelines/try.yml index bdd36e8555d7..e04804d2deed 100644 --- a/.azure-pipelines/try.yml +++ b/.azure-pipelines/try.yml @@ -11,7 +11,6 @@ variables: jobs: - job: Linux - timeoutInMinutes: 180 pool: vmImage: ubuntu-16.04 strategy: @@ -27,4 +26,4 @@ jobs: IMAGE: dist-x86_64-linux DEPLOY_ALT: 1 steps: - - template: steps/linux.yml + - template: steps/run.yml From 4183f3c41b5a6b7d046b66a270f8d9a8ffd671c8 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 20 May 2019 12:29:30 -0700 Subject: [PATCH 0191/3207] Configure a few more builders on `try` temporarily Make sure there's one dist and one test builder for each of the three main platforms --- .azure-pipelines/try.yml | 58 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/.azure-pipelines/try.yml b/.azure-pipelines/try.yml index e04804d2deed..47470a2aa348 100644 --- a/.azure-pipelines/try.yml +++ b/.azure-pipelines/try.yml @@ -18,12 +18,62 @@ jobs: dist-x86_64-linux: IMAGE: dist-x86_64-linux DEPLOY: 1 - - # "alternate" deployments, these are "nightlies" but have LLVM assertions - # turned on, they're deployed to a different location primarily for - # additional testing. dist-x86_64-linux-alt: IMAGE: dist-x86_64-linux DEPLOY_ALT: 1 + test-various: + IMAGE: test-various + steps: + - template: steps/run.yml + +- job: macOS + pool: + vmImage: macos-10.13 + strategy: + matrix: + x86_64-apple: + RUST_CHECK_TARGET: check + RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + + dist-x86_64-apple: + RUST_CHECK_TARGET: dist + RUST_CONFIGURE_ARGS: --target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --enable-lldb --set rust.jemalloc + DEPLOY: 1 + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + DIST_REQUIRE_ALL_TOOLS: 1 + steps: + - template: steps/run.yml + +- job: Windows + pool: + vmImage: 'vs2017-win2016' + strategy: + matrix: + x86_64-msvc-1: + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + SCRIPT: make ci-subset-1 + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + x86_64-msvc-2: + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + SCRIPT: make ci-subset-2 + + dist-x86_64-msvc: + RUST_CONFIGURE_ARGS: > + --build=x86_64-pc-windows-msvc + --target=x86_64-pc-windows-msvc,aarch64-pc-windows-msvc + --enable-full-tools + --enable-profiler + SCRIPT: python x.py dist + DIST_REQUIRE_ALL_TOOLS: 1 + DEPLOY: 1 steps: - template: steps/run.yml From d8f764bbbf10cdccfde48f0a6b7dfdea157b5568 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Mon, 20 May 2019 12:27:15 -0700 Subject: [PATCH 0192/3207] Set -funwind-tables and -fno-exceptions unconditionally for LLVM's libunwind These are required otherwise libunwind will end up with undefined references to __gxx_personality_v0 which is provided by C++ ABI library and that's undesirable. --- src/libunwind/build.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs index 70f591e653ba..20280aa3c413 100644 --- a/src/libunwind/build.rs +++ b/src/libunwind/build.rs @@ -67,13 +67,10 @@ mod llvm_libunwind { cfg.flag("-std=c99"); cfg.flag("-std=c++11"); cfg.flag("-nostdinc++"); - if cfg.is_flag_supported("-funwind-tables").unwrap_or_default() && - cfg.is_flag_supported("-fno-exceptions").unwrap_or_default() { - cfg.flag("-funwind-tables"); - cfg.flag("-fno-exceptions"); - } + cfg.flag("-fno-exceptions"); cfg.flag("-fno-rtti"); cfg.flag("-fstrict-aliasing"); + cfg.flag("-funwind-tables"); } let mut unwind_sources = vec![ From 91b1655528bf47224ae325ef7b4973afb6cd9cda Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 20 May 2019 12:35:21 -0700 Subject: [PATCH 0193/3207] Remove a now stray file --- .azure-pipelines/steps/verify-publish-toolstate.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .azure-pipelines/steps/verify-publish-toolstate.yml diff --git a/.azure-pipelines/steps/verify-publish-toolstate.yml b/.azure-pipelines/steps/verify-publish-toolstate.yml deleted file mode 100644 index e69de29bb2d1..000000000000 From 528cce96cf1d40f50b9b9768fa763d7702e67da9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 20 May 2019 12:37:18 -0700 Subject: [PATCH 0194/3207] Job name config works for all platforms --- .azure-pipelines/steps/run.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.azure-pipelines/steps/run.yml b/.azure-pipelines/steps/run.yml index 06bb8eb4dc8e..4e7889a1d22c 100644 --- a/.azure-pipelines/steps/run.yml +++ b/.azure-pipelines/steps/run.yml @@ -53,8 +53,7 @@ steps: # Configure our CI_JOB_NAME variable which log analyzers can use for the main # step to see what's going on. - bash: echo "##vso[task.setvariable variable=CI_JOB_NAME]$SYSTEM_JOBNAME" - condition: eq(variables['Agent.OS'], 'Windows_NT') - displayName: Configure Job Name (Windows) + displayName: Configure Job Name # As a quick smoke check on the otherwise very fast mingw-check linux builder # check our own internal scripts. From 7b266ff1812cc1576bcd61906c592c2e7b5642d4 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 20 May 2019 12:38:17 -0700 Subject: [PATCH 0195/3207] Fix a typo in clang install --- .azure-pipelines/steps/install-clang.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure-pipelines/steps/install-clang.yml b/.azure-pipelines/steps/install-clang.yml index 9e3545ea93cb..edb7679d4c58 100644 --- a/.azure-pipelines/steps/install-clang.yml +++ b/.azure-pipelines/steps/install-clang.yml @@ -32,7 +32,7 @@ steps: %TEMP%\LLVM-7.0.0-win64.exe /S /NCRC /D=%CLANG_DIR% set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --set llvm.clang-cl=%CLANG_DIR%\bin\clang-cl.exe echo ##vso[task.setvariable variable=RUST_CONFIGURE_ARGS]%RUST_CONFIGURE_ARGS% - condition: and(eq(variables['Agent.OS'], 'Darwin'), eq(variables['MINGW_URL'],'')) + condition: and(eq(variables['Agent.OS'], 'Windows_NT'), eq(variables['MINGW_URL'],'')) displayName: Install clang (Windows) # Note that we don't install clang on Linux since its compiler story is just so From 804ec5faab1bbe487b42fbd4147d9c8f4c1352b1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 20 May 2019 12:39:25 -0700 Subject: [PATCH 0196/3207] Execute `docker/run.sh` on Linux --- .azure-pipelines/steps/run.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.azure-pipelines/steps/run.yml b/.azure-pipelines/steps/run.yml index 4e7889a1d22c..a0d92cc4d4e8 100644 --- a/.azure-pipelines/steps/run.yml +++ b/.azure-pipelines/steps/run.yml @@ -67,7 +67,13 @@ steps: condition: and(succeeded(), eq(variables['IMAGE'], 'mingw-check')) displayName: Verify the publish_toolstate script works -- script: sh src/ci/run.sh +- bash: | + set -e + if [ "$IMAGE" = ""]; then + src/ci/run.sh + else + src/ci/docker/run.sh $IMAGE + fi timeoutInMinutes: 180 env: CI: true From fa8d3b59bd1b547ea34fee1fe76d66b1dbd86695 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 20 May 2019 12:46:10 -0700 Subject: [PATCH 0197/3207] Fix a typo in the run script --- .azure-pipelines/steps/run.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure-pipelines/steps/run.yml b/.azure-pipelines/steps/run.yml index a0d92cc4d4e8..05ceb66cdbad 100644 --- a/.azure-pipelines/steps/run.yml +++ b/.azure-pipelines/steps/run.yml @@ -69,7 +69,7 @@ steps: - bash: | set -e - if [ "$IMAGE" = ""]; then + if [ "$IMAGE" = "" ]; then src/ci/run.sh else src/ci/docker/run.sh $IMAGE From 0843207d1b8e079aebbb06527abb26bbd083e54d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 20 May 2019 12:55:01 -0700 Subject: [PATCH 0198/3207] Make sure sccache not present doesn't kill the build --- src/ci/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/run.sh b/src/ci/run.sh index a51c2da3cbdc..c996dcb14af3 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -141,4 +141,4 @@ else do_make "$RUST_CHECK_TARGET" fi -sccache --show-stats +sccache --show-stats || true From 751597f0c79a7602db1481b44ebfd5c9a554b591 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 20 May 2019 12:58:53 -0700 Subject: [PATCH 0199/3207] Check out rustfmt submodule through tarballs This takes 30+ seconds to check out on Windows, so let's speed it up through a tarball like we do other big git repositories. --- src/ci/init_repo.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/init_repo.sh b/src/ci/init_repo.sh index 3dfd33815761..b1e4f931c441 100755 --- a/src/ci/init_repo.sh +++ b/src/ci/init_repo.sh @@ -46,7 +46,7 @@ function fetch_github_commit_archive { rm $cached } -included="src/llvm-project src/llvm-emscripten src/doc/book src/doc/rust-by-example" +included="src/llvm-project src/llvm-emscripten src/doc/book src/doc/rust-by-example src/tools/rustfmt" modules="$(git config --file .gitmodules --get-regexp '\.path$' | cut -d' ' -f2)" modules=($modules) use_git="" From a775d11fff5f604c09c5ec06c2a82cb8fbef285f Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Mon, 20 May 2019 15:27:11 -0400 Subject: [PATCH 0200/3207] Fix MSP430 AsmPrinter and assembler syntax mismatch. --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index eb38a1888d1d..2c5656ae5938 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit eb38a1888d1d29b2d2c6b31428a5201cd8fba0ff +Subproject commit 2c5656ae593851d0b2336a727cc14b77a06b8ac0 From 9b8af0608f0817caabbe15ec25c9ebedbb670245 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 20 May 2019 13:16:16 -0700 Subject: [PATCH 0201/3207] Manually install AWS CLI --- .azure-pipelines/steps/run.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.azure-pipelines/steps/run.yml b/.azure-pipelines/steps/run.yml index 05ceb66cdbad..fa1afd2d634f 100644 --- a/.azure-pipelines/steps/run.yml +++ b/.azure-pipelines/steps/run.yml @@ -7,6 +7,17 @@ # Check travis config for `gdb --batch` command to print all crash logs steps: + +# Ensure the `aws` CLI is installed so we can deploy later on, cache docker +# images, etc. +- bash: | + set -e + pip install setuptools + pip install awscli + displayName: Install awscli + +- bash: aws s3 help +- bash: exit 1 - checkout: self fetchDepth: 2 From 12f370156ddcdff567e7b0acf83cdf871a997a0a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 20 May 2019 14:21:12 -0700 Subject: [PATCH 0202/3207] Only execute conditional steps on success Make sure `succeeded()` is in all the conditionals --- .azure-pipelines/steps/install-clang.yml | 4 ++-- .azure-pipelines/steps/install-sccache.yml | 4 ++-- .../steps/install-windows-build-deps.yml | 2 +- .azure-pipelines/steps/run.yml | 20 ++++++++++++------- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/.azure-pipelines/steps/install-clang.yml b/.azure-pipelines/steps/install-clang.yml index edb7679d4c58..26a223282cd8 100644 --- a/.azure-pipelines/steps/install-clang.yml +++ b/.azure-pipelines/steps/install-clang.yml @@ -14,7 +14,7 @@ steps: # `clang-ar` by accident. echo "##vso[task.setvariable variable=AR]ar" displayName: Install clang (OSX) - condition: eq(variables['Agent.OS'], 'Darwin') + condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin')) # If we're compiling for MSVC then we, like most other distribution builders, # switch to clang as the compiler. This'll allow us eventually to enable LTO @@ -32,7 +32,7 @@ steps: %TEMP%\LLVM-7.0.0-win64.exe /S /NCRC /D=%CLANG_DIR% set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --set llvm.clang-cl=%CLANG_DIR%\bin\clang-cl.exe echo ##vso[task.setvariable variable=RUST_CONFIGURE_ARGS]%RUST_CONFIGURE_ARGS% - condition: and(eq(variables['Agent.OS'], 'Windows_NT'), eq(variables['MINGW_URL'],'')) + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), eq(variables['MINGW_URL'],'')) displayName: Install clang (Windows) # Note that we don't install clang on Linux since its compiler story is just so diff --git a/.azure-pipelines/steps/install-sccache.yml b/.azure-pipelines/steps/install-sccache.yml index 6933f4e9f279..39f58002a735 100644 --- a/.azure-pipelines/steps/install-sccache.yml +++ b/.azure-pipelines/steps/install-sccache.yml @@ -5,14 +5,14 @@ steps: curl -fo /usr/local/bin/sccache https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-02-sccache-x86_64-apple-darwin chmod +x /usr/local/bin/sccache displayName: Install sccache (OSX) - condition: eq(variables['Agent.OS'], 'Darwin') + condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin')) - script: | md sccache powershell -Command "iwr -outf sccache\sccache.exe https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-26-sccache-x86_64-pc-windows-msvc" echo ##vso[task.prependpath]%CD%\sccache displayName: Install sccache (Windows) - condition: eq(variables['Agent.OS'], 'Windows_NT') + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) # Note that we don't install sccache on Linux since it's installed elsewhere # through all the containers. diff --git a/.azure-pipelines/steps/install-windows-build-deps.yml b/.azure-pipelines/steps/install-windows-build-deps.yml index 4eab460543bb..45ce01fee758 100644 --- a/.azure-pipelines/steps/install-windows-build-deps.yml +++ b/.azure-pipelines/steps/install-windows-build-deps.yml @@ -29,7 +29,7 @@ steps: echo ##vso[task.setvariable variable=MSYS_PATH]%MSYS_PATH% echo ##vso[task.prependpath]%MSYS_PATH%\usr\bin displayName: Install msys2 - condition: eq(variables['Agent.OS'], 'Windows_NT') + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) # If we need to download a custom MinGW, do so here and set the path # appropriately. diff --git a/.azure-pipelines/steps/run.yml b/.azure-pipelines/steps/run.yml index fa1afd2d634f..2d98efd586e7 100644 --- a/.azure-pipelines/steps/run.yml +++ b/.azure-pipelines/steps/run.yml @@ -12,12 +12,18 @@ steps: # images, etc. - bash: | set -e - pip install setuptools - pip install awscli - displayName: Install awscli + sudo apt-get install -y python3-setuptools + pip3 install awscli --upgrade --user + echo "##vso[task.prependpath]$HOME/.local/bin" + displayName: Install awscli (Linux) + condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux')) +- script: pip install awscli + displayName: Install awscli (non-Linux) + condition: and(succeeded(), ne(variables['Agent.OS'], 'Linux')) - bash: aws s3 help - bash: exit 1 + - checkout: self fetchDepth: 2 @@ -30,7 +36,7 @@ steps: du . | sort -nr | head -n100 displayName: Show disk usage # FIXME: this hasn't been tested, but maybe it works on Windows? Should test! - condition: ne(variables['Agent.OS'], 'Windows_NT') + condition: and(succeeded(), ne(variables['Agent.OS'], 'Windows_NT')) - template: install-sccache.yml - template: install-clang.yml @@ -43,7 +49,7 @@ steps: brew install xz brew install swig displayName: Install build dependencies (OSX) - condition: and(eq(variables['Agent.OS'], 'Darwin'), eq(variables['RUST_CHECK_TARGET'],'dist')) + condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin'), eq(variables['RUST_CHECK_TARGET'],'dist')) - template: install-windows-build-deps.yml @@ -53,12 +59,12 @@ steps: set -e mkdir -p $HOME/rustsrc $BUILD_SOURCESDIRECTORY/src/ci/init_repo.sh . $HOME/rustsrc - condition: ne(variables['Agent.OS'], 'Windows_NT') + condition: and(succeeded(), ne(variables['Agent.OS'], 'Windows_NT')) displayName: Check out submodules (Unix) - script: | if not exist D:\cache\rustsrc\NUL mkdir D:\cache\rustsrc sh src/ci/init_repo.sh . /d/cache/rustsrc - condition: eq(variables['Agent.OS'], 'Windows_NT') + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) displayName: Check out submodules (Windows) # Configure our CI_JOB_NAME variable which log analyzers can use for the main From 9843a79496a4943b882d8046abfbff52caf51c3d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 20 May 2019 14:37:24 -0700 Subject: [PATCH 0203/3207] Finalize AWS install --- .azure-pipelines/steps/run.yml | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/.azure-pipelines/steps/run.yml b/.azure-pipelines/steps/run.yml index 2d98efd586e7..dfe54e65e4ec 100644 --- a/.azure-pipelines/steps/run.yml +++ b/.azure-pipelines/steps/run.yml @@ -8,22 +8,6 @@ steps: -# Ensure the `aws` CLI is installed so we can deploy later on, cache docker -# images, etc. -- bash: | - set -e - sudo apt-get install -y python3-setuptools - pip3 install awscli --upgrade --user - echo "##vso[task.prependpath]$HOME/.local/bin" - displayName: Install awscli (Linux) - condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux')) -- script: pip install awscli - displayName: Install awscli (non-Linux) - condition: and(succeeded(), ne(variables['Agent.OS'], 'Linux')) - -- bash: aws s3 help -- bash: exit 1 - - checkout: self fetchDepth: 2 @@ -67,6 +51,19 @@ steps: condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) displayName: Check out submodules (Windows) +# Ensure the `aws` CLI is installed so we can deploy later on, cache docker +# images, etc. +- bash: | + set -e + sudo apt-get install -y python3-setuptools + pip3 install awscli --upgrade --user + echo "##vso[task.prependpath]$HOME/.local/bin" + displayName: Install awscli (Linux) + condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux')) +- script: pip install awscli + displayName: Install awscli (non-Linux) + condition: and(succeeded(), ne(variables['Agent.OS'], 'Linux')) + # Configure our CI_JOB_NAME variable which log analyzers can use for the main # step to see what's going on. - bash: echo "##vso[task.setvariable variable=CI_JOB_NAME]$SYSTEM_JOBNAME" From 56b18ce6370a7e3376fce2d1c404532a887eb5b6 Mon Sep 17 00:00:00 2001 From: MaulingMonkey Date: Mon, 20 May 2019 15:00:36 -0700 Subject: [PATCH 0204/3207] Address CDB review feedback - Don't add path_buf_capacity feature. - Convert `find_cdb` to early return style, reducing indentation - Simplify `compute_stamp_hash` for CDB to just hash it's path, if any. --- src/tools/compiletest/src/main.rs | 54 ++++++++++++++-------------- src/tools/compiletest/src/runtest.rs | 6 +--- 2 files changed, 27 insertions(+), 33 deletions(-) diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 48ecd5a91422..d0dc9d11d396 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -1,6 +1,5 @@ #![crate_name = "compiletest"] #![feature(test)] -#![feature(path_buf_capacity)] #![feature(vec_remove_item)] #![deny(warnings, rust_2018_idioms)] @@ -857,35 +856,34 @@ fn is_pc_windows_msvc_target(target: &String) -> bool { } fn find_cdb(target: &String) -> Option { - if cfg!(windows) && is_pc_windows_msvc_target(target) { - let pf86 = env::var_os("ProgramFiles(x86)").or(env::var_os("ProgramFiles"))?; - let cdb_arch = if cfg!(target_arch="x86") { - "x86" - } else if cfg!(target_arch="x86_64") { - "x64" - } else if cfg!(target_arch="aarch64") { - "arm64" - } else if cfg!(target_arch="arm") { - "arm" - } else { - return None; // No compatible CDB.exe in the Windows 10 SDK - }; - - let mut path = PathBuf::with_capacity(64); - path.push(pf86); - path.push(r"Windows Kits\10\Debuggers"); // We could check 8.1 etc. too? - path.push(cdb_arch); - path.push(r"cdb.exe"); - - if path.exists() { - Some(path.into_os_string()) - } else { - None - } + if !(cfg!(windows) && is_pc_windows_msvc_target(target)) { + return None; } - else { - None + + let pf86 = env::var_os("ProgramFiles(x86)").or(env::var_os("ProgramFiles"))?; + let cdb_arch = if cfg!(target_arch="x86") { + "x86" + } else if cfg!(target_arch="x86_64") { + "x64" + } else if cfg!(target_arch="aarch64") { + "arm64" + } else if cfg!(target_arch="arm") { + "arm" + } else { + return None; // No compatible CDB.exe in the Windows 10 SDK + }; + + let mut path = PathBuf::new(); + path.push(pf86); + path.push(r"Windows Kits\10\Debuggers"); // We could check 8.1 etc. too? + path.push(cdb_arch); + path.push(r"cdb.exe"); + + if !path.exists() { + return None; } + + Some(path.into_os_string()) } /// Returns Path to CDB diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index c940e2de665a..d87bd66a1ac7 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -244,11 +244,7 @@ pub fn compute_stamp_hash(config: &Config) -> String { config.stage_id.hash(&mut hash); if config.mode == DebugInfoCdb { - match config.cdb { - None => env::var_os("ProgramFiles(x86)").hash(&mut hash), - Some(ref s) if s.is_empty() => env::var_os("ProgramFiles(x86)").hash(&mut hash), - Some(ref s) => s.hash(&mut hash), - } + config.cdb.hash(&mut hash); } if config.mode == DebugInfoGdb || config.mode == DebugInfoGdbLldb { From 419ca9d64001da616ab3c325aca4de8bc7e3be4d Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 20 May 2019 20:13:58 -0300 Subject: [PATCH 0205/3207] LocalDecl push returns Local len --- src/librustc_mir/transform/generator.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index d2da1e6e3ac9..780b3c9686b6 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -212,8 +212,8 @@ impl<'a, 'tcx> TransformVisitor<'a, 'tcx> { // Create a statement which reads the discriminant into a temporary fn get_discr(&self, mir: &mut Mir<'tcx>) -> (Statement<'tcx>, Place<'tcx>) { let temp_decl = LocalDecl::new_internal(self.tcx.types.isize, mir.span); - let temp = Place::Base(PlaceBase::Local(Local::new(mir.local_decls.len()))); - mir.local_decls.push(temp_decl); + let local_decls_len = mir.local_decls.push(temp_decl); + let temp = Place::Base(PlaceBase::Local(local_decls_len)); let self_place = Place::Base(PlaceBase::Local(self_arg())); let assign = Statement { From 4e37785c7d6ef85d00833e93943cdee28baf97b3 Mon Sep 17 00:00:00 2001 From: Brent Kerby Date: Mon, 20 May 2019 21:03:40 -0600 Subject: [PATCH 0206/3207] Create and reference Memory Layout section of boxed docs --- src/liballoc/boxed.rs | 70 ++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 4e712a946b85..024594517d98 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -4,16 +4,6 @@ //! heap allocation in Rust. Boxes provide ownership for this allocation, and //! drop their contents when they go out of scope. //! -//! For non-zero-sized values, a [`Box`] will use the [`Global`] allocator for -//! its allocation. It is valid to convert both ways between a [`Box`] and a -//! raw pointer allocated with the [`Global`] allocator, given that the -//! [`Layout`] used with the allocator is correct for the type. More precisely, -//! a `value: *mut T` that has been allocated with the [`Global`] allocator -//! with `Layout::for_value(&*value)` may be converted into a box using -//! `Box::::from_raw(value)`. Conversely, the memory backing a `value: *mut -//! T` obtained from `Box::::into_raw` may be deallocated using the -//! [`Global`] allocator with `Layout::for_value(&*value)`. -//! //! # Examples //! //! Move a value from the stack to the heap by creating a [`Box`]: @@ -61,6 +51,19 @@ //! for a `Cons`. By introducing a `Box`, which has a defined size, we know how //! big `Cons` needs to be. //! +//! # Memory layout +//! +//! For non-zero-sized values, a [`Box`] will use the [`Global`] allocator for +//! its allocation. It is valid to convert both ways between a [`Box`] and a +//! raw pointer allocated with the [`Global`] allocator, given that the +//! [`Layout`] used with the allocator is correct for the type. More precisely, +//! a `value: *mut T` that has been allocated with the [`Global`] allocator +//! with `Layout::for_value(&*value)` may be converted into a box using +//! `Box::::from_raw(value)`. Conversely, the memory backing a `value: *mut +//! T` obtained from `Box::::into_raw` may be deallocated using the +//! [`Global`] allocator with `Layout::for_value(&*value)`. +//! +//! //! [dereferencing]: ../../std/ops/trait.Deref.html //! [`Box`]: struct.Box.html //! [`Global`]: ../alloc/struct.Global.html @@ -128,11 +131,8 @@ impl Box { /// After calling this function, the raw pointer is owned by the /// resulting `Box`. Specifically, the `Box` destructor will call /// the destructor of `T` and free the allocated memory. For this - /// to be safe, the memory must have been allocated in the precise - /// way that `Box` expects, namely, using the global allocator - /// with the correct [`Layout`] for holding a value of type `T`. In - /// particular, this will be satisfied for a pointer obtained - /// from a previously existing `Box` using [`Box::into_raw`]. + /// to be safe, the memory must have been allocated in accordance + /// with the [memory layout] used by `Box` . /// /// # Safety /// @@ -141,7 +141,8 @@ impl Box { /// function is called twice on the same raw pointer. /// /// # Examples - /// Recreate a `Box` which was previously converted to a raw pointer using [`Box::into_raw`]: + /// Recreate a `Box` which was previously converted to a raw pointer + /// using [`Box::into_raw`]: /// ``` /// let x = Box::new(5); /// let ptr = Box::into_raw(x); @@ -149,16 +150,18 @@ impl Box { /// ``` /// Manually create a `Box` from scratch by using the global allocator: /// ``` - /// use std::alloc::{Layout, alloc}; + /// use std::alloc::{alloc, Layout}; /// - /// let ptr = unsafe{ alloc(Layout::new::()) } as *mut i32; - /// unsafe{ *ptr = 5; } - /// let x = unsafe{ Box::from_raw(ptr) }; + /// unsafe { + /// let ptr = alloc(Layout::new::()) as *mut i32; + /// *ptr = 5; + /// let x = Box::from_raw(ptr); + /// } /// ``` /// + /// [memory layout]: index.html#memory-layout /// [`Layout`]: ../alloc/struct.Layout.html /// [`Box::into_raw`]: struct.Box.html#method.into_raw - /// #[stable(feature = "box_raw", since = "1.4.0")] #[inline] pub unsafe fn from_raw(raw: *mut T) -> Self { @@ -171,9 +174,11 @@ impl Box { /// /// After calling this function, the caller is responsible for the /// memory previously managed by the `Box`. In particular, the - /// caller should properly destroy `T` and release the memory. The - /// easiest way to do so is to convert the raw pointer back into a `Box` - /// with the [`Box::from_raw`] function. + /// caller should properly destroy `T` and release the memory, taking + /// into account the [memory layout] used by `Box`. The easiest way to + /// do this is to convert the raw pointer back into a `Box` with the + /// [`Box::from_raw`] function, allowing the `Box` destructor to perform + /// the cleanup. /// /// Note: this is an associated function, which means that you have /// to call it as `Box::into_raw(b)` instead of `b.into_raw()`. This @@ -185,21 +190,24 @@ impl Box { /// ``` /// let x = Box::new(String::from("Hello")); /// let ptr = Box::into_raw(x); - /// let x = unsafe{ Box::from_raw(ptr) }; + /// let x = unsafe { Box::from_raw(ptr) }; /// ``` - /// Manual cleanup by running the destructor and deallocating the memory: + /// Manual cleanup by explicitly running the destructor and deallocating + /// the memory: /// ``` - /// use std::alloc::{Layout, dealloc}; + /// use std::alloc::{dealloc, Layout}; /// use std::ptr; /// /// let x = Box::new(String::from("Hello")); /// let p = Box::into_raw(x); - /// unsafe{ ptr::drop_in_place(p); } - /// unsafe{ dealloc(p as *mut u8, Layout::new::()); } + /// unsafe { + /// ptr::drop_in_place(p); + /// dealloc(p as *mut u8, Layout::new::()); + /// } /// ``` /// + /// [memory layout]: index.html#memory-layout /// [`Box::from_raw`]: struct.Box.html#method.from_raw - /// #[stable(feature = "box_raw", since = "1.4.0")] #[inline] pub fn into_raw(b: Box) -> *mut T { @@ -233,7 +241,7 @@ impl Box { /// /// // Clean up the memory by converting the NonNull pointer back /// // into a Box and letting the Box be dropped. - /// let x = unsafe{ Box::from_raw(ptr.as_ptr()) }; + /// let x = unsafe { Box::from_raw(ptr.as_ptr()) }; /// } /// ``` #[unstable(feature = "box_into_raw_non_null", issue = "47336")] From e186d3f3e057eef69c60c7d34e474461432ee544 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 21 May 2019 13:18:20 +0900 Subject: [PATCH 0207/3207] Add stream_to_parser_with_base_dir --- src/libsyntax/parse/mod.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 0611c1d9b42a..53d6838939d0 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -329,6 +329,13 @@ pub fn stream_to_parser(sess: &ParseSess, stream: TokenStream) -> Parser<'_> { Parser::new(sess, stream, None, true, false) } +/// Given stream, the `ParseSess` and the base directory, produces a parser. +pub fn stream_to_parser_with_base_dir<'a>(sess: &'a ParseSess, + stream: TokenStream, + base_dir: Directory<'a>) -> Parser<'a> { + Parser::new(sess, stream, Some(base_dir), true, false) +} + /// A sequence separator. pub struct SeqSep { /// The seperator token. From 5ea5fe30726b616a7a561d9b9737b5f4bf629118 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 21 May 2019 08:51:18 +0200 Subject: [PATCH 0208/3207] static_assert: make use of anonymous constants --- src/librustc_data_structures/macros.rs | 6 +++--- src/librustc_mir/transform/qualify_consts.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_data_structures/macros.rs b/src/librustc_data_structures/macros.rs index 7fc23999284a..40899c414722 100644 --- a/src/librustc_data_structures/macros.rs +++ b/src/librustc_data_structures/macros.rs @@ -1,13 +1,13 @@ /// A simple static assertion macro. The first argument should be a unique /// ALL_CAPS identifier that describes the condition. #[macro_export] -#[allow_internal_unstable(type_ascription)] +#[allow_internal_unstable(type_ascription, underscore_const_names)] macro_rules! static_assert { - ($name:ident: $test:expr) => { + ($test:expr) => { // Use the bool to access an array such that if the bool is false, the access // is out-of-bounds. #[allow(dead_code)] - static $name: () = [()][!($test: bool) as usize]; + const _: () = [()][!($test: bool) as usize]; } } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 579f75ba5165..84e2caec68e1 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -544,14 +544,14 @@ impl Qualif for IsNotImplicitlyPromotable { // Ensure the `IDX` values are sequential (`0..QUALIF_COUNT`). macro_rules! static_assert_seq_qualifs { ($i:expr => $first:ident $(, $rest:ident)*) => { - static_assert!(SEQ_QUALIFS: { + static_assert!({ static_assert_seq_qualifs!($i + 1 => $($rest),*); $first::IDX == $i }); }; ($i:expr =>) => { - static_assert!(SEQ_QUALIFS: QUALIF_COUNT == $i); + static_assert!(QUALIF_COUNT == $i); }; } static_assert_seq_qualifs!( From 1daab471ce0d71fd0bf071a4bce0e19dd171f546 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 21 May 2019 10:27:41 +0200 Subject: [PATCH 0209/3207] ci: temp increase of the timeout to 10 hours Let's see how long a full build takes. --- .azure-pipelines/steps/run.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.azure-pipelines/steps/run.yml b/.azure-pipelines/steps/run.yml index dfe54e65e4ec..8882278e3fe0 100644 --- a/.azure-pipelines/steps/run.yml +++ b/.azure-pipelines/steps/run.yml @@ -88,7 +88,8 @@ steps: else src/ci/docker/run.sh $IMAGE fi - timeoutInMinutes: 180 + #timeoutInMinutes: 180 + timeoutInMinutes: 600 env: CI: true SRC: . From 67db2304771d3c7065a68f6a486048b770b8e63e Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 21 May 2019 10:51:37 +0200 Subject: [PATCH 0210/3207] ci: fix tidy --- src/ci/init_repo.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ci/init_repo.sh b/src/ci/init_repo.sh index b1e4f931c441..10215d863be0 100755 --- a/src/ci/init_repo.sh +++ b/src/ci/init_repo.sh @@ -46,7 +46,8 @@ function fetch_github_commit_archive { rm $cached } -included="src/llvm-project src/llvm-emscripten src/doc/book src/doc/rust-by-example src/tools/rustfmt" +included="src/llvm-project src/llvm-emscripten src/doc/book src/doc/rust-by-example" +included="${included} src/tools/rustfmt" modules="$(git config --file .gitmodules --get-regexp '\.path$' | cut -d' ' -f2)" modules=($modules) use_git="" From b557567c35cbb0c84c536e62df8dbfd1694314ef Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 15 May 2019 06:32:44 +1000 Subject: [PATCH 0211/3207] Remove impls for `InternedString`/string equality. `Symbol` received the same treatment in #60630. Also, we can derive `PartialEq` for `InternedString`. --- src/librustc/middle/intrinsicck.rs | 4 +-- src/librustc/traits/on_unimplemented.rs | 10 +++--- src/librustc/ty/mod.rs | 6 ++-- src/librustc/ty/print/pretty.rs | 11 ++++--- src/librustc_codegen_utils/symbol_names.rs | 4 +-- src/librustc_lint/builtin.rs | 2 +- src/librustc_metadata/cstore_impl.rs | 2 +- src/librustc_metadata/decoder.rs | 13 ++++---- src/librustc_mir/shim.rs | 6 ++-- src/librustc_mir/transform/rustc_peek.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- src/libsyntax_pos/symbol.rs | 38 +--------------------- 12 files changed, 34 insertions(+), 66 deletions(-) diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index 5c28d480571e..1f25dba2915c 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -6,7 +6,7 @@ use crate::ty::query::Providers; use rustc_target::spec::abi::Abi::RustIntrinsic; use rustc_data_structures::indexed_vec::Idx; -use syntax_pos::Span; +use syntax_pos::{Span, sym}; use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; use crate::hir; @@ -69,7 +69,7 @@ fn unpack_option_like<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl<'a, 'tcx> ExprVisitor<'a, 'tcx> { fn def_id_is_transmute(&self, def_id: DefId) -> bool { self.tcx.fn_sig(def_id).abi() == RustIntrinsic && - self.tcx.item_name(def_id) == "transmute" + self.tcx.item_name(def_id) == sym::transmute } fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>) { diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index 7ba7429f465a..f9ceeb5bfc01 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -243,15 +243,15 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { // `{Self}` is allowed Position::ArgumentNamed(s) if s == "Self" => (), // `{ThisTraitsName}` is allowed - Position::ArgumentNamed(s) if s == name => (), + Position::ArgumentNamed(s) if s == name.as_str() => (), // `{from_method}` is allowed Position::ArgumentNamed(s) if s == "from_method" => (), // `{from_desugaring}` is allowed Position::ArgumentNamed(s) if s == "from_desugaring" => (), // So is `{A}` if A is a type parameter - Position::ArgumentNamed(s) => match generics.params.iter().find(|param| - param.name == s - ) { + Position::ArgumentNamed(s) => match generics.params.iter().find(|param| { + param.name.as_str() == s + }) { Some(_) => (), None => { span_err!(tcx.sess, span, E0230, @@ -301,7 +301,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { Piece::NextArgument(a) => match a.position { Position::ArgumentNamed(s) => match generic_map.get(s) { Some(val) => val, - None if s == name => { + None if s == name.as_str() => { &trait_str } None => { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index e1c432d5b6da..6629a190c157 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2981,9 +2981,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - pub fn item_name(self, id: DefId) -> InternedString { + pub fn item_name(self, id: DefId) -> Symbol { if id.index == CRATE_DEF_INDEX { - self.original_crate_name(id.krate).as_interned_str() + self.original_crate_name(id.krate) } else { let def_key = self.def_key(id); match def_key.disambiguated_data.data { @@ -2995,7 +2995,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { }), _ => def_key.disambiguated_data.data.get_opt_name().unwrap_or_else(|| { bug!("item_name: no name for {:?}", self.def_path(id)); - }), + }).as_symbol(), } } } diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 91b708d7dbe1..c18852a832fc 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1140,14 +1140,16 @@ impl PrettyPrinter<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> match *region { ty::ReEarlyBound(ref data) => { - data.name != "" && data.name != "'_" + data.name.as_symbol() != keywords::Invalid.name() && + data.name.as_symbol() != keywords::UnderscoreLifetime.name() } ty::ReLateBound(_, br) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { if let ty::BrNamed(_, name) = br { - if name != "" && name != "'_" { + if name.as_symbol() != keywords::Invalid.name() && + name.as_symbol() != keywords::UnderscoreLifetime.name() { return true; } } @@ -1203,7 +1205,7 @@ impl FmtPrinter<'_, '_, '_, F> { // `explain_region()` or `note_and_explain_region()`. match *region { ty::ReEarlyBound(ref data) => { - if data.name != "" { + if data.name.as_symbol() != keywords::Invalid.name() { p!(write("{}", data.name)); return Ok(self); } @@ -1212,7 +1214,8 @@ impl FmtPrinter<'_, '_, '_, F> { ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { if let ty::BrNamed(_, name) = br { - if name != "" && name != "'_" { + if name.as_symbol() != keywords::Invalid.name() && + name.as_symbol() != keywords::UnderscoreLifetime.name() { p!(write("{}", name)); return Ok(self); } diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 6915687ceba9..1a8647ed197b 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -264,7 +264,7 @@ fn compute_symbol_name(tcx: TyCtxt<'_, 'tcx, 'tcx>, instance: Instance<'tcx>) -> return name.as_interned_str(); } // Don't mangle foreign items. - return tcx.item_name(def_id); + return tcx.item_name(def_id).as_interned_str(); } if let Some(name) = &attrs.export_name { @@ -274,7 +274,7 @@ fn compute_symbol_name(tcx: TyCtxt<'_, 'tcx, 'tcx>, instance: Instance<'tcx>) -> if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) { // Don't mangle - return tcx.item_name(def_id); + return tcx.item_name(def_id).as_interned_str(); } // We want to compute the "type" of this item. Unfortunately, some diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index af4f1b88b0fb..d17a92efb066 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -929,7 +929,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { fn def_id_is_transmute(cx: &LateContext<'_, '_>, def_id: DefId) -> bool { cx.tcx.fn_sig(def_id).abi() == RustIntrinsic && - cx.tcx.item_name(def_id) == "transmute" + cx.tcx.item_name(def_id) == sym::transmute } } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 087256a97105..f9b4784bb220 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -432,7 +432,7 @@ impl cstore::CStore { let data = self.get_crate_data(id.krate); if let Some(ref proc_macros) = data.proc_macros { return LoadedMacro::ProcMacro(proc_macros[id.index.to_proc_macro_index()].1.clone()); - } else if data.name == sym::proc_macro && data.item_name(id.index) == "quote" { + } else if data.name == sym::proc_macro && data.item_name(id.index) == sym::quote { use syntax::ext::base::SyntaxExtension; use syntax_ext::proc_macro_impl::BangProcMacro; diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index d882fe6f27ec..d2ba82b5a1c9 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -29,7 +29,7 @@ use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; use syntax::attr; use syntax::ast::{self, Ident}; use syntax::source_map; -use syntax::symbol::{InternedString, sym}; +use syntax::symbol::{Symbol, sym}; use syntax::ext::base::{MacroKind, SyntaxExtension}; use syntax::ext::hygiene::Mark; use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION}; @@ -497,12 +497,13 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn item_name(&self, item_index: DefIndex) -> InternedString { + pub fn item_name(&self, item_index: DefIndex) -> Symbol { self.def_key(item_index) .disambiguated_data .data .get_opt_name() .expect("no name in item_name") + .as_symbol() } pub fn def_kind(&self, index: DefIndex) -> Option { @@ -568,7 +569,7 @@ impl<'a, 'tcx> CrateMetadata { ty::VariantDef::new( tcx, - Ident::from_interned_str(self.item_name(index)), + Ident::with_empty_ctxt(self.item_name(index)), variant_did, ctor_did, data.discr, @@ -576,7 +577,7 @@ impl<'a, 'tcx> CrateMetadata { let f = self.entry(index); ty::FieldDef { did: self.local_def_id(index), - ident: Ident::from_interned_str(self.item_name(index)), + ident: Ident::with_empty_ctxt(self.item_name(index)), vis: f.visibility.decode(self) } }).collect(), @@ -787,7 +788,7 @@ impl<'a, 'tcx> CrateMetadata { if let Some(kind) = self.def_kind(child_index) { callback(def::Export { res: Res::Def(kind, self.local_def_id(child_index)), - ident: Ident::from_interned_str(self.item_name(child_index)), + ident: Ident::with_empty_ctxt(self.item_name(child_index)), vis: self.get_visibility(child_index), span: self.entry(child_index).span.decode((self, sess)), }); @@ -982,7 +983,7 @@ impl<'a, 'tcx> CrateMetadata { self.entry(id) .children .decode(self) - .map(|index| self.item_name(index).as_symbol()) + .map(|index| self.item_name(index)) .collect() } diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 5bd3a1714887..b9224d973fe7 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -10,7 +10,7 @@ use rustc::ty::query::Providers; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc_target::spec::abi::Abi; -use syntax_pos::Span; +use syntax_pos::{Span, sym}; use std::fmt; use std::iter; @@ -100,9 +100,9 @@ fn make_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } ty::InstanceDef::CloneShim(def_id, ty) => { let name = tcx.item_name(def_id); - if name == "clone" { + if name == sym::clone { build_clone_shim(tcx, def_id, ty) - } else if name == "clone_from" { + } else if name == sym::clone_from { debug!("make_shim({:?}: using default trait implementation", instance); return tcx.optimized_mir(def_id); } else { diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 815821f6ff03..7d2dbff996d0 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -223,7 +223,7 @@ fn is_rustc_peek<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if let ty::FnDef(def_id, _) = func.ty.sty { let abi = tcx.fn_sig(def_id).abi(); let name = tcx.item_name(def_id); - if abi == Abi::RustIntrinsic && name == "rustc_peek" { + if abi == Abi::RustIntrinsic && name == sym::rustc_peek { return Some((args, source_info.span)); } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e434623d4a12..6d03a5ad63bb 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1702,7 +1702,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, let stripped_typarams = gens.params.iter().filter_map(|param| match param.kind { ty::GenericParamDefKind::Lifetime => None, ty::GenericParamDefKind::Type { .. } => { - if param.name == keywords::SelfUpper.name().as_str() { + if param.name.as_symbol() == keywords::SelfUpper.name() { assert_eq!(param.index, 0); return None; } diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index aa9028d4a6ba..ed2edaef14e2 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -1146,7 +1146,7 @@ impl Encodable for LocalInternedString { /// assert_ne!(Symbol::gensym("x"), Symbol::gensym("x")) /// assert_eq!(Symbol::gensym("x").as_interned_str(), Symbol::gensym("x").as_interned_str()) /// ``` -#[derive(Clone, Copy, Eq)] +#[derive(Clone, Copy, PartialEq, Eq)] pub struct InternedString { symbol: Symbol, } @@ -1211,42 +1211,6 @@ impl Ord for InternedString { } } -impl> PartialEq for InternedString { - fn eq(&self, other: &T) -> bool { - self.with(|string| string == other.deref()) - } -} - -impl PartialEq for InternedString { - fn eq(&self, other: &InternedString) -> bool { - self.symbol == other.symbol - } -} - -impl PartialEq for str { - fn eq(&self, other: &InternedString) -> bool { - other.with(|string| self == string) - } -} - -impl<'a> PartialEq for &'a str { - fn eq(&self, other: &InternedString) -> bool { - other.with(|string| *self == string) - } -} - -impl PartialEq for String { - fn eq(&self, other: &InternedString) -> bool { - other.with(|string| self == string) - } -} - -impl<'a> PartialEq for &'a String { - fn eq(&self, other: &InternedString) -> bool { - other.with(|string| *self == string) - } -} - impl fmt::Debug for InternedString { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.with(|str| fmt::Debug::fmt(&str, f)) From d2304e1e26aec2ffd4ae3eefcd0745b2b5065233 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 21 May 2019 12:05:57 +0200 Subject: [PATCH 0212/3207] ci: increase timeout, take 2 --- .azure-pipelines/try.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.azure-pipelines/try.yml b/.azure-pipelines/try.yml index 47470a2aa348..8060dc0a2f32 100644 --- a/.azure-pipelines/try.yml +++ b/.azure-pipelines/try.yml @@ -11,6 +11,7 @@ variables: jobs: - job: Linux + timeoutInMinutes: 600 pool: vmImage: ubuntu-16.04 strategy: @@ -27,6 +28,7 @@ jobs: - template: steps/run.yml - job: macOS + timeoutInMinutes: 600 pool: vmImage: macos-10.13 strategy: @@ -53,6 +55,7 @@ jobs: - template: steps/run.yml - job: Windows + timeoutInMinutes: 600 pool: vmImage: 'vs2017-win2016' strategy: From 61735abc063e4622d1c9322d70c263a6a673bf42 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 21 May 2019 13:10:28 +0200 Subject: [PATCH 0213/3207] adjust deprecation date of mem::uninitialized --- src/libcore/mem.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 24bee6355a7c..56869f38a4f6 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -466,7 +466,7 @@ pub unsafe fn zeroed() -> T { /// [`MaybeUninit`]: union.MaybeUninit.html /// [inv]: union.MaybeUninit.html#initialization-invariant #[inline] -#[rustc_deprecated(since = "1.40.0", reason = "use `mem::MaybeUninit` instead")] +#[rustc_deprecated(since = "1.38.0", reason = "use `mem::MaybeUninit` instead")] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn uninitialized() -> T { intrinsics::panic_if_uninhabited::(); From 46e3d04b2baab130be52dc2b3a26085b3582f8ba Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 21 May 2019 13:41:44 +0200 Subject: [PATCH 0214/3207] debuginfo: Revert to old/more verbose behavior for -Cdebuginfo=1. https://github.com/rust-lang/rust/commit/cff075009 made LLVM emit less debuginfo when compiling with "line-tables-only". The change was essentially correct but the reduced amount of debuginfo broke a number of tools. This commit reverts the change so we get back the old behavior, until we figure out how to do this properly and give external tools to adapt to the new format. See https://github.com/rust-lang/rust/issues/60020 for more info. --- .../debuginfo/metadata.rs | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 9bdce37b8bae..13590faa1238 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -31,7 +31,7 @@ use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; use rustc::ty::layout::{self, Align, Integer, IntegerExt, LayoutOf, PrimitiveExt, Size, TyLayout, VariantIdx}; use rustc::ty::subst::UnpackedKind; -use rustc::session::config; +use rustc::session::config::{self, DebugInfo}; use rustc::util::nodemap::FxHashMap; use rustc_fs_util::path_to_c_string; use rustc_data_structures::small_c_str::SmallCStr; @@ -925,7 +925,26 @@ pub fn compile_unit_metadata(tcx: TyCtxt<'_, '_, '_>, let producer = CString::new(producer).unwrap(); let flags = "\0"; let split_name = "\0"; - let kind = DebugEmissionKind::from_generic(tcx.sess.opts.debuginfo); + + // FIXME(#60020): + // + // This should actually be + // + // ``` + // let kind = DebugEmissionKind::from_generic(tcx.sess.opts.debuginfo); + // ``` + // + // that is, we should set LLVM's emission kind to `LineTablesOnly` if + // we are compiling with "limited" debuginfo. However, some of the + // existing tools relied on slightly more debuginfo being generated than + // would be the case with `LineTablesOnly`, and we did not want to break + // these tools in a "drive-by fix", without a good idea or plan about + // what limited debuginfo should exactly look like. So for now we keep + // the emission kind as `FullDebug`. + // + // See https://github.com/rust-lang/rust/issues/60020 for details. + let kind = DebugEmissionKind::FullDebug; + assert!(tcx.sess.opts.debuginfo != DebugInfo::None); unsafe { let file_metadata = llvm::LLVMRustDIBuilderCreateFile( From 8ca388743927547a23e512ecccb66d87ab024043 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 21 May 2019 14:49:53 +0200 Subject: [PATCH 0215/3207] Fix lines highlighting in rustdoc source view --- src/librustdoc/html/static/main.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 72a01a49bc66..82d2c11b2497 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -162,8 +162,15 @@ if (!DOMTokenList.prototype.remove) { var i, from, to, match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/); if (match) { from = parseInt(match[1], 10); - to = Math.min(50000, parseInt(match[2] || match[1], 10)); - from = Math.min(from, to); + to = from; + if (typeof match[2] !== "undefined") { + to = parseInt(match[2], 10); + } + if (to < from) { + var tmp = to; + to = from; + from = tmp; + } elem = document.getElementById(from); if (!elem) { return; @@ -180,7 +187,11 @@ if (!DOMTokenList.prototype.remove) { }); }); for (i = from; i <= to; ++i) { - addClass(document.getElementById(i), "line-highlighted"); + elem = document.getElementById(i); + if (!elem) { + break; + } + addClass(elem, "line-highlighted"); } } else if (ev !== null && search && !hasClass(search, "hidden") && ev.newURL) { addClass(search, "hidden"); From b07dbe1d44038b84e722cbe1efe3201e8fa934d8 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 21 May 2019 22:57:34 +0900 Subject: [PATCH 0216/3207] Add doc comment --- src/libsyntax/parse/mod.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 53d6838939d0..8c1810e3efa0 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -330,6 +330,16 @@ pub fn stream_to_parser(sess: &ParseSess, stream: TokenStream) -> Parser<'_> { } /// Given stream, the `ParseSess` and the base directory, produces a parser. +/// +/// Use this function when you are creating a parser from the token stream +/// and also care about the current working directory of the parser (e.g., +/// you are trying to resolve modules defined inside a macro invocation). +/// +/// # Note +/// +/// The main usage of this function is outside of rustc, for those who uses +/// libsyntax as a library. Please do not remove this function while refactoring +/// just because it is not used in rustc codebase! pub fn stream_to_parser_with_base_dir<'a>(sess: &'a ParseSess, stream: TokenStream, base_dir: Directory<'a>) -> Parser<'a> { From 1f1a9176e7963b43155ce56d2a4cea3bee4a4f7e Mon Sep 17 00:00:00 2001 From: topecongiro Date: Tue, 21 May 2019 23:17:59 +0900 Subject: [PATCH 0217/3207] Fix tidy: remove a trailing whitespace --- src/libsyntax/parse/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 8c1810e3efa0..d0af1afd8fdb 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -334,7 +334,7 @@ pub fn stream_to_parser(sess: &ParseSess, stream: TokenStream) -> Parser<'_> { /// Use this function when you are creating a parser from the token stream /// and also care about the current working directory of the parser (e.g., /// you are trying to resolve modules defined inside a macro invocation). -/// +/// /// # Note /// /// The main usage of this function is outside of rustc, for those who uses From a2168b0259f67ca478255239cdde9b76603b08c8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 21 May 2019 17:14:09 +0200 Subject: [PATCH 0218/3207] update doc comment --- src/librustc_data_structures/macros.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustc_data_structures/macros.rs b/src/librustc_data_structures/macros.rs index 40899c414722..b851263aaf9c 100644 --- a/src/librustc_data_structures/macros.rs +++ b/src/librustc_data_structures/macros.rs @@ -1,5 +1,4 @@ -/// A simple static assertion macro. The first argument should be a unique -/// ALL_CAPS identifier that describes the condition. +/// A simple static assertion macro. #[macro_export] #[allow_internal_unstable(type_ascription, underscore_const_names)] macro_rules! static_assert { From a1f2dceaebd21a6f8a5f9341bf41724bb20e2a7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 6 Apr 2019 00:15:49 +0200 Subject: [PATCH 0219/3207] Move `edition` outside the hygiene lock and avoid accessing it --- src/librustc/session/config.rs | 12 +++---- src/librustc_allocator/expand.rs | 4 +-- src/librustc_interface/interface.rs | 4 ++- src/librustc_interface/passes.rs | 6 ++-- src/librustc_interface/util.rs | 7 ++-- src/librustc_metadata/encoder.rs | 4 +-- src/librustc_plugin/registry.rs | 3 +- src/librustc_resolve/macros.rs | 4 +-- src/librustdoc/clean/cfg.rs | 16 ++++----- src/librustdoc/test.rs | 5 ++- src/libsyntax/ext/base.rs | 8 +++-- src/libsyntax/ext/derive.rs | 4 +-- src/libsyntax/ext/expand.rs | 8 ++--- src/libsyntax/lib.rs | 15 +++++--- src/libsyntax/mut_visit.rs | 6 ++-- src/libsyntax/parse/lexer/mod.rs | 31 +++++++++-------- src/libsyntax/parse/mod.rs | 27 ++++++++------- src/libsyntax/print/pprust.rs | 6 ++-- src/libsyntax/source_map.rs | 2 +- src/libsyntax/std_inject.rs | 8 ++--- src/libsyntax/test.rs | 2 +- src/libsyntax/test_snippet.rs | 4 +-- src/libsyntax/tokenstream.rs | 34 ++++++++++--------- src/libsyntax/util/lev_distance.rs | 4 +-- src/libsyntax_ext/lib.rs | 12 +++---- src/libsyntax_ext/proc_macro_decls.rs | 4 +-- src/libsyntax_ext/test.rs | 4 +-- src/libsyntax_ext/test_case.rs | 4 +-- src/libsyntax_pos/edition.rs | 5 +++ src/libsyntax_pos/hygiene.rs | 12 +------ src/libsyntax_pos/lib.rs | 10 ++++-- src/libsyntax_pos/symbol.rs | 3 +- .../run-pass-fulldeps/ast_stmt_expr_attr.rs | 2 +- .../auxiliary/plugin-args.rs | 2 +- .../mod_dir_path_canonicalized.rs | 2 +- .../pprust-expr-roundtrip.rs | 2 +- .../rustdoc-ui/failed-doctest-output.stdout | 4 +-- .../rustdoc-ui/unparseable-doc-test.stdout | 2 +- src/tools/error_index_generator/main.rs | 2 +- 39 files changed, 155 insertions(+), 139 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index b5e3c4cda0a6..f16137bd2c27 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1853,7 +1853,7 @@ pub fn rustc_optgroups() -> Vec { // Convert strings provided as --cfg [cfgspec] into a crate_cfg pub fn parse_cfgspecs(cfgspecs: Vec) -> FxHashSet<(String, Option)> { - syntax::with_globals(move || { + syntax::with_default_globals(move || { let cfg = cfgspecs.into_iter().map(|s| { let sess = parse::ParseSess::new(FilePathMapping::empty()); let filename = FileName::cfg_spec_source_code(&s); @@ -2735,7 +2735,7 @@ mod tests { // When the user supplies --test we should implicitly supply --cfg test #[test] fn test_switch_implies_cfg_test() { - syntax::with_globals(|| { + syntax::with_default_globals(|| { let matches = &match optgroups().parse(&["--test".to_string()]) { Ok(m) => m, Err(f) => panic!("test_switch_implies_cfg_test: {}", f), @@ -2753,7 +2753,7 @@ mod tests { #[test] fn test_switch_implies_cfg_test_unless_cfg_test() { use syntax::symbol::sym; - syntax::with_globals(|| { + syntax::with_default_globals(|| { let matches = &match optgroups().parse(&["--test".to_string(), "--cfg=test".to_string()]) { Ok(m) => m, @@ -2771,7 +2771,7 @@ mod tests { #[test] fn test_can_print_warnings() { - syntax::with_globals(|| { + syntax::with_default_globals(|| { let matches = optgroups().parse(&["-Awarnings".to_string()]).unwrap(); let registry = errors::registry::Registry::new(&[]); let (sessopts, _) = build_session_options_and_crate_config(&matches); @@ -2779,7 +2779,7 @@ mod tests { assert!(!sess.diagnostic().flags.can_emit_warnings); }); - syntax::with_globals(|| { + syntax::with_default_globals(|| { let matches = optgroups() .parse(&["-Awarnings".to_string(), "-Dwarnings".to_string()]) .unwrap(); @@ -2789,7 +2789,7 @@ mod tests { assert!(sess.diagnostic().flags.can_emit_warnings); }); - syntax::with_globals(|| { + syntax::with_default_globals(|| { let matches = optgroups().parse(&["-Adead_code".to_string()]).unwrap(); let registry = errors::registry::Registry::new(&[]); let (sessopts, _) = build_session_options_and_crate_config(&matches); diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs index 6931b3542f76..0c19d770194b 100644 --- a/src/librustc_allocator/expand.rs +++ b/src/librustc_allocator/expand.rs @@ -14,7 +14,7 @@ use syntax::{ base::{ExtCtxt, Resolver}, build::AstBuilder, expand::ExpansionConfig, - hygiene::{self, Mark, SyntaxContext}, + hygiene::{Mark, SyntaxContext}, }, mut_visit::{self, MutVisitor}, parse::ParseSess, @@ -96,7 +96,7 @@ impl MutVisitor for ExpandAllocatorDirectives<'_> { ].into()), allow_internal_unsafe: false, local_inner_macros: false, - edition: hygiene::default_edition(), + edition: self.sess.edition, }); // Tie the span to the macro expansion info we just created diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs index f2a21d61aed4..d598a48649ee 100644 --- a/src/librustc_interface/interface.rs +++ b/src/librustc_interface/interface.rs @@ -18,6 +18,7 @@ use std::result; use std::sync::{Arc, Mutex}; use syntax; use syntax::source_map::{FileLoader, SourceMap}; +use syntax_pos::edition; pub type Result = result::Result; @@ -135,6 +136,7 @@ where { let stderr = config.stderr.take(); util::spawn_thread_pool( + config.opts.edition, config.opts.debugging_opts.threads, &stderr, || run_compiler_in_existing_thread_pool(config, f), @@ -146,5 +148,5 @@ where F: FnOnce() -> R + Send, R: Send, { - util::spawn_thread_pool(None, &None, f) + util::spawn_thread_pool(edition::DEFAULT_EDITION, None, &None, f) } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index c5ac8860ccd9..04041f883442 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -48,7 +48,7 @@ use syntax::util::node_count::NodeCounter; use syntax::util::lev_distance::find_best_match_for_name; use syntax::symbol::Symbol; use syntax::feature_gate::AttributeType; -use syntax_pos::{FileName, hygiene}; +use syntax_pos::{FileName, edition::Edition, hygiene}; use syntax_ext; use serialize::json; @@ -70,8 +70,6 @@ use std::ops::Generator; pub fn parse<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::Crate> { sess.diagnostic() .set_continue_after_error(sess.opts.debugging_opts.continue_parse_after_error); - hygiene::set_default_edition(sess.edition()); - sess.profiler(|p| p.start_activity("parsing")); let krate = time(sess, "parsing", || match *input { Input::File(ref file) => parse::parse_crate_from_file(file, &sess.parse_sess), @@ -375,7 +373,7 @@ fn configure_and_expand_inner<'a>( crate_loader, &resolver_arenas, ); - syntax_ext::register_builtins(&mut resolver, plugin_info.syntax_exts); + syntax_ext::register_builtins(&mut resolver, plugin_info.syntax_exts, sess.edition()); // Expand all macros sess.profiler(|p| p.start_activity("macro expansion")); diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index d2d0d1918078..09bb547191f4 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -37,6 +37,7 @@ use syntax::util::lev_distance::find_best_match_for_name; use syntax::source_map::{FileLoader, RealFileLoader, SourceMap}; use syntax::symbol::{Symbol, sym}; use syntax::{self, ast, attr}; +use syntax_pos::edition::Edition; #[cfg(not(parallel_compiler))] use std::{thread, panic}; @@ -167,6 +168,7 @@ pub fn scoped_thread R + Send, R: Send>(cfg: thread::Builder, f: #[cfg(not(parallel_compiler))] pub fn spawn_thread_pool R + Send, R: Send>( + edition: Edition, _threads: Option, stderr: &Option>>>, f: F, @@ -178,7 +180,7 @@ pub fn spawn_thread_pool R + Send, R: Send>( } scoped_thread(cfg, || { - syntax::with_globals( || { + syntax::with_globals(edition, || { ty::tls::GCX_PTR.set(&Lock::new(0), || { if let Some(stderr) = stderr { io::set_panic(Some(box Sink(stderr.clone()))); @@ -191,6 +193,7 @@ pub fn spawn_thread_pool R + Send, R: Send>( #[cfg(parallel_compiler)] pub fn spawn_thread_pool R + Send, R: Send>( + edition: Edition, threads: Option, stderr: &Option>>>, f: F, @@ -213,7 +216,7 @@ pub fn spawn_thread_pool R + Send, R: Send>( let with_pool = move |pool: &ThreadPool| pool.install(move || f()); - syntax::with_globals(|| { + syntax::with_globals(edition, || { syntax::GLOBALS.with(|syntax_globals| { syntax_pos::GLOBALS.with(|syntax_pos_globals| { // The main handler runs for each Rayon worker thread and sets up diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 939aadcc9ec9..7f0993e799f5 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -34,7 +34,7 @@ use syntax::ast; use syntax::attr; use syntax::source_map::Spanned; use syntax::symbol::{keywords, sym}; -use syntax_pos::{self, hygiene, FileName, SourceFile, Span}; +use syntax_pos::{self, FileName, SourceFile, Span}; use log::{debug, trace}; use rustc::hir::{self, PatKind}; @@ -480,7 +480,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { hash: tcx.crate_hash(LOCAL_CRATE), disambiguator: tcx.sess.local_crate_disambiguator(), panic_strategy: tcx.sess.panic_strategy(), - edition: hygiene::default_edition(), + edition: tcx.sess.edition(), has_global_allocator: has_global_allocator, has_panic_handler: has_panic_handler, has_default_lib_allocator: has_default_lib_allocator, diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs index c2d1d5fa65af..2ed6f868fa1e 100644 --- a/src/librustc_plugin/registry.rs +++ b/src/librustc_plugin/registry.rs @@ -6,7 +6,6 @@ use rustc::util::nodemap::FxHashMap; use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT, IdentTT}; use syntax::ext::base::MacroExpanderFn; -use syntax::ext::hygiene; use syntax::symbol::{Symbol, sym}; use syntax::ast; use syntax::feature_gate::AttributeType; @@ -130,7 +129,7 @@ impl<'a> Registry<'a> { allow_internal_unsafe: false, local_inner_macros: false, unstable_feature: None, - edition: hygiene::default_edition(), + edition: self.sess.edition(), }); } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index e34a33ef8fad..d07f7b65275f 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -17,7 +17,7 @@ use syntax::errors::DiagnosticBuilder; use syntax::ext::base::{self, Determinacy}; use syntax::ext::base::{MacroKind, SyntaxExtension}; use syntax::ext::expand::{AstFragment, Invocation, InvocationKind}; -use syntax::ext::hygiene::{self, Mark}; +use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; use syntax::feature_gate::{ feature_err, is_builtin_attr_name, AttributeGate, GateIssue, Stability, BUILTIN_ATTRIBUTES, @@ -1100,7 +1100,7 @@ impl<'a> Resolver<'a> { let def_id = self.definitions.local_def_id(item.id); let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess, &self.session.features_untracked(), - item, hygiene::default_edition())); + item, self.session.edition())); self.macro_map.insert(def_id, ext); let def = match item.node { ast::ItemKind::MacroDef(ref def) => def, _ => unreachable!() }; diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 61399e0568cb..67113787915a 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -418,7 +418,7 @@ mod test { use syntax::attr; use syntax::source_map::dummy_spanned; use syntax::symbol::Symbol; - use syntax::with_globals; + use syntax::with_default_globals; fn word_cfg(s: &str) -> Cfg { Cfg::Cfg(Symbol::intern(s), None) @@ -466,7 +466,7 @@ mod test { #[test] fn test_cfg_not() { - with_globals(|| { + with_default_globals(|| { assert_eq!(!Cfg::False, Cfg::True); assert_eq!(!Cfg::True, Cfg::False); assert_eq!(!word_cfg("test"), Cfg::Not(Box::new(word_cfg("test")))); @@ -484,7 +484,7 @@ mod test { #[test] fn test_cfg_and() { - with_globals(|| { + with_default_globals(|| { let mut x = Cfg::False; x &= Cfg::True; assert_eq!(x, Cfg::False); @@ -536,7 +536,7 @@ mod test { #[test] fn test_cfg_or() { - with_globals(|| { + with_default_globals(|| { let mut x = Cfg::True; x |= Cfg::False; assert_eq!(x, Cfg::True); @@ -588,7 +588,7 @@ mod test { #[test] fn test_parse_ok() { - with_globals(|| { + with_default_globals(|| { let mi = dummy_meta_item_word("all"); assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all"))); @@ -622,7 +622,7 @@ mod test { #[test] fn test_parse_err() { - with_globals(|| { + with_default_globals(|| { let mi = attr::mk_name_value_item( DUMMY_SP, Ident::from_str("foo"), @@ -661,7 +661,7 @@ mod test { #[test] fn test_render_short_html() { - with_globals(|| { + with_default_globals(|| { assert_eq!( word_cfg("unix").render_short_html(), "Unix" @@ -741,7 +741,7 @@ mod test { #[test] fn test_render_long_html() { - with_globals(|| { + with_default_globals(|| { assert_eq!( word_cfg("unix").render_long_html(), "This is supported on Unix only." diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 0cc99da64079..d76d4380755f 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -8,6 +8,7 @@ use rustc::session::config::{OutputType, OutputTypes, Externs, CodegenOptions}; use rustc::session::search_paths::SearchPath; use rustc::util::common::ErrorReported; use syntax::ast; +use syntax::with_globals; use syntax::source_map::SourceMap; use syntax::edition::Edition; use syntax::feature_gate::UnstableFeatures; @@ -386,13 +387,11 @@ pub fn make_test(s: &str, // Uses libsyntax to parse the doctest and find if there's a main fn and the extern // crate already is included. - let (already_has_main, already_has_extern_crate, found_macro) = crate::syntax::with_globals(|| { + let (already_has_main, already_has_extern_crate, found_macro) = with_globals(edition, || { use crate::syntax::{parse::{self, ParseSess}, source_map::FilePathMapping}; use errors::emitter::EmitterWriter; use errors::Handler; - syntax::ext::hygiene::set_default_edition(edition); - let filename = FileName::anon_source_code(s); let source = crates + &everything_else; diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 0a88d2f8824d..489fac4f1ca4 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -5,7 +5,7 @@ use crate::attr::HasAttrs; use crate::source_map::{SourceMap, Spanned, respan}; use crate::edition::Edition; use crate::ext::expand::{self, AstFragment, Invocation}; -use crate::ext::hygiene::{self, Mark, SyntaxContext, Transparency}; +use crate::ext::hygiene::{Mark, SyntaxContext, Transparency}; use crate::mut_visit::{self, MutVisitor}; use crate::parse::{self, parser, DirectoryOwnership}; use crate::parse::token; @@ -713,7 +713,7 @@ impl SyntaxExtension { } } - pub fn edition(&self) -> Edition { + pub fn edition(&self, default_edition: Edition) -> Edition { match *self { SyntaxExtension::NormalTT { edition, .. } | SyntaxExtension::DeclMacro { edition, .. } | @@ -725,7 +725,7 @@ impl SyntaxExtension { SyntaxExtension::IdentTT { .. } | SyntaxExtension::MultiDecorator(..) | SyntaxExtension::MultiModifier(..) | - SyntaxExtension::BuiltinDerive(..) => hygiene::default_edition(), + SyntaxExtension::BuiltinDerive(..) => default_edition, } } } @@ -734,6 +734,7 @@ pub type NamedSyntaxExtension = (Name, SyntaxExtension); pub trait Resolver { fn next_node_id(&mut self) -> ast::NodeId; + fn get_module_scope(&mut self, id: ast::NodeId) -> Mark; fn resolve_dollar_crates(&mut self, fragment: &AstFragment); @@ -768,6 +769,7 @@ pub struct DummyResolver; impl Resolver for DummyResolver { fn next_node_id(&mut self) -> ast::NodeId { ast::DUMMY_NODE_ID } + fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() } fn resolve_dollar_crates(&mut self, _fragment: &AstFragment) {} diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs index a24e09f127ea..6e789c4c7086 100644 --- a/src/libsyntax/ext/derive.rs +++ b/src/libsyntax/ext/derive.rs @@ -1,6 +1,6 @@ use crate::attr::HasAttrs; use crate::ast; -use crate::source_map::{hygiene, ExpnInfo, ExpnFormat}; +use crate::source_map::{ExpnInfo, ExpnFormat}; use crate::ext::base::ExtCtxt; use crate::ext::build::AstBuilder; use crate::parse::parser::PathStyle; @@ -64,7 +64,7 @@ pub fn add_derived_markers(cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::P ].into()), allow_internal_unsafe: false, local_inner_macros: false, - edition: hygiene::default_edition(), + edition: cx.parse_sess.edition, }); let span = span.with_ctxt(cx.backtrace()); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 019ebc8566ff..478ae4de82b7 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -5,7 +5,7 @@ use crate::source_map::{ExpnInfo, MacroBang, MacroAttribute, dummy_spanned, resp use crate::config::StripUnconfigured; use crate::ext::base::*; use crate::ext::derive::{add_derived_markers, collect_derives}; -use crate::ext::hygiene::{self, Mark, SyntaxContext}; +use crate::ext::hygiene::{Mark, SyntaxContext}; use crate::ext::placeholders::{placeholder, PlaceholderExpander}; use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err}; use crate::mut_visit::*; @@ -560,7 +560,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { allow_internal_unstable: None, allow_internal_unsafe: false, local_inner_macros: false, - edition: ext.edition(), + edition: ext.edition(self.cx.parse_sess.edition), }); match *ext { @@ -805,7 +805,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { allow_internal_unstable: allow_internal_unstable.clone(), allow_internal_unsafe: false, local_inner_macros: false, - edition: hygiene::default_edition(), + edition: self.cx.parse_sess.edition, }); let input: Vec<_> = mac.node.stream().into_trees().collect(); @@ -921,7 +921,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { allow_internal_unstable: None, allow_internal_unsafe: false, local_inner_macros: false, - edition: ext.edition(), + edition: ext.edition(self.cx.parse_sess.edition), }; match *ext { diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index db10ab7af5a7..5eda975bc9ee 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -29,6 +29,7 @@ use rustc_data_structures::sync::Lock; use rustc_data_structures::bit_set::GrowableBitSet; pub use rustc_data_structures::thin_vec::ThinVec; use ast::AttrId; +use syntax_pos::edition::Edition; // A variant of 'try!' that panics on an Err. This is used as a crutch on the // way towards a non-panic!-prone parser. It should be used for fatal parsing @@ -82,26 +83,32 @@ pub struct Globals { } impl Globals { - fn new() -> Globals { + fn new(edition: Edition) -> Globals { Globals { // We have no idea how many attributes their will be, so just // initiate the vectors with 0 bits. We'll grow them as necessary. used_attrs: Lock::new(GrowableBitSet::new_empty()), known_attrs: Lock::new(GrowableBitSet::new_empty()), - syntax_pos_globals: syntax_pos::Globals::new(), + syntax_pos_globals: syntax_pos::Globals::new(edition), } } } -pub fn with_globals(f: F) -> R +pub fn with_globals(edition: Edition, f: F) -> R where F: FnOnce() -> R { - let globals = Globals::new(); + let globals = Globals::new(edition); GLOBALS.set(&globals, || { syntax_pos::GLOBALS.set(&globals.syntax_pos_globals, f) }) } +pub fn with_default_globals(f: F) -> R + where F: FnOnce() -> R +{ + with_globals(edition::DEFAULT_EDITION, f) +} + scoped_tls::scoped_thread_local!(pub static GLOBALS: Globals); #[macro_use] diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index f587e63e12b9..8fdd15a029f1 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -1305,7 +1305,7 @@ mod tests { use crate::util::parser_testing::{string_to_crate, matches_codepattern}; use crate::print::pprust; use crate::mut_visit; - use crate::with_globals; + use crate::with_default_globals; use super::*; // this version doesn't care about getting comments or docstrings in. @@ -1343,7 +1343,7 @@ mod tests { // make sure idents get transformed everywhere #[test] fn ident_transformation () { - with_globals(|| { + with_default_globals(|| { let mut zz_visitor = ToZzIdentMutVisitor; let mut krate = string_to_crate( "#[a] mod b {fn c (d : e, f : g) {h!(i,j,k);l;m}}".to_string()); @@ -1358,7 +1358,7 @@ mod tests { // even inside macro defs.... #[test] fn ident_transformation_in_defs () { - with_globals(|| { + with_default_globals(|| { let mut zz_visitor = ToZzIdentMutVisitor; let mut krate = string_to_crate( "macro_rules! a {(b $c:expr $(d $e:token)f+ => \ diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 47da3ee6a6c7..c97d80407615 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1558,10 +1558,10 @@ mod tests { use crate::feature_gate::UnstableFeatures; use crate::parse::token; use crate::diagnostics::plugin::ErrorMap; - use crate::with_globals; + use crate::with_default_globals; use std::io; use std::path::PathBuf; - use syntax_pos::{BytePos, Span, NO_EXPANSION}; + use syntax_pos::{BytePos, Span, NO_EXPANSION, edition::Edition}; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use rustc_data_structures::sync::Lock; @@ -1581,6 +1581,7 @@ mod tests { raw_identifier_spans: Lock::new(Vec::new()), registered_diagnostics: Lock::new(ErrorMap::new()), buffered_lints: Lock::new(vec![]), + edition: Edition::from_session(), ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), } } @@ -1601,7 +1602,7 @@ mod tests { #[test] fn t1() { - with_globals(|| { + with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); let mut string_reader = setup(&sm, @@ -1649,7 +1650,7 @@ mod tests { #[test] fn doublecolonparsing() { - with_globals(|| { + with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); check_tokenization(setup(&sm, &sh, "a b".to_string()), @@ -1659,7 +1660,7 @@ mod tests { #[test] fn dcparsing_2() { - with_globals(|| { + with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); check_tokenization(setup(&sm, &sh, "a::b".to_string()), @@ -1669,7 +1670,7 @@ mod tests { #[test] fn dcparsing_3() { - with_globals(|| { + with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); check_tokenization(setup(&sm, &sh, "a ::b".to_string()), @@ -1679,7 +1680,7 @@ mod tests { #[test] fn dcparsing_4() { - with_globals(|| { + with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); check_tokenization(setup(&sm, &sh, "a:: b".to_string()), @@ -1689,7 +1690,7 @@ mod tests { #[test] fn character_a() { - with_globals(|| { + with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); assert_eq!(setup(&sm, &sh, "'a'".to_string()).next_token().tok, @@ -1699,7 +1700,7 @@ mod tests { #[test] fn character_space() { - with_globals(|| { + with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); assert_eq!(setup(&sm, &sh, "' '".to_string()).next_token().tok, @@ -1709,7 +1710,7 @@ mod tests { #[test] fn character_escaped() { - with_globals(|| { + with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); assert_eq!(setup(&sm, &sh, "'\\n'".to_string()).next_token().tok, @@ -1719,7 +1720,7 @@ mod tests { #[test] fn lifetime_name() { - with_globals(|| { + with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); assert_eq!(setup(&sm, &sh, "'abc".to_string()).next_token().tok, @@ -1729,7 +1730,7 @@ mod tests { #[test] fn raw_string() { - with_globals(|| { + with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); assert_eq!(setup(&sm, &sh, "r###\"\"#a\\b\x00c\"\"###".to_string()) @@ -1741,7 +1742,7 @@ mod tests { #[test] fn literal_suffixes() { - with_globals(|| { + with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); macro_rules! test { @@ -1787,7 +1788,7 @@ mod tests { #[test] fn nested_block_comments() { - with_globals(|| { + with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); let mut lexer = setup(&sm, &sh, "/* /* */ */'a'".to_string()); @@ -1802,7 +1803,7 @@ mod tests { #[test] fn crlf_comments() { - with_globals(|| { + with_default_globals(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let sh = mk_sess(sm.clone()); let mut lexer = setup(&sm, &sh, "// test\r\n/// test\r\n".to_string()); diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 0611c1d9b42a..d574626e6dbc 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -13,6 +13,7 @@ use crate::print::pprust::token_to_string; use errors::{Applicability, FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder}; use rustc_data_structures::sync::{Lrc, Lock}; use syntax_pos::{Span, SourceFile, FileName, MultiSpan}; +use syntax_pos::edition::Edition; use rustc_data_structures::fx::{FxHashSet, FxHashMap}; use std::borrow::Cow; @@ -38,6 +39,7 @@ pub struct ParseSess { pub span_diagnostic: Handler, pub unstable_features: UnstableFeatures, pub config: CrateConfig, + pub edition: Edition, pub missing_fragment_specifiers: Lock>, /// Places where raw identifiers were used. This is used for feature-gating raw identifiers. pub raw_identifier_spans: Lock>, @@ -74,6 +76,7 @@ impl ParseSess { included_mod_stack: Lock::new(vec![]), source_map, buffered_lints: Lock::new(vec![]), + edition: Edition::from_session(), ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), } } @@ -363,7 +366,7 @@ mod tests { use crate::tokenstream::{DelimSpan, TokenTree}; use crate::util::parser_testing::string_to_stream; use crate::util::parser_testing::{string_to_expr, string_to_item}; - use crate::with_globals; + use crate::with_default_globals; use syntax_pos::{Span, BytePos, Pos, NO_EXPANSION}; /// Parses an item. @@ -382,7 +385,7 @@ mod tests { #[should_panic] #[test] fn bad_path_expr_1() { - with_globals(|| { + with_default_globals(|| { string_to_expr("::abc::def::return".to_string()); }) } @@ -390,7 +393,7 @@ mod tests { // check the token-tree-ization of macros #[test] fn string_to_tts_macro () { - with_globals(|| { + with_default_globals(|| { use crate::symbol::sym; let tts: Vec<_> = @@ -447,7 +450,7 @@ mod tests { #[test] fn string_to_tts_1() { - with_globals(|| { + with_default_globals(|| { let tts = string_to_stream("fn a (b : i32) { b; }".to_string()); let expected = TokenStream::new(vec![ @@ -480,7 +483,7 @@ mod tests { } #[test] fn parse_use() { - with_globals(|| { + with_default_globals(|| { let use_s = "use foo::bar::baz;"; let vitem = string_to_item(use_s.to_string()).unwrap(); let vitem_s = item_to_string(&vitem); @@ -494,7 +497,7 @@ mod tests { } #[test] fn parse_extern_crate() { - with_globals(|| { + with_default_globals(|| { let ex_s = "extern crate foo;"; let vitem = string_to_item(ex_s.to_string()).unwrap(); let vitem_s = item_to_string(&vitem); @@ -531,7 +534,7 @@ mod tests { } #[test] fn span_of_self_arg_pat_idents_are_correct() { - with_globals(|| { + with_default_globals(|| { let srcs = ["impl z { fn a (&self, &myarg: i32) {} }", "impl z { fn a (&mut self, &myarg: i32) {} }", @@ -551,7 +554,7 @@ mod tests { } #[test] fn parse_exprs () { - with_globals(|| { + with_default_globals(|| { // just make sure that they parse.... string_to_expr("3 + 4".to_string()); string_to_expr("a::z.froob(b,&(987+3))".to_string()); @@ -559,7 +562,7 @@ mod tests { } #[test] fn attrs_fix_bug () { - with_globals(|| { + with_default_globals(|| { string_to_item("pub fn mk_file_writer(path: &Path, flags: &[FileFlag]) -> Result, String> { #[cfg(windows)] @@ -576,7 +579,7 @@ mod tests { } #[test] fn crlf_doc_comments() { - with_globals(|| { + with_default_globals(|| { use crate::symbol::sym; let sess = ParseSess::new(FilePathMapping::empty()); @@ -613,7 +616,7 @@ mod tests { new_parser_from_source_str(sess, name, source).parse_expr() } - with_globals(|| { + with_default_globals(|| { let sess = ParseSess::new(FilePathMapping::empty()); let expr = parse_expr_from_source_str(PathBuf::from("foo").into(), "foo!( fn main() { body } )".to_string(), &sess).unwrap(); @@ -637,7 +640,7 @@ mod tests { // See `recurse_into_file_modules` in the parser. #[test] fn out_of_line_mod() { - with_globals(|| { + with_default_globals(|| { let sess = ParseSess::new(FilePathMapping::empty()); let item = parse_item_from_source_str( PathBuf::from("foo").into(), diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index cd86d94f4b81..ac240359b56b 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -3147,12 +3147,12 @@ mod tests { use crate::ast; use crate::source_map; - use crate::with_globals; + use crate::with_default_globals; use syntax_pos; #[test] fn test_fun_to_string() { - with_globals(|| { + with_default_globals(|| { let abba_ident = ast::Ident::from_str("abba"); let decl = ast::FnDecl { @@ -3180,7 +3180,7 @@ mod tests { #[test] fn test_variant_to_string() { - with_globals(|| { + with_default_globals(|| { let ident = ast::Ident::from_str("principal_skinner"); let var = source_map::respan(syntax_pos::DUMMY_SP, ast::Variant_ { diff --git a/src/libsyntax/source_map.rs b/src/libsyntax/source_map.rs index 215618bd09ca..8a210db91858 100644 --- a/src/libsyntax/source_map.rs +++ b/src/libsyntax/source_map.rs @@ -947,7 +947,7 @@ impl SourceMap { allow_internal_unstable, allow_internal_unsafe: false, local_inner_macros: false, - edition: hygiene::default_edition(), + edition: edition::Edition::from_session(), }); span.with_ctxt(SyntaxContext::empty().apply_mark(mark)) } diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 1be7986ad53c..e01a3260d499 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -3,7 +3,7 @@ use crate::attr; use crate::edition::Edition; use crate::ext::hygiene::{Mark, SyntaxContext}; use crate::symbol::{Ident, Symbol, keywords, sym}; -use crate::source_map::{ExpnInfo, MacroAttribute, dummy_spanned, hygiene, respan}; +use crate::source_map::{ExpnInfo, MacroAttribute, dummy_spanned, respan}; use crate::ptr::P; use crate::tokenstream::TokenStream; @@ -14,7 +14,7 @@ use syntax_pos::{DUMMY_SP, Span}; /// Craft a span that will be ignored by the stability lint's /// call to source_map's `is_internal` check. /// The expanded code uses the unstable `#[prelude_import]` attribute. -fn ignored_span(sp: Span) -> Span { +fn ignored_span(sp: Span, edition: Edition) -> Span { let mark = Mark::fresh(Mark::root()); mark.set_expn_info(ExpnInfo { call_site: DUMMY_SP, @@ -25,7 +25,7 @@ fn ignored_span(sp: Span) -> Span { ].into()), allow_internal_unsafe: false, local_inner_macros: false, - edition: hygiene::default_edition(), + edition, }); sp.with_ctxt(SyntaxContext::empty().apply_mark(mark)) } @@ -94,7 +94,7 @@ pub fn maybe_inject_crates_ref( INJECTED_CRATE_NAME.with(|opt_name| opt_name.set(Some(name))); - let span = ignored_span(DUMMY_SP); + let span = ignored_span(DUMMY_SP, edition); krate.module.items.insert(0, P(ast::Item { attrs: vec![ast::Attribute { style: ast::AttrStyle::Outer, diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 3dc7aad94593..7cd83f3e495b 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -291,7 +291,7 @@ fn generate_test_harness(sess: &ParseSess, ].into()), allow_internal_unsafe: false, local_inner_macros: false, - edition: hygiene::default_edition(), + edition: sess.edition, }); TestHarnessGenerator { diff --git a/src/libsyntax/test_snippet.rs b/src/libsyntax/test_snippet.rs index 3cf6699538de..107cbe70a23d 100644 --- a/src/libsyntax/test_snippet.rs +++ b/src/libsyntax/test_snippet.rs @@ -1,5 +1,5 @@ use crate::source_map::{SourceMap, FilePathMapping}; -use crate::with_globals; +use crate::with_default_globals; use errors::Handler; use errors::emitter::EmitterWriter; @@ -39,7 +39,7 @@ impl Write for Shared { } fn test_harness(file_text: &str, span_labels: Vec, expected_output: &str) { - with_globals(|| { + with_default_globals(|| { let output = Arc::new(Mutex::new(Vec::new())); let source_map = Lrc::new(SourceMap::new(FilePathMapping::empty())); diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 3cb16c30a50d..79efc6bf689c 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -557,7 +557,7 @@ impl DelimSpan { mod tests { use super::*; use crate::syntax::ast::Ident; - use crate::with_globals; + use crate::with_default_globals; use crate::parse::token::Token; use crate::util::parser_testing::string_to_stream; use syntax_pos::{Span, BytePos, NO_EXPANSION}; @@ -572,7 +572,7 @@ mod tests { #[test] fn test_concat() { - with_globals(|| { + with_default_globals(|| { let test_res = string_to_ts("foo::bar::baz"); let test_fst = string_to_ts("foo::bar"); let test_snd = string_to_ts("::baz"); @@ -585,7 +585,7 @@ mod tests { #[test] fn test_to_from_bijection() { - with_globals(|| { + with_default_globals(|| { let test_start = string_to_ts("foo::bar(baz)"); let test_end = test_start.trees().collect(); assert_eq!(test_start, test_end) @@ -594,7 +594,7 @@ mod tests { #[test] fn test_eq_0() { - with_globals(|| { + with_default_globals(|| { let test_res = string_to_ts("foo"); let test_eqs = string_to_ts("foo"); assert_eq!(test_res, test_eqs) @@ -603,7 +603,7 @@ mod tests { #[test] fn test_eq_1() { - with_globals(|| { + with_default_globals(|| { let test_res = string_to_ts("::bar::baz"); let test_eqs = string_to_ts("::bar::baz"); assert_eq!(test_res, test_eqs) @@ -612,7 +612,7 @@ mod tests { #[test] fn test_eq_3() { - with_globals(|| { + with_default_globals(|| { let test_res = string_to_ts(""); let test_eqs = string_to_ts(""); assert_eq!(test_res, test_eqs) @@ -621,7 +621,7 @@ mod tests { #[test] fn test_diseq_0() { - with_globals(|| { + with_default_globals(|| { let test_res = string_to_ts("::bar::baz"); let test_eqs = string_to_ts("bar::baz"); assert_eq!(test_res == test_eqs, false) @@ -630,7 +630,7 @@ mod tests { #[test] fn test_diseq_1() { - with_globals(|| { + with_default_globals(|| { let test_res = string_to_ts("(bar,baz)"); let test_eqs = string_to_ts("bar,baz"); assert_eq!(test_res == test_eqs, false) @@ -639,7 +639,7 @@ mod tests { #[test] fn test_is_empty() { - with_globals(|| { + with_default_globals(|| { let test0: TokenStream = Vec::::new().into_iter().collect(); let test1: TokenStream = TokenTree::Token(sp(0, 1), Token::Ident(Ident::from_str("a"), false)).into(); @@ -653,12 +653,14 @@ mod tests { #[test] fn test_dotdotdot() { - let mut builder = TokenStreamBuilder::new(); - builder.push(TokenTree::Token(sp(0, 1), Token::Dot).joint()); - builder.push(TokenTree::Token(sp(1, 2), Token::Dot).joint()); - builder.push(TokenTree::Token(sp(2, 3), Token::Dot)); - let stream = builder.build(); - assert!(stream.eq_unspanned(&string_to_ts("..."))); - assert_eq!(stream.trees().count(), 1); + with_default_globals(|| { + let mut builder = TokenStreamBuilder::new(); + builder.push(TokenTree::Token(sp(0, 1), Token::Dot).joint()); + builder.push(TokenTree::Token(sp(1, 2), Token::Dot).joint()); + builder.push(TokenTree::Token(sp(2, 3), Token::Dot)); + let stream = builder.build(); + assert!(stream.eq_unspanned(&string_to_ts("..."))); + assert_eq!(stream.trees().count(), 1); + }) } } diff --git a/src/libsyntax/util/lev_distance.rs b/src/libsyntax/util/lev_distance.rs index 2f150d22159f..885b5a4f333b 100644 --- a/src/libsyntax/util/lev_distance.rs +++ b/src/libsyntax/util/lev_distance.rs @@ -101,8 +101,8 @@ fn test_lev_distance() { #[test] fn test_find_best_match_for_name() { - use crate::with_globals; - with_globals(|| { + use crate::with_default_globals; + with_default_globals(|| { let input = vec![Symbol::intern("aaab"), Symbol::intern("aaabc")]; assert_eq!( find_best_match_for_name(input.iter(), "aaaa", None), diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 508f740cac92..e5fc7aab61db 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -42,17 +42,17 @@ pub mod proc_macro_impl; use rustc_data_structures::sync::Lrc; use syntax::ast; use syntax::ext::base::{MacroExpanderFn, NormalTT, NamedSyntaxExtension, MultiModifier}; -use syntax::ext::hygiene; use syntax::symbol::Symbol; +use syntax::edition::Edition; pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver, - user_exts: Vec) { + user_exts: Vec, + edition: Edition) { deriving::register_builtin_derives(resolver); let mut register = |name, ext| { resolver.add_builtin(ast::Ident::with_empty_ctxt(name), Lrc::new(ext)); }; - macro_rules! register { ($( $name:ident: $f:expr, )*) => { $( register(Symbol::intern(stringify!($name)), @@ -63,7 +63,7 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver, allow_internal_unsafe: false, local_inner_macros: false, unstable_feature: None, - edition: hygiene::default_edition(), + edition, }); )* } } @@ -108,7 +108,7 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver, allow_internal_unsafe: false, local_inner_macros: false, unstable_feature: None, - edition: hygiene::default_edition(), + edition, }); register(Symbol::intern("format_args_nl"), NormalTT { @@ -120,7 +120,7 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver, allow_internal_unsafe: false, local_inner_macros: false, unstable_feature: None, - edition: hygiene::default_edition(), + edition, }); for (name, ext) in user_exts { diff --git a/src/libsyntax_ext/proc_macro_decls.rs b/src/libsyntax_ext/proc_macro_decls.rs index 200445d12488..a13fe65ca0dd 100644 --- a/src/libsyntax_ext/proc_macro_decls.rs +++ b/src/libsyntax_ext/proc_macro_decls.rs @@ -4,7 +4,7 @@ use crate::deriving; use syntax::ast::{self, Ident}; use syntax::attr; -use syntax::source_map::{ExpnInfo, MacroAttribute, hygiene, respan}; +use syntax::source_map::{ExpnInfo, MacroAttribute, respan}; use syntax::ext::base::ExtCtxt; use syntax::ext::build::AstBuilder; use syntax::ext::expand::ExpansionConfig; @@ -358,7 +358,7 @@ fn mk_decls( ].into()), allow_internal_unsafe: false, local_inner_macros: false, - edition: hygiene::default_edition(), + edition: cx.parse_sess.edition, }); let span = DUMMY_SP.apply_mark(mark); diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index 211a098022f9..8ee61a3f67f5 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -3,7 +3,7 @@ use syntax::ext::base::*; use syntax::ext::build::AstBuilder; -use syntax::ext::hygiene::{self, Mark, SyntaxContext}; +use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::attr; use syntax::ast; use syntax::print::pprust; @@ -72,7 +72,7 @@ pub fn expand_test_or_bench( ].into()), allow_internal_unsafe: false, local_inner_macros: false, - edition: hygiene::default_edition(), + edition: cx.parse_sess.edition, }); (item.span.with_ctxt(SyntaxContext::empty().apply_mark(mark)), attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(mark))) diff --git a/src/libsyntax_ext/test_case.rs b/src/libsyntax_ext/test_case.rs index 802037f6d22b..5b1ae167ce31 100644 --- a/src/libsyntax_ext/test_case.rs +++ b/src/libsyntax_ext/test_case.rs @@ -11,7 +11,7 @@ use syntax::ext::base::*; use syntax::ext::build::AstBuilder; -use syntax::ext::hygiene::{self, Mark, SyntaxContext}; +use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::ast; use syntax::source_map::respan; use syntax::symbol::{Symbol, sym}; @@ -47,7 +47,7 @@ pub fn expand( ].into()), allow_internal_unsafe: false, local_inner_macros: false, - edition: hygiene::default_edition(), + edition: ecx.parse_sess.edition, }); attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(mark)) }; diff --git a/src/libsyntax_pos/edition.rs b/src/libsyntax_pos/edition.rs index 00cd00f28378..20216568426f 100644 --- a/src/libsyntax_pos/edition.rs +++ b/src/libsyntax_pos/edition.rs @@ -1,6 +1,7 @@ use crate::symbol::{Symbol, sym}; use std::fmt; use std::str::FromStr; +use crate::GLOBALS; /// The edition of the compiler (RFC 2052) #[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug, RustcEncodable, RustcDecodable, Eq)] @@ -38,6 +39,10 @@ impl fmt::Display for Edition { } impl Edition { + pub fn from_session() -> Edition { + GLOBALS.with(|globals| globals.edition) + } + pub fn lint_name(&self) -> &'static str { match *self { Edition::Edition2015 => "rust_2015_compatibility", diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 1d9dc26bf609..6e787c08504f 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -7,7 +7,7 @@ use crate::GLOBALS; use crate::Span; -use crate::edition::{Edition, DEFAULT_EDITION}; +use crate::edition::Edition; use crate::symbol::{keywords, Symbol}; use serialize::{Encodable, Decodable, Encoder, Decoder}; @@ -174,7 +174,6 @@ crate struct HygieneData { marks: Vec, syntax_contexts: Vec, markings: FxHashMap<(SyntaxContext, Mark, Transparency), SyntaxContext>, - default_edition: Edition, } impl HygieneData { @@ -196,7 +195,6 @@ impl HygieneData { dollar_crate_name: keywords::DollarCrate.name(), }], markings: FxHashMap::default(), - default_edition: DEFAULT_EDITION, } } @@ -205,14 +203,6 @@ impl HygieneData { } } -pub fn default_edition() -> Edition { - HygieneData::with(|data| data.default_edition) -} - -pub fn set_default_edition(edition: Edition) { - HygieneData::with(|data| data.default_edition = edition); -} - pub fn clear_markings() { HygieneData::with(|data| data.markings = FxHashMap::default()); } diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 39859f25f97f..cb5aaf7eb882 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -26,6 +26,7 @@ use serialize::{Encodable, Decodable, Encoder, Decoder}; extern crate serialize as rustc_serialize; // used by deriving pub mod edition; +use edition::Edition; pub mod hygiene; pub use hygiene::{Mark, SyntaxContext, ExpnInfo, ExpnFormat, CompilerDesugaringKind}; @@ -52,14 +53,16 @@ pub struct Globals { symbol_interner: Lock, span_interner: Lock, hygiene_data: Lock, + edition: Edition, } impl Globals { - pub fn new() -> Globals { + pub fn new(edition: Edition) -> Globals { Globals { symbol_interner: Lock::new(symbol::Interner::fresh()), span_interner: Lock::new(span_encoding::SpanInterner::default()), hygiene_data: Lock::new(hygiene::HygieneData::new()), + edition, } } } @@ -356,8 +359,9 @@ impl Span { /// Edition of the crate from which this span came. pub fn edition(self) -> edition::Edition { - self.ctxt().outer().expn_info().map_or_else(|| hygiene::default_edition(), - |einfo| einfo.edition) + self.ctxt().outer().expn_info().map_or_else(|| { + Edition::from_session() + }, |einfo| einfo.edition) } #[inline] diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index a07c7eb897ec..e69a9a1c5cfc 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -1276,6 +1276,7 @@ impl Encodable for InternedString { mod tests { use super::*; use crate::Globals; + use crate::edition; #[test] fn interner_tests() { @@ -1300,7 +1301,7 @@ mod tests { #[test] fn without_first_quote_test() { - GLOBALS.set(&Globals::new(), || { + GLOBALS.set(&Globals::new(edition::DEFAULT_EDITION), || { let i = Ident::from_str("'break"); assert_eq!(i.without_first_quote().name, keywords::Break.name()); }); diff --git a/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs b/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs index d32fafd215c0..49e137549c04 100644 --- a/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs +++ b/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs @@ -105,7 +105,7 @@ fn reject_stmt_parse(es: &str) { } fn main() { - syntax::with_globals(|| run()); + syntax::with_default_globals(|| run()); } fn run() { diff --git a/src/test/run-pass-fulldeps/auxiliary/plugin-args.rs b/src/test/run-pass-fulldeps/auxiliary/plugin-args.rs index 309acb25184a..096701bd9b3e 100644 --- a/src/test/run-pass-fulldeps/auxiliary/plugin-args.rs +++ b/src/test/run-pass-fulldeps/auxiliary/plugin-args.rs @@ -47,6 +47,6 @@ pub fn plugin_registrar(reg: &mut Registry) { allow_internal_unsafe: false, local_inner_macros: false, unstable_feature: None, - edition: hygiene::default_edition(), + edition: reg.sess.edition(), }); } diff --git a/src/test/run-pass-fulldeps/mod_dir_path_canonicalized.rs b/src/test/run-pass-fulldeps/mod_dir_path_canonicalized.rs index 22a76a3d968a..a0dca9b1da4d 100644 --- a/src/test/run-pass-fulldeps/mod_dir_path_canonicalized.rs +++ b/src/test/run-pass-fulldeps/mod_dir_path_canonicalized.rs @@ -13,7 +13,7 @@ use syntax::parse::{self, ParseSess}; mod gravy; pub fn main() { - syntax::with_globals(|| parse()); + syntax::with_default_globals(|| parse()); assert_eq!(gravy::foo(), 10); } diff --git a/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs b/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs index 80e0b0102af7..659de9cf6d51 100644 --- a/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs +++ b/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs @@ -189,7 +189,7 @@ impl MutVisitor for AddParens { } fn main() { - syntax::with_globals(|| run()); + syntax::with_default_globals(|| run()); } fn run() { diff --git a/src/test/rustdoc-ui/failed-doctest-output.stdout b/src/test/rustdoc-ui/failed-doctest-output.stdout index 7b1cd7027314..45efa30d9919 100644 --- a/src/test/rustdoc-ui/failed-doctest-output.stdout +++ b/src/test/rustdoc-ui/failed-doctest-output.stdout @@ -15,7 +15,7 @@ error[E0425]: cannot find value `no` in this scope error: aborting due to previous error For more information about this error, try `rustc --explain E0425`. -thread '$DIR/failed-doctest-output.rs - OtherStruct (line 17)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:319:13 +thread '$DIR/failed-doctest-output.rs - OtherStruct (line 17)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:320:13 note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace. ---- $DIR/failed-doctest-output.rs - SomeStruct (line 11) stdout ---- @@ -24,7 +24,7 @@ thread '$DIR/failed-doctest-output.rs - SomeStruct (line 11)' panicked at 'test thread 'main' panicked at 'oh no', $DIR/failed-doctest-output.rs:3:1 note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace. -', src/librustdoc/test.rs:341:17 +', src/librustdoc/test.rs:342:17 failures: diff --git a/src/test/rustdoc-ui/unparseable-doc-test.stdout b/src/test/rustdoc-ui/unparseable-doc-test.stdout index 7048ef2c5897..f31b64fbce36 100644 --- a/src/test/rustdoc-ui/unparseable-doc-test.stdout +++ b/src/test/rustdoc-ui/unparseable-doc-test.stdout @@ -13,7 +13,7 @@ error: unterminated double quote string error: aborting due to previous error -thread '$DIR/unparseable-doc-test.rs - foo (line 6)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:319:13 +thread '$DIR/unparseable-doc-test.rs - foo (line 6)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:320:13 note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace. diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index 38bd3fc006dc..3e7c7ab6379d 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -266,7 +266,7 @@ fn main() { *slot.borrow_mut() = Some((None, String::from("https://play.rust-lang.org/"))); }); let (format, dst) = parse_args(); - let result = syntax::with_globals(move || { + let result = syntax::with_default_globals(move || { main_with_result(format, &dst) }); if let Err(e) = result { From 0b37900b40e8db004b2a13ff4c70fc363eba610b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 20 May 2019 03:39:48 +0200 Subject: [PATCH 0220/3207] Specify the edition for the rustdoc thread-pool --- src/librustc_interface/interface.rs | 4 ++-- src/librustdoc/lib.rs | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs index d598a48649ee..674b2b60e44a 100644 --- a/src/librustc_interface/interface.rs +++ b/src/librustc_interface/interface.rs @@ -143,10 +143,10 @@ where ) } -pub fn default_thread_pool(f: F) -> R +pub fn default_thread_pool(edition: edition::Edition, f: F) -> R where F: FnOnce() -> R + Send, R: Send, { - util::spawn_thread_pool(edition::DEFAULT_EDITION, None, &None, f) + util::spawn_thread_pool(edition, None, &None, f) } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index f5061b671828..ffe277ae50bd 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -94,9 +94,7 @@ pub fn main() { rustc_driver::set_sigpipe_handler(); env_logger::init(); let res = std::thread::Builder::new().stack_size(thread_stack_size).spawn(move || { - rustc_interface::interface::default_thread_pool(move || { - get_args().map(|args| main_args(&args)).unwrap_or(1) - }) + get_args().map(|args| main_args(&args)).unwrap_or(1) }).unwrap().join().unwrap_or(rustc_driver::EXIT_FAILURE); process::exit(res); } @@ -382,7 +380,12 @@ fn main_args(args: &[String]) -> i32 { Ok(opts) => opts, Err(code) => return code, }; + rustc_interface::interface::default_thread_pool(options.edition, move || { + main_options(options) + }) +} +fn main_options(options: config::Options) -> i32 { let diag = core::new_handler(options.error_format, None, options.debugging_options.treat_err_as_bug, From 33fb1c501c95b9089b67c079aa79b50f1adedfe5 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Mon, 13 May 2019 17:09:30 -0700 Subject: [PATCH 0221/3207] Add FAQ for NLL migration --- src/librustc_mir/borrow_check/mod.rs | 5 +-- src/librustc_mir/error_codes.rs | 32 +++++++++++++++++++ .../borrowck-anon-fields-variant.stderr | 1 + .../borrowck/borrowck-describe-lvalue.stderr | 2 ++ .../borrowck-migrate-to-nll.edition.stderr | 1 + .../borrowck-migrate-to-nll.zflag.stderr | 1 + .../borrowck/borrowck-mutate-in-guard.stderr | 2 ++ src/test/ui/consts/const_let_refutable.stderr | 2 ++ .../consts/min_const_fn/min_const_fn.stderr | 1 + .../min_const_fn/min_const_fn_dyn.stderr | 1 + src/test/ui/empty/empty-never-array.stderr | 1 + .../ui/feature-gates/feature-gate-nll.stderr | 1 + src/test/ui/issues/issue-15381.stderr | 1 + .../ui/issues/issue-40510-1.migrate.stderr | 1 + .../ui/issues/issue-40510-3.migrate.stderr | 1 + ...96-scribble-on-boxed-borrow.migrate.stderr | 3 ++ src/test/ui/issues/issue-49824.stderr | 1 + .../pattern/pattern-bindings-after-at.stderr | 1 + ...recursive-types-are-not-uninhabited.stderr | 1 + src/test/ui/thread-local-in-ctfe.stderr | 2 ++ 20 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index fc1f5eb5d5a7..cf02878ec82e 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -439,10 +439,11 @@ fn downgrade_if_error(diag: &mut Diagnostic) { diag.warn( "this error has been downgraded to a warning for backwards \ compatibility with previous releases", - ); - diag.warn( + ).warn( "this represents potential undefined behavior in your code and \ this warning will become a hard error in the future", + ).note( + "for more information, try `rustc --explain E0729`" ); } } diff --git a/src/librustc_mir/error_codes.rs b/src/librustc_mir/error_codes.rs index 74a4278d5991..4807782c6634 100644 --- a/src/librustc_mir/error_codes.rs +++ b/src/librustc_mir/error_codes.rs @@ -2424,6 +2424,38 @@ const fn foo() -> impl T { ``` "##, +E0729: r##" +Support for Non-Lexical Lifetimes (NLL) has been included in the Rust compiler +since 1.31, and has been enabled on the 2015 edition since 1.36. The new borrow +checker for NLL uncovered some bugs in the old borrow checker, which in some +cases allowed unsound code to compile, resulting in memory safety issues. + +### What do I do? + +Change your code so the warning does no longer trigger. For backwards +compatibility, this unsound code may still compile (with a warning) right now. +However, at some point in the future, the compiler will no longer accept this +code and will throw a hard error. + +### Shouldn't you fix the old borrow checker? + +The old borrow checker has known soundness issues that are basically impossible +to fix. The new NLL-based borrow checker is the fix. + +### Can I turn these warnings into errors by denying a lint? + +No. + +### When are these warnings going to turn into errors? + +No formal timeline for turning the warnings into errors has been set. See +[GitHub issue 58781](https://github.com/rust-lang/rust/issues/58781) for more +information. + +### Why do I get this message with code that doesn't involve borrowing? + +There are some known bugs that trigger this message. +"##, } register_diagnostics! { diff --git a/src/test/ui/borrowck/borrowck-anon-fields-variant.stderr b/src/test/ui/borrowck/borrowck-anon-fields-variant.stderr index 5e86dcb1232c..e2d3e417ac3a 100644 --- a/src/test/ui/borrowck/borrowck-anon-fields-variant.stderr +++ b/src/test/ui/borrowck/borrowck-anon-fields-variant.stderr @@ -12,6 +12,7 @@ LL | *a += 1; | = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` error[E0503]: cannot use `y` because it was mutably borrowed --> $DIR/borrowck-anon-fields-variant.rs:37:7 diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.stderr index fb42e5fbca8a..14b9b50f0c32 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.stderr +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.stderr @@ -341,6 +341,7 @@ LL | drop(x); | = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` warning[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable --> $DIR/borrowck-describe-lvalue.rs:227:33 @@ -355,6 +356,7 @@ LL | drop(x); | = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` error[E0382]: use of moved value: `x` --> $DIR/borrowck-describe-lvalue.rs:282:22 diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr b/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr index 8dba34bd8086..461fb7d11a58 100644 --- a/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr +++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr @@ -6,4 +6,5 @@ LL | (|| { let bar = foo; bar.take() })(); | = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr b/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr index 8dba34bd8086..461fb7d11a58 100644 --- a/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr +++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr @@ -6,4 +6,5 @@ LL | (|| { let bar = foo; bar.take() })(); | = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr index d12d751d89b7..ac6bed6137fa 100644 --- a/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr +++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr @@ -28,6 +28,7 @@ LL | Enum::A(_) if { x = Enum::B(false); false } => 1, | = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` warning[E0510]: cannot mutably borrow `x` in match guard --> $DIR/borrowck-mutate-in-guard.rs:15:33 @@ -40,6 +41,7 @@ LL | Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1, | = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` error: aborting due to 3 previous errors diff --git a/src/test/ui/consts/const_let_refutable.stderr b/src/test/ui/consts/const_let_refutable.stderr index 20433bbf8b5c..2ca76667bd11 100644 --- a/src/test/ui/consts/const_let_refutable.stderr +++ b/src/test/ui/consts/const_let_refutable.stderr @@ -21,6 +21,7 @@ LL | a + b | = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` warning[E0381]: use of possibly uninitialized variable: `b` --> $DIR/const_let_refutable.rs:4:9 @@ -30,6 +31,7 @@ LL | a + b | = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr index 7af379924608..93b57bc24a82 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr @@ -297,6 +297,7 @@ LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } | = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable --> $DIR/min_const_fn.rs:144:41 diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr index b6445329db38..9ded93c16727 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr @@ -27,6 +27,7 @@ LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) } | = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` error: aborting due to 2 previous errors diff --git a/src/test/ui/empty/empty-never-array.stderr b/src/test/ui/empty/empty-never-array.stderr index 6608ad763b2e..9911dd4683b6 100644 --- a/src/test/ui/empty/empty-never-array.stderr +++ b/src/test/ui/empty/empty-never-array.stderr @@ -19,6 +19,7 @@ LL | u | = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` error: aborting due to previous error diff --git a/src/test/ui/feature-gates/feature-gate-nll.stderr b/src/test/ui/feature-gates/feature-gate-nll.stderr index ac21241b3038..37542d52dc2c 100644 --- a/src/test/ui/feature-gates/feature-gate-nll.stderr +++ b/src/test/ui/feature-gates/feature-gate-nll.stderr @@ -11,6 +11,7 @@ LL | m; | = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` error: compilation successful --> $DIR/feature-gate-nll.rs:10:1 diff --git a/src/test/ui/issues/issue-15381.stderr b/src/test/ui/issues/issue-15381.stderr index 0f44a0f170f8..7b11d85ead87 100644 --- a/src/test/ui/issues/issue-15381.stderr +++ b/src/test/ui/issues/issue-15381.stderr @@ -12,6 +12,7 @@ LL | println!("y={}", y); | = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-40510-1.migrate.stderr b/src/test/ui/issues/issue-40510-1.migrate.stderr index 17d1c48d0754..28aaa2a797e0 100644 --- a/src/test/ui/issues/issue-40510-1.migrate.stderr +++ b/src/test/ui/issues/issue-40510-1.migrate.stderr @@ -10,6 +10,7 @@ LL | &mut x = note: ...therefore, they cannot allow references to captured variables to escape = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` error: compilation successful --> $DIR/issue-40510-1.rs:20:1 diff --git a/src/test/ui/issues/issue-40510-3.migrate.stderr b/src/test/ui/issues/issue-40510-3.migrate.stderr index 692aa1053779..f00690efc312 100644 --- a/src/test/ui/issues/issue-40510-3.migrate.stderr +++ b/src/test/ui/issues/issue-40510-3.migrate.stderr @@ -12,6 +12,7 @@ LL | | } = note: ...therefore, they cannot allow references to captured variables to escape = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` error: compilation successful --> $DIR/issue-40510-3.rs:22:1 diff --git a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr index 8cc9f1eb2a63..479b724ad18f 100644 --- a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr +++ b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr @@ -11,6 +11,7 @@ LL | } | = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` warning[E0713]: borrow may still be in use when destructor runs --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:62:5 @@ -25,6 +26,7 @@ LL | } | = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` warning[E0713]: borrow may still be in use when destructor runs --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:73:5 @@ -39,6 +41,7 @@ LL | } | = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` error: compilation successful --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:80:1 diff --git a/src/test/ui/issues/issue-49824.stderr b/src/test/ui/issues/issue-49824.stderr index c66ee69cb2bd..d5f1af88e133 100644 --- a/src/test/ui/issues/issue-49824.stderr +++ b/src/test/ui/issues/issue-49824.stderr @@ -15,6 +15,7 @@ LL | | } = note: ...therefore, they cannot allow references to captured variables to escape = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` error: compilation successful --> $DIR/issue-49824.rs:6:1 diff --git a/src/test/ui/pattern/pattern-bindings-after-at.stderr b/src/test/ui/pattern/pattern-bindings-after-at.stderr index 3a2cffcbf45f..70452a930ee7 100644 --- a/src/test/ui/pattern/pattern-bindings-after-at.stderr +++ b/src/test/ui/pattern/pattern-bindings-after-at.stderr @@ -18,6 +18,7 @@ LL | **z = None; | = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` error: aborting due to previous error diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr index 940ab94a6133..9203f893fdbf 100644 --- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr +++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr @@ -12,6 +12,7 @@ LL | x | = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` error: aborting due to previous error diff --git a/src/test/ui/thread-local-in-ctfe.stderr b/src/test/ui/thread-local-in-ctfe.stderr index bba5b0c74d98..6869109e67fc 100644 --- a/src/test/ui/thread-local-in-ctfe.stderr +++ b/src/test/ui/thread-local-in-ctfe.stderr @@ -20,6 +20,7 @@ LL | static C: &u32 = &A; | = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` error[E0625]: thread-local statics cannot be accessed at compile-time --> $DIR/thread-local-in-ctfe.rs:15:16 @@ -43,6 +44,7 @@ LL | const E: &u32 = &A; | = warning: this error has been downgraded to a warning for backwards compatibility with previous releases = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future + = note: for more information, try `rustc --explain E0729` error[E0625]: thread-local statics cannot be accessed at compile-time --> $DIR/thread-local-in-ctfe.rs:25:5 From 0e5f02f9025ce2f5b9ff5035c50bcdde051b6ade Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 21 May 2019 10:28:56 -0700 Subject: [PATCH 0222/3207] Fix typo in key configuration --- .azure-pipelines/steps/run.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.azure-pipelines/steps/run.yml b/.azure-pipelines/steps/run.yml index 8882278e3fe0..e697eb1c064e 100644 --- a/.azure-pipelines/steps/run.yml +++ b/.azure-pipelines/steps/run.yml @@ -93,7 +93,7 @@ steps: env: CI: true SRC: . - AWS_SECRET_ACCESS_KEY: $(SCCACHE_AWS_SECRET_ACCESS_KEY) + AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY) displayName: Run build - bash: | @@ -104,6 +104,6 @@ steps: fi aws s3 cp --no-progress --recursive --acl public-read ./deploy s3://$DEPLOY_BUCKET/$deploy_dir env: - AWS_SECRET_ACCESS_KEY: $(SCCACHE_AWS_SECRET_ACCESS_KEY) + AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY) condition: and(succeeded(), or(eq(variables.DEPLOY, '1'), eq(variables.DEPLOY_ALT, '1'))) displayName: Upload artifacts From 571366f71bd1d76934959ba33ce7ef2ee07649a3 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 21 May 2019 10:33:19 -0700 Subject: [PATCH 0223/3207] Attempt to enable IPv6 for Linux --- .azure-pipelines/steps/run.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.azure-pipelines/steps/run.yml b/.azure-pipelines/steps/run.yml index e697eb1c064e..2d38920da88e 100644 --- a/.azure-pipelines/steps/run.yml +++ b/.azure-pipelines/steps/run.yml @@ -37,6 +37,15 @@ steps: - template: install-windows-build-deps.yml +# Looks like docker containers have IPv6 disabled by default, so let's turn it +# on since libstd tests require it +- bash: | + set -e + echo '{"ipv6":true,"fixed-cidr-v6":"fd9a:8454:6789:13f7::/64"}' | sudo tee /etc/docker/daemon.json + sudo service docker restart + displayName: Enable IPv6 + condition: and(succeeded(), eq(variables['Agent.OS'], 'Linux')) + # Check out all our submodules, but more quickly than using git by using one of # our custom scripts - bash: | From a83250dcfa5d0751f7d896cb8999ef76ea074771 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 21 May 2019 10:38:05 -0700 Subject: [PATCH 0224/3207] Update upload logic to upload right directory --- .azure-pipelines/steps/run.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.azure-pipelines/steps/run.yml b/.azure-pipelines/steps/run.yml index 2d38920da88e..3516ca598075 100644 --- a/.azure-pipelines/steps/run.yml +++ b/.azure-pipelines/steps/run.yml @@ -107,11 +107,19 @@ steps: - bash: | set -e + if [ "$AGENT_OS" = "Linux" ]; then + rm -rf obj/build/dist/doc + upload_dir=obj/build/dist deploy/$BUILD_SOURCEVERSION + else + rm -rf build/dist/doc + upload_dir=build/dist + fi + ls -la $upload_dir deploy_dir=rustc-builds if [ "$DEPLOY_ALT" == "1" ]; then deploy_dir=rustc-builds-alt fi - aws s3 cp --no-progress --recursive --acl public-read ./deploy s3://$DEPLOY_BUCKET/$deploy_dir + aws s3 cp --no-progress --recursive --acl public-read ./$upload_dir s3://$DEPLOY_BUCKET/$deploy_dir/$BUILD_SOURCEVERSION env: AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY) condition: and(succeeded(), or(eq(variables.DEPLOY, '1'), eq(variables.DEPLOY_ALT, '1'))) From ebdc36eb8e4b0fa8d8954ded3cb282951bab95d3 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 21 May 2019 10:39:37 -0700 Subject: [PATCH 0225/3207] Re-enable hack for Windows builds to see if it works --- .../steps/install-windows-build-deps.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.azure-pipelines/steps/install-windows-build-deps.yml b/.azure-pipelines/steps/install-windows-build-deps.yml index 45ce01fee758..8bda290cd985 100644 --- a/.azure-pipelines/steps/install-windows-build-deps.yml +++ b/.azure-pipelines/steps/install-windows-build-deps.yml @@ -5,13 +5,14 @@ steps: # git submodule # export SUBMODULES_EXCLUDES=$(git submodule | grep -Eow 'src/[^ ]+' | sed 's/\(.*\)/--exclude=\1\/\.git/') # echo "##vso[task.setvariable variable=SUBMODULES_EXCLUDES;]$SUBMODULES_EXCLUDES" -# -# - script: | -# REM echo hack as drive D is too small -# IF NOT "%DISABLE_DISK_SPACE_HACK%"=="1" ( -# mkdir c:\MORE_SPACE -# mklink /J build c:\MORE_SPACE -# ) + +# FIXME: needs a comment to justify its existence +- script: | + REM echo hack as drive D is too small + IF NOT "%DISABLE_DISK_SPACE_HACK%"=="1" ( + mkdir c:\MORE_SPACE + mklink /J build c:\MORE_SPACE + ) - script: | set MSYS_PATH=%CD%\citools\msys64 From 55108b379ebc1e5de5a7a40ab8f3abbfdbb20be2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 21 May 2019 10:45:13 -0700 Subject: [PATCH 0226/3207] Run a full build on `try` temporarily --- .azure-pipelines/try.yml | 296 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 279 insertions(+), 17 deletions(-) diff --git a/.azure-pipelines/try.yml b/.azure-pipelines/try.yml index 8060dc0a2f32..603516370d9f 100644 --- a/.azure-pipelines/try.yml +++ b/.azure-pipelines/try.yml @@ -1,38 +1,163 @@ # -# Azure Pipelines "try" branch build for Rust +# Azure Pipelines "auto" branch build for Rust on Linux, macOS, and Windows. # pr: none -trigger: -- try + trigger: + - auto variables: - group: prod-credentials jobs: - job: Linux - timeoutInMinutes: 600 pool: vmImage: ubuntu-16.04 + steps: + - template: steps/run.yml strategy: matrix: + x86_64-gnu-llvm-6.0: + IMAGE: x86_64-gnu-llvm-6.0 + RUST_BACKTRACE: 1 + dist-x86_64-linux: IMAGE: dist-x86_64-linux DEPLOY: 1 dist-x86_64-linux-alt: IMAGE: dist-x86_64-linux DEPLOY_ALT: 1 - test-various: - IMAGE: test-various - steps: - - template: steps/run.yml + + arm-android: + IMAGE: arm-android + + armhf-gnu: + IMAGE: armhf-gnu + + dist-various-1: + IMAGE: dist-various-1 + DEPLOY: 1 + + dist-various-2: + IMAGE: dist-various-2 + DEPLOY: 1 + + dist-aarch64-linux: + IMAGE: dist-aarch64-linux + DEPLOY: 1 + + dist-android: + IMAGE: dist-android + DEPLOY: 1 + + dist-arm-linux: + IMAGE: dist-arm-linux + DEPLOY: 1 + + dist-armhf-linux: + IMAGE: dist-armhf-linux + DEPLOY: 1 + + dist-armv7-linux: + IMAGE: dist-armv7-linux + DEPLOY: 1 + + dist-i586-gnu-i586-i686-musl: + IMAGE: dist-i586-gnu-i586-i686-musl + DEPLOY: 1 + + dist-i686-freebsd: + IMAGE: dist-i686-freebsd + DEPLOY: 1 + + dist-i686-linux: + IMAGE: dist-i686-linux + DEPLOY: 1 + + dist-mips-linux: + IMAGE: dist-mips-linux + DEPLOY: 1 + + dist-mips64-linux: + IMAGE: dist-mips64-linux + DEPLOY: 1 + + dist-mips64el-linux: + IMAGE: dist-mips64el-linux + DEPLOY: 1 + + dist-mipsel-linux: + IMAGE: dist-mipsel-linux + DEPLOY: 1 + + dist-powerpc-linux: + IMAGE: dist-powerpc-linux + DEPLOY: 1 + + dist-powerpc64-linux: + IMAGE: dist-powerpc64-linux + DEPLOY: 1 + + dist-powerpc64le-linux: + IMAGE: dist-powerpc64le-linux + DEPLOY: 1 + + dist-s390x-linux: + IMAGE: dist-s390x-linux + DEPLOY: 1 + + dist-x86_64-freebsd: + IMAGE: dist-x86_64-freebsd + DEPLOY: 1 + + dist-x86_64-musl: + IMAGE: dist-x86_64-musl + DEPLOY: 1 + + dist-x86_64-netbsd: + IMAGE: dist-x86_64-netbsd + DEPLOY: 1 + + asmjs: + IMAGE: asmjs + i686-gnu: + IMAGE: i686-gnu + i686-gnu-nopt: + IMAGE: i686-gnu-nopt + test-various: + IMAGE: test-various + x86_64-gnu: + IMAGE: x86_64-gnu + x86_64-gnu-full-bootstrap: + IMAGE: x86_64-gnu-full-bootstrap + x86_64-gnu-aux: + IMAGE: x86_64-gnu-aux + x86_64-gnu-tools: + IMAGE: x86_64-gnu-tools + x86_64-gnu-debug: + IMAGE: x86_64-gnu-debug + x86_64-gnu-nopt: + IMAGE: x86_64-gnu-nopt + x86_64-gnu-distcheck: + IMAGE: x86_64-gnu-distcheck + mingw-check: + IMAGE: mingw-check - job: macOS - timeoutInMinutes: 600 pool: vmImage: macos-10.13 + steps: + - checkout: self + fetchDepth: 2 + - template: steps/run.yml strategy: matrix: + # OSX builders running tests, these run the full test suite. + # NO_DEBUG_ASSERTIONS=1 to make them go faster, but also do have some + # runners that run `//ignore-debug` tests. + # + # Note that the compiler is compiled to target 10.8 here because the Xcode + # version that we're using, 8.2, cannot compile LLVM for OSX 10.7. x86_64-apple: RUST_CHECK_TARGET: check RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc @@ -51,32 +176,169 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 DIST_REQUIRE_ALL_TOOLS: 1 - steps: - - template: steps/run.yml + + dist-x86_64-apple-alt: + RUST_CHECK_TARGET: dist + RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --enable-lldb --set rust.jemalloc + DEPLOY_ALT: 1 + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + + i686-apple: + RUST_CHECK_TARGET: check + RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + + dist-i686-apple: + RUST_CHECK_TARGET: dist + RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb --set rust.jemalloc + DEPLOY: 1 + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + DIST_REQUIRE_ALL_TOOLS: 1 + + - job: Windows - timeoutInMinutes: 600 pool: vmImage: 'vs2017-win2016' + steps: + - template: steps/run.yml strategy: matrix: + # 32/64 bit MSVC tests x86_64-msvc-1: + MSYS_BITS: 64 RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler SCRIPT: make ci-subset-1 + # FIXME(#59637) NO_DEBUG_ASSERTIONS: 1 NO_LLVM_ASSERTIONS: 1 x86_64-msvc-2: + MSYS_BITS: 64 RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler SCRIPT: make ci-subset-2 + i686-msvc-1: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc + SCRIPT: make ci-subset-1 + i686-msvc-2: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc + SCRIPT: make ci-subset-2 + # MSVC aux tests + x86_64-msvc-aux: + MSYS_BITS: 64 + RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + x86_64-msvc-cargo: + MSYS_BITS: 64 + SCRIPT: python x.py test src/tools/cargotest src/tools/cargo + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + VCVARS_BAT: vcvars64.bat + # MSVC tools tests + x86_64-msvc-tools: + MSYS_BITS: 64 + SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri - dist-x86_64-msvc: + # 32/64-bit MinGW builds. + # + # We are using MinGW with posix threads since LLVM does not compile with + # the win32 threads version due to missing support for C++'s std::thread. + # + # Instead of relying on the MinGW version installed on appveryor we download + # and install one ourselves so we won't be surprised by changes to appveyor's + # build image. + # + # Finally, note that the downloads below are all in the `rust-lang-ci` S3 + # bucket, but they cleraly didn't originate there! The downloads originally + # came from the mingw-w64 SourceForge download site. Unfortunately + # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. + i686-mingw-1: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + SCRIPT: make ci-subset-1 + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z + MINGW_DIR: mingw32 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + i686-mingw-2: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + SCRIPT: make ci-subset-2 + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z + MINGW_DIR: mingw32 + x86_64-mingw-1: + MSYS_BITS: 64 + SCRIPT: make ci-subset-1 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z + MINGW_DIR: mingw64 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + x86_64-mingw-2: + MSYS_BITS: 64 + SCRIPT: make ci-subset-2 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z + MINGW_DIR: mingw64 + + # 32/64 bit MSVC and GNU deployment + dist-x86_64-msvc: + RUST_CONFIGURE_ARGS: > + --build=x86_64-pc-windows-msvc + --target=x86_64-pc-windows-msvc,aarch64-pc-windows-msvc + --enable-full-tools + --enable-profiler + SCRIPT: python x.py dist + DIST_REQUIRE_ALL_TOOLS: 1 + DEPLOY: 1 + dist-i686-msvc: RUST_CONFIGURE_ARGS: > - --build=x86_64-pc-windows-msvc - --target=x86_64-pc-windows-msvc,aarch64-pc-windows-msvc + --build=i686-pc-windows-msvc + --target=i586-pc-windows-msvc --enable-full-tools --enable-profiler SCRIPT: python x.py dist DIST_REQUIRE_ALL_TOOLS: 1 DEPLOY: 1 - steps: - - template: steps/run.yml + dist-i686-mingw: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools + SCRIPT: python x.py dist + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z + MINGW_DIR: mingw32 + DIST_REQUIRE_ALL_TOOLS: 1 + DEPLOY: 1 + dist-x86_64-mingw: + MSYS_BITS: 64 + SCRIPT: python x.py dist + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z + MINGW_DIR: mingw64 + DIST_REQUIRE_ALL_TOOLS: 1 + DEPLOY: 1 + + # "alternate" deployment, see .travis.yml for more info + dist-x86_64-msvc-alt: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler + SCRIPT: python x.py dist + DEPLOY_ALT: 1 From e8f0e70b004f5bbce00249e95768ba9fdc48838f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 21 May 2019 10:46:41 -0700 Subject: [PATCH 0227/3207] Typos --- .azure-pipelines/try.yml | 466 +++++++++++++++++++-------------------- 1 file changed, 231 insertions(+), 235 deletions(-) diff --git a/.azure-pipelines/try.yml b/.azure-pipelines/try.yml index 603516370d9f..3ef24d2de973 100644 --- a/.azure-pipelines/try.yml +++ b/.azure-pipelines/try.yml @@ -3,8 +3,8 @@ # pr: none - trigger: - - auto +trigger: +- try variables: - group: prod-credentials @@ -28,118 +28,118 @@ jobs: IMAGE: dist-x86_64-linux DEPLOY_ALT: 1 - arm-android: - IMAGE: arm-android + arm-android: + IMAGE: arm-android - armhf-gnu: - IMAGE: armhf-gnu + armhf-gnu: + IMAGE: armhf-gnu - dist-various-1: - IMAGE: dist-various-1 - DEPLOY: 1 + dist-various-1: + IMAGE: dist-various-1 + DEPLOY: 1 - dist-various-2: - IMAGE: dist-various-2 - DEPLOY: 1 + dist-various-2: + IMAGE: dist-various-2 + DEPLOY: 1 - dist-aarch64-linux: - IMAGE: dist-aarch64-linux - DEPLOY: 1 + dist-aarch64-linux: + IMAGE: dist-aarch64-linux + DEPLOY: 1 - dist-android: - IMAGE: dist-android - DEPLOY: 1 + dist-android: + IMAGE: dist-android + DEPLOY: 1 - dist-arm-linux: - IMAGE: dist-arm-linux - DEPLOY: 1 + dist-arm-linux: + IMAGE: dist-arm-linux + DEPLOY: 1 - dist-armhf-linux: - IMAGE: dist-armhf-linux - DEPLOY: 1 + dist-armhf-linux: + IMAGE: dist-armhf-linux + DEPLOY: 1 - dist-armv7-linux: - IMAGE: dist-armv7-linux - DEPLOY: 1 + dist-armv7-linux: + IMAGE: dist-armv7-linux + DEPLOY: 1 - dist-i586-gnu-i586-i686-musl: - IMAGE: dist-i586-gnu-i586-i686-musl - DEPLOY: 1 + dist-i586-gnu-i586-i686-musl: + IMAGE: dist-i586-gnu-i586-i686-musl + DEPLOY: 1 - dist-i686-freebsd: - IMAGE: dist-i686-freebsd - DEPLOY: 1 + dist-i686-freebsd: + IMAGE: dist-i686-freebsd + DEPLOY: 1 - dist-i686-linux: - IMAGE: dist-i686-linux - DEPLOY: 1 + dist-i686-linux: + IMAGE: dist-i686-linux + DEPLOY: 1 - dist-mips-linux: - IMAGE: dist-mips-linux - DEPLOY: 1 + dist-mips-linux: + IMAGE: dist-mips-linux + DEPLOY: 1 - dist-mips64-linux: - IMAGE: dist-mips64-linux - DEPLOY: 1 + dist-mips64-linux: + IMAGE: dist-mips64-linux + DEPLOY: 1 - dist-mips64el-linux: - IMAGE: dist-mips64el-linux - DEPLOY: 1 + dist-mips64el-linux: + IMAGE: dist-mips64el-linux + DEPLOY: 1 - dist-mipsel-linux: - IMAGE: dist-mipsel-linux - DEPLOY: 1 + dist-mipsel-linux: + IMAGE: dist-mipsel-linux + DEPLOY: 1 - dist-powerpc-linux: - IMAGE: dist-powerpc-linux - DEPLOY: 1 + dist-powerpc-linux: + IMAGE: dist-powerpc-linux + DEPLOY: 1 - dist-powerpc64-linux: - IMAGE: dist-powerpc64-linux - DEPLOY: 1 + dist-powerpc64-linux: + IMAGE: dist-powerpc64-linux + DEPLOY: 1 - dist-powerpc64le-linux: - IMAGE: dist-powerpc64le-linux - DEPLOY: 1 + dist-powerpc64le-linux: + IMAGE: dist-powerpc64le-linux + DEPLOY: 1 - dist-s390x-linux: - IMAGE: dist-s390x-linux - DEPLOY: 1 + dist-s390x-linux: + IMAGE: dist-s390x-linux + DEPLOY: 1 - dist-x86_64-freebsd: - IMAGE: dist-x86_64-freebsd - DEPLOY: 1 + dist-x86_64-freebsd: + IMAGE: dist-x86_64-freebsd + DEPLOY: 1 - dist-x86_64-musl: - IMAGE: dist-x86_64-musl - DEPLOY: 1 + dist-x86_64-musl: + IMAGE: dist-x86_64-musl + DEPLOY: 1 - dist-x86_64-netbsd: - IMAGE: dist-x86_64-netbsd - DEPLOY: 1 + dist-x86_64-netbsd: + IMAGE: dist-x86_64-netbsd + DEPLOY: 1 - asmjs: - IMAGE: asmjs - i686-gnu: - IMAGE: i686-gnu - i686-gnu-nopt: - IMAGE: i686-gnu-nopt - test-various: - IMAGE: test-various - x86_64-gnu: - IMAGE: x86_64-gnu - x86_64-gnu-full-bootstrap: - IMAGE: x86_64-gnu-full-bootstrap - x86_64-gnu-aux: - IMAGE: x86_64-gnu-aux - x86_64-gnu-tools: - IMAGE: x86_64-gnu-tools - x86_64-gnu-debug: - IMAGE: x86_64-gnu-debug - x86_64-gnu-nopt: - IMAGE: x86_64-gnu-nopt - x86_64-gnu-distcheck: - IMAGE: x86_64-gnu-distcheck + asmjs: + IMAGE: asmjs + i686-gnu: + IMAGE: i686-gnu + i686-gnu-nopt: + IMAGE: i686-gnu-nopt + test-various: + IMAGE: test-various + x86_64-gnu: + IMAGE: x86_64-gnu + x86_64-gnu-full-bootstrap: + IMAGE: x86_64-gnu-full-bootstrap + x86_64-gnu-aux: + IMAGE: x86_64-gnu-aux + x86_64-gnu-tools: + IMAGE: x86_64-gnu-tools + x86_64-gnu-debug: + IMAGE: x86_64-gnu-debug + x86_64-gnu-nopt: + IMAGE: x86_64-gnu-nopt + x86_64-gnu-distcheck: + IMAGE: x86_64-gnu-distcheck mingw-check: IMAGE: mingw-check @@ -147,8 +147,6 @@ jobs: pool: vmImage: macos-10.13 steps: - - checkout: self - fetchDepth: 2 - template: steps/run.yml strategy: matrix: @@ -177,35 +175,33 @@ jobs: NO_DEBUG_ASSERTIONS: 1 DIST_REQUIRE_ALL_TOOLS: 1 - dist-x86_64-apple-alt: - RUST_CHECK_TARGET: dist - RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --enable-lldb --set rust.jemalloc - DEPLOY_ALT: 1 - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - - i686-apple: - RUST_CHECK_TARGET: check - RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.8 - MACOSX_STD_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - - dist-i686-apple: - RUST_CHECK_TARGET: dist - RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb --set rust.jemalloc - DEPLOY: 1 - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - DIST_REQUIRE_ALL_TOOLS: 1 + dist-x86_64-apple-alt: + RUST_CHECK_TARGET: dist + RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --enable-lldb --set rust.jemalloc + DEPLOY_ALT: 1 + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + i686-apple: + RUST_CHECK_TARGET: check + RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + dist-i686-apple: + RUST_CHECK_TARGET: dist + RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb --set rust.jemalloc + DEPLOY: 1 + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + DIST_REQUIRE_ALL_TOOLS: 1 - job: Windows pool: @@ -214,89 +210,89 @@ jobs: - template: steps/run.yml strategy: matrix: - # 32/64 bit MSVC tests - x86_64-msvc-1: - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler - SCRIPT: make ci-subset-1 - # FIXME(#59637) - NO_DEBUG_ASSERTIONS: 1 - NO_LLVM_ASSERTIONS: 1 - x86_64-msvc-2: - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler - SCRIPT: make ci-subset-2 - i686-msvc-1: - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc - SCRIPT: make ci-subset-1 - i686-msvc-2: - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc - SCRIPT: make ci-subset-2 - # MSVC aux tests - x86_64-msvc-aux: - MSYS_BITS: 64 - RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc - x86_64-msvc-cargo: - MSYS_BITS: 64 - SCRIPT: python x.py test src/tools/cargotest src/tools/cargo - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc - VCVARS_BAT: vcvars64.bat - # MSVC tools tests - x86_64-msvc-tools: - MSYS_BITS: 64 - SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri + # 32/64 bit MSVC tests + x86_64-msvc-1: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + SCRIPT: make ci-subset-1 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + x86_64-msvc-2: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + SCRIPT: make ci-subset-2 + i686-msvc-1: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc + SCRIPT: make ci-subset-1 + i686-msvc-2: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc + SCRIPT: make ci-subset-2 + # MSVC aux tests + x86_64-msvc-aux: + MSYS_BITS: 64 + RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + x86_64-msvc-cargo: + MSYS_BITS: 64 + SCRIPT: python x.py test src/tools/cargotest src/tools/cargo + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + VCVARS_BAT: vcvars64.bat + # MSVC tools tests + x86_64-msvc-tools: + MSYS_BITS: 64 + SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri - # 32/64-bit MinGW builds. - # - # We are using MinGW with posix threads since LLVM does not compile with - # the win32 threads version due to missing support for C++'s std::thread. - # - # Instead of relying on the MinGW version installed on appveryor we download - # and install one ourselves so we won't be surprised by changes to appveyor's - # build image. - # - # Finally, note that the downloads below are all in the `rust-lang-ci` S3 - # bucket, but they cleraly didn't originate there! The downloads originally - # came from the mingw-w64 SourceForge download site. Unfortunately - # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. - i686-mingw-1: - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - SCRIPT: make ci-subset-1 - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z - MINGW_DIR: mingw32 - # FIXME(#59637) - NO_DEBUG_ASSERTIONS: 1 - NO_LLVM_ASSERTIONS: 1 - i686-mingw-2: - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - SCRIPT: make ci-subset-2 - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z - MINGW_DIR: mingw32 - x86_64-mingw-1: - MSYS_BITS: 64 - SCRIPT: make ci-subset-1 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z - MINGW_DIR: mingw64 - # FIXME(#59637) - NO_DEBUG_ASSERTIONS: 1 - NO_LLVM_ASSERTIONS: 1 - x86_64-mingw-2: - MSYS_BITS: 64 - SCRIPT: make ci-subset-2 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z - MINGW_DIR: mingw64 + # 32/64-bit MinGW builds. + # + # We are using MinGW with posix threads since LLVM does not compile with + # the win32 threads version due to missing support for C++'s std::thread. + # + # Instead of relying on the MinGW version installed on appveryor we download + # and install one ourselves so we won't be surprised by changes to appveyor's + # build image. + # + # Finally, note that the downloads below are all in the `rust-lang-ci` S3 + # bucket, but they cleraly didn't originate there! The downloads originally + # came from the mingw-w64 SourceForge download site. Unfortunately + # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. + i686-mingw-1: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + SCRIPT: make ci-subset-1 + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z + MINGW_DIR: mingw32 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + i686-mingw-2: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + SCRIPT: make ci-subset-2 + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z + MINGW_DIR: mingw32 + x86_64-mingw-1: + MSYS_BITS: 64 + SCRIPT: make ci-subset-1 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z + MINGW_DIR: mingw64 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + x86_64-mingw-2: + MSYS_BITS: 64 + SCRIPT: make ci-subset-2 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z + MINGW_DIR: mingw64 # 32/64 bit MSVC and GNU deployment dist-x86_64-msvc: @@ -308,37 +304,37 @@ jobs: SCRIPT: python x.py dist DIST_REQUIRE_ALL_TOOLS: 1 DEPLOY: 1 - dist-i686-msvc: - RUST_CONFIGURE_ARGS: > - --build=i686-pc-windows-msvc - --target=i586-pc-windows-msvc - --enable-full-tools - --enable-profiler - SCRIPT: python x.py dist - DIST_REQUIRE_ALL_TOOLS: 1 - DEPLOY: 1 - dist-i686-mingw: - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools - SCRIPT: python x.py dist - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z - MINGW_DIR: mingw32 - DIST_REQUIRE_ALL_TOOLS: 1 - DEPLOY: 1 - dist-x86_64-mingw: - MSYS_BITS: 64 - SCRIPT: python x.py dist - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z - MINGW_DIR: mingw64 - DIST_REQUIRE_ALL_TOOLS: 1 - DEPLOY: 1 + dist-i686-msvc: + RUST_CONFIGURE_ARGS: > + --build=i686-pc-windows-msvc + --target=i586-pc-windows-msvc + --enable-full-tools + --enable-profiler + SCRIPT: python x.py dist + DIST_REQUIRE_ALL_TOOLS: 1 + DEPLOY: 1 + dist-i686-mingw: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools + SCRIPT: python x.py dist + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z + MINGW_DIR: mingw32 + DIST_REQUIRE_ALL_TOOLS: 1 + DEPLOY: 1 + dist-x86_64-mingw: + MSYS_BITS: 64 + SCRIPT: python x.py dist + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z + MINGW_DIR: mingw64 + DIST_REQUIRE_ALL_TOOLS: 1 + DEPLOY: 1 - # "alternate" deployment, see .travis.yml for more info - dist-x86_64-msvc-alt: - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler - SCRIPT: python x.py dist - DEPLOY_ALT: 1 + # "alternate" deployment, see .travis.yml for more info + dist-x86_64-msvc-alt: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler + SCRIPT: python x.py dist + DEPLOY_ALT: 1 From a2255518c76f67d8993bebffb2b62903ef707d15 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 21 May 2019 11:01:39 -0700 Subject: [PATCH 0228/3207] Only run Window script on Windows --- .azure-pipelines/steps/install-windows-build-deps.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.azure-pipelines/steps/install-windows-build-deps.yml b/.azure-pipelines/steps/install-windows-build-deps.yml index 8bda290cd985..e54f7b6eb672 100644 --- a/.azure-pipelines/steps/install-windows-build-deps.yml +++ b/.azure-pipelines/steps/install-windows-build-deps.yml @@ -13,6 +13,8 @@ steps: mkdir c:\MORE_SPACE mklink /J build c:\MORE_SPACE ) + displayName: "Ensure build happens on C:/ instead of D:/" + condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) - script: | set MSYS_PATH=%CD%\citools\msys64 From 615c23f6ecc07e87501f2f52190e3fb08b50a17e Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 30 Mar 2019 21:49:52 +0000 Subject: [PATCH 0229/3207] Remove unused parameter from in(_opt)?_scope --- src/librustc_mir/build/block.rs | 12 ++++++------ src/librustc_mir/build/expr/as_operand.rs | 2 +- src/librustc_mir/build/expr/as_place.rs | 2 +- src/librustc_mir/build/expr/as_rvalue.rs | 2 +- src/librustc_mir/build/expr/as_temp.rs | 2 +- src/librustc_mir/build/expr/into.rs | 2 +- src/librustc_mir/build/expr/stmt.rs | 2 +- src/librustc_mir/build/mod.rs | 4 ++-- src/librustc_mir/build/scope.rs | 8 ++++---- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index 7469aceee3a9..d93223a4292c 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -23,8 +23,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { safety_mode } = self.hir.mirror(ast_block); - self.in_opt_scope(opt_destruction_scope.map(|de|(de, source_info)), block, move |this| { - this.in_scope((region_scope, source_info), LintLevel::Inherited, block, move |this| { + self.in_opt_scope(opt_destruction_scope.map(|de|(de, source_info)), move |this| { + this.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| { if targeted_by_break { // This is a `break`-able block let exit_block = this.cfg.start_new_block(); @@ -83,9 +83,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { StmtKind::Expr { scope, expr } => { this.block_context.push(BlockFrame::Statement { ignores_expr_result: true }); unpack!(block = this.in_opt_scope( - opt_destruction_scope.map(|de|(de, source_info)), block, |this| { + opt_destruction_scope.map(|de|(de, source_info)), |this| { let si = (scope, source_info); - this.in_scope(si, LintLevel::Inherited, block, |this| { + this.in_scope(si, LintLevel::Inherited, |this| { let expr = this.hir.mirror(expr); this.stmt_expr(block, expr, Some(stmt_span)) }) @@ -128,9 +128,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { Some((None, initializer_span)), ); unpack!(block = this.in_opt_scope( - opt_destruction_scope.map(|de|(de, source_info)), block, |this| { + opt_destruction_scope.map(|de|(de, source_info)), |this| { let scope = (init_scope, source_info); - this.in_scope(scope, lint_level, block, |this| { + this.in_scope(scope, lint_level, |this| { this.expr_into_pattern(block, pattern, init) }) })); diff --git a/src/librustc_mir/build/expr/as_operand.rs b/src/librustc_mir/build/expr/as_operand.rs index e354a2ee8160..ed80cb1a1636 100644 --- a/src/librustc_mir/build/expr/as_operand.rs +++ b/src/librustc_mir/build/expr/as_operand.rs @@ -57,7 +57,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { { let source_info = this.source_info(expr.span); let region_scope = (region_scope, source_info); - return this.in_scope(region_scope, lint_level, block, |this| { + return this.in_scope(region_scope, lint_level, |this| { this.as_operand(block, scope, value) }); } diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index 5f444d4ceeb8..a956eacb0699 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -52,7 +52,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { region_scope, lint_level, value, - } => this.in_scope((region_scope, source_info), lint_level, block, |this| { + } => this.in_scope((region_scope, source_info), lint_level, |this| { if mutability == Mutability::Not { this.as_read_only_place(block, value) } else { diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index fbc4835a6557..a0b504a99de9 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -58,7 +58,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { value, } => { let region_scope = (region_scope, source_info); - this.in_scope(region_scope, lint_level, block, |this| { + this.in_scope(region_scope, lint_level, |this| { this.as_rvalue(block, scope, value) }) } diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index cba771f27065..c60e19701006 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -43,7 +43,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { value, } = expr.kind { - return this.in_scope((region_scope, source_info), lint_level, block, |this| { + return this.in_scope((region_scope, source_info), lint_level, |this| { this.as_temp(block, temp_lifetime, value, mutability) }); } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 15795a64e3b7..7bdfdf0b0895 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -46,7 +46,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { value, } => { let region_scope = (region_scope, source_info); - this.in_scope(region_scope, lint_level, block, |this| { + this.in_scope(region_scope, lint_level, |this| { this.into(destination, block, value) }) } diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs index b58914b017fd..ac690f89264b 100644 --- a/src/librustc_mir/build/expr/stmt.rs +++ b/src/librustc_mir/build/expr/stmt.rs @@ -29,7 +29,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { value, } => { let value = this.hir.mirror(value); - this.in_scope((region_scope, source_info), lint_level, block, |this| { + this.in_scope((region_scope, source_info), lint_level, |this| { this.stmt_expr(block, value, opt_stmt_span) }) } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 16ab233bd2e3..b432ed47d0b8 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -702,13 +702,13 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let mut block = START_BLOCK; let source_info = builder.source_info(span); let call_site_s = (call_site_scope, source_info); - unpack!(block = builder.in_scope(call_site_s, LintLevel::Inherited, block, |builder| { + unpack!(block = builder.in_scope(call_site_s, LintLevel::Inherited, |builder| { if should_abort_on_panic(tcx, fn_def_id, abi) { builder.schedule_abort(); } let arg_scope_s = (arg_scope, source_info); - unpack!(block = builder.in_scope(arg_scope_s, LintLevel::Inherited, block, |builder| { + unpack!(block = builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| { builder.args_and_body(block, &arguments, arg_scope, &body.value) })); // Attribute epilogue to function's closing brace diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 4aa463b37ab7..471304012c9a 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -279,13 +279,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn in_opt_scope(&mut self, opt_scope: Option<(region::Scope, SourceInfo)>, - mut block: BasicBlock, f: F) -> BlockAnd where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) -> BlockAnd { - debug!("in_opt_scope(opt_scope={:?}, block={:?})", opt_scope, block); + debug!("in_opt_scope(opt_scope={:?})", opt_scope); if let Some(region_scope) = opt_scope { self.push_scope(region_scope); } + let mut block; let rv = unpack!(block = f(self)); if let Some(region_scope) = opt_scope { unpack!(block = self.pop_scope(region_scope, block)); @@ -299,12 +299,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn in_scope(&mut self, region_scope: (region::Scope, SourceInfo), lint_level: LintLevel, - mut block: BasicBlock, f: F) -> BlockAnd where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) -> BlockAnd { - debug!("in_scope(region_scope={:?}, block={:?})", region_scope, block); + debug!("in_scope(region_scope={:?})", region_scope); let source_scope = self.source_scope; let tcx = self.hir.tcx(); if let LintLevel::Explicit(current_hir_id) = lint_level { @@ -330,6 +329,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } } self.push_scope(region_scope); + let mut block; let rv = unpack!(block = f(self)); unpack!(block = self.pop_scope(region_scope, block)); self.source_scope = source_scope; From 4bfb0453f537b2927574f29bdf90c9a22ea98add Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 30 Mar 2019 22:54:29 +0000 Subject: [PATCH 0230/3207] Give match arms an HirId and a Span --- src/librustc/hir/intravisit.rs | 1 + src/librustc/hir/lowering.rs | 8 ++++++++ src/librustc/hir/map/collector.rs | 10 ++++++++++ src/librustc/hir/map/mod.rs | 7 +++++++ src/librustc/hir/mod.rs | 4 ++++ src/librustc/hir/print.rs | 2 +- src/librustc_passes/hir_stats.rs | 2 +- src/librustc_typeck/check/_match.rs | 15 +++++++++------ src/libsyntax/ast.rs | 1 + src/libsyntax/ext/build.rs | 3 ++- src/libsyntax/mut_visit.rs | 6 +++++- src/libsyntax/parse/parser.rs | 4 ++++ 12 files changed, 53 insertions(+), 10 deletions(-) diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 38d6d710868c..517c99f99efe 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -1102,6 +1102,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { } pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) { + visitor.visit_id(arm.hir_id); walk_list!(visitor, visit_pat, &arm.pats); if let Some(ref g) = arm.guard { match g { diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 3ec4d4e8cc8f..8dba7491bf50 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1313,7 +1313,10 @@ impl<'a> LoweringContext<'a> { } fn lower_arm(&mut self, arm: &Arm) -> hir::Arm { + let LoweredNodeId { node_id: _, hir_id } = self.next_id(); + hir::Arm { + hir_id, attrs: self.lower_attrs(&arm.attrs), pats: arm.pats.iter().map(|x| self.lower_pat(x)).collect(), guard: match arm.guard { @@ -1321,6 +1324,7 @@ impl<'a> LoweringContext<'a> { _ => None, }, body: P(self.lower_expr(&arm.body)), + span: arm.span, } } @@ -5023,10 +5027,14 @@ impl<'a> LoweringContext<'a> { // Helper methods for building HIR. fn arm(&mut self, pats: hir::HirVec>, expr: P) -> hir::Arm { + let LoweredNodeId { node_id: _, hir_id } = self.next_id(); + hir::Arm { + hir_id, attrs: hir_vec![], pats, guard: None, + span: expr.span, body: expr, } } diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index eeba628b3bf2..b5203f9ec1f7 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -430,6 +430,16 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } + fn visit_arm(&mut self, arm: &'hir Arm) { + let node = Node::Arm(arm); + + self.insert(arm.span, arm.hir_id, node); + + self.with_parent(arm.hir_id, |this| { + intravisit::walk_arm(this, arm); + }); + } + fn visit_anon_const(&mut self, constant: &'hir AnonConst) { self.insert(DUMMY_SP, constant.hir_id, Node::AnonConst(constant)); diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 4b94f772554e..d8fe90d40481 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -373,6 +373,7 @@ impl<'hir> Map<'hir> { Node::Pat(_) | Node::Binding(_) | Node::Local(_) | + Node::Arm(_) | Node::Lifetime(_) | Node::Visibility(_) | Node::Block(_) | @@ -1000,6 +1001,7 @@ impl<'hir> Map<'hir> { Some(Node::Field(ref f)) => Some(&f.attrs[..]), Some(Node::Expr(ref e)) => Some(&*e.attrs), Some(Node::Stmt(ref s)) => Some(s.node.attrs()), + Some(Node::Arm(ref a)) => Some(&*a.attrs), Some(Node::GenericParam(param)) => Some(¶m.attrs[..]), // Unit/tuple structs/variants take the attributes straight from // the struct/variant definition. @@ -1073,6 +1075,7 @@ impl<'hir> Map<'hir> { Some(Node::TraitRef(tr)) => tr.path.span, Some(Node::Binding(pat)) => pat.span, Some(Node::Pat(pat)) => pat.span, + Some(Node::Arm(arm)) => arm.span, Some(Node::Block(block)) => block.span, Some(Node::Ctor(..)) => match self.find_by_hir_id( self.get_parent_node_by_hir_id(hir_id)) @@ -1288,6 +1291,7 @@ impl<'a> print::State<'a> { Node::TraitRef(a) => self.print_trait_ref(&a), Node::Binding(a) | Node::Pat(a) => self.print_pat(&a), + Node::Arm(a) => self.print_arm(&a), Node::Block(a) => { use syntax::print::pprust::PrintState; @@ -1417,6 +1421,9 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { Some(Node::Pat(_)) => { format!("pat {}{}", map.hir_to_pretty_string(id), id_str) } + Some(Node::Arm(_)) => { + format!("arm {}{}", map.hir_to_pretty_string(id), id_str) + } Some(Node::Block(_)) => { format!("block {}{}", map.hir_to_pretty_string(id), id_str) } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 57304c5ed37a..08feea3ccce4 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1228,6 +1228,9 @@ pub struct Local { /// ` (if ) => `. #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct Arm { + #[stable_hasher(ignore)] + pub hir_id: HirId, + pub span: Span, pub attrs: HirVec, /// Multiple patterns can be combined with `|` pub pats: HirVec>, @@ -2656,6 +2659,7 @@ pub enum Node<'hir> { TraitRef(&'hir TraitRef), Binding(&'hir Pat), Pat(&'hir Pat), + Arm(&'hir Arm), Block(&'hir Block), Local(&'hir Local), MacroDef(&'hir MacroDef), diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 8a9028e54439..ef9fee5cab69 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1862,7 +1862,7 @@ impl<'a> State<'a> { self.ann.post(self, AnnNode::Pat(pat)) } - fn print_arm(&mut self, arm: &hir::Arm) -> io::Result<()> { + pub fn print_arm(&mut self, arm: &hir::Arm) -> io::Result<()> { // I have no idea why this check is necessary, but here it // is :( if arm.attrs.is_empty() { diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs index c74314ce0c4b..0088c97679c6 100644 --- a/src/librustc_passes/hir_stats.rs +++ b/src/librustc_passes/hir_stats.rs @@ -149,7 +149,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { } fn visit_arm(&mut self, a: &'v hir::Arm) { - self.record("Arm", Id::None, a); + self.record("Arm", Id::Node(a.hir_id), a); hir_visit::walk_arm(self, a) } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index a69f639e8941..99b350b83327 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -781,14 +781,17 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); fn maybe_get_coercion_reason(&self, hir_id: hir::HirId, span: Span) -> Option<(Span, String)> { use hir::Node::{Block, Item, Local}; - let node = self.tcx.hir().get_by_hir_id(self.tcx.hir().get_parent_node_by_hir_id( - self.tcx.hir().get_parent_node_by_hir_id(hir_id), - )); + let hir = self.tcx.hir(); + let arm_id = hir.get_parent_node_by_hir_id(hir_id); + let match_id = hir.get_parent_node_by_hir_id(arm_id); + let containing_id = hir.get_parent_node_by_hir_id(match_id); + + let node = hir.get_by_hir_id(containing_id); if let Block(block) = node { // check that the body's parent is an fn - let parent = self.tcx.hir().get_by_hir_id( - self.tcx.hir().get_parent_node_by_hir_id( - self.tcx.hir().get_parent_node_by_hir_id(block.hir_id), + let parent = hir.get_by_hir_id( + hir.get_parent_node_by_hir_id( + hir.get_parent_node_by_hir_id(block.hir_id), ), ); if let (Some(expr), Item(hir::Item { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a6bb47bef87e..e2c2c46abf6b 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -908,6 +908,7 @@ pub struct Arm { pub pats: Vec>, pub guard: Option, pub body: P, + pub span: Span, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index d24106f697e1..cb967a76822c 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -890,12 +890,13 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.pat_tuple_struct(span, path, vec![pat]) } - fn arm(&self, _span: Span, pats: Vec>, expr: P) -> ast::Arm { + fn arm(&self, span: Span, pats: Vec>, expr: P) -> ast::Arm { ast::Arm { attrs: vec![], pats, guard: None, body: expr, + span, } } diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index f587e63e12b9..cb21014ec764 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -392,11 +392,15 @@ pub fn noop_visit_use_tree(use_tree: &mut UseTree, vis: &mut T) { vis.visit_span(span); } -pub fn noop_visit_arm(Arm { attrs, pats, guard, body }: &mut Arm, vis: &mut T) { +pub fn noop_visit_arm( + Arm { attrs, pats, guard, body, span }: &mut Arm, + vis: &mut T, +) { visit_attrs(attrs, vis); visit_vec(pats, |pat| vis.visit_pat(pat)); visit_opt(guard, |guard| vis.visit_guard(guard)); vis.visit_expr(body); + vis.visit_span(span); } pub fn noop_visit_guard(g: &mut Guard, vis: &mut T) { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 24d120376def..ba36783e11e9 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3946,6 +3946,7 @@ impl<'a> Parser<'a> { crate fn parse_arm(&mut self) -> PResult<'a, Arm> { let attrs = self.parse_outer_attributes()?; + let lo = self.span; let pats = self.parse_pats()?; let guard = if self.eat_keyword(keywords::If) { Some(Guard::If(self.parse_expr()?)) @@ -3965,6 +3966,8 @@ impl<'a> Parser<'a> { let require_comma = classify::expr_requires_semi_to_be_stmt(&expr) && self.token != token::CloseDelim(token::Brace); + let hi = self.span; + if require_comma { let cm = self.sess.source_map(); self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Brace)]) @@ -4008,6 +4011,7 @@ impl<'a> Parser<'a> { pats, guard, body: expr, + span: lo.to(hi), }) } From e784595c280da04c98e76a5ce9d603b58f6a88e2 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 30 Mar 2019 23:00:07 +0000 Subject: [PATCH 0231/3207] Respect lint attributes on match arms --- src/librustc/lint/mod.rs | 6 ++++++ src/test/ui/lint/lint-match-arms.rs | 18 ++++++++++++++++++ src/test/ui/lint/lint-match-arms.stderr | 14 ++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 src/test/ui/lint/lint-match-arms.rs create mode 100644 src/test/ui/lint/lint-match-arms.stderr diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 9c4683e09463..512e4d434434 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -852,6 +852,12 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'a, 'tcx> { }) } + fn visit_arm(&mut self, a: &'tcx hir::Arm) { + self.with_lint_attrs(a.hir_id, &a.attrs, |builder| { + intravisit::walk_arm(builder, a); + }) + } + fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { self.with_lint_attrs(trait_item.hir_id, &trait_item.attrs, |builder| { intravisit::walk_trait_item(builder, trait_item); diff --git a/src/test/ui/lint/lint-match-arms.rs b/src/test/ui/lint/lint-match-arms.rs new file mode 100644 index 000000000000..2c471a61054b --- /dev/null +++ b/src/test/ui/lint/lint-match-arms.rs @@ -0,0 +1,18 @@ +fn deny_on_arm() { + match 0 { + #[deny(unused_variables)] + //~^ NOTE lint level defined here + y => (), + //~^ ERROR unused variable + } +} + +#[deny(unused_variables)] +fn allow_on_arm() { + match 0 { + #[allow(unused_variables)] + y => (), // OK + } +} + +fn main() {} diff --git a/src/test/ui/lint/lint-match-arms.stderr b/src/test/ui/lint/lint-match-arms.stderr new file mode 100644 index 000000000000..e4e3adab0a9b --- /dev/null +++ b/src/test/ui/lint/lint-match-arms.stderr @@ -0,0 +1,14 @@ +error: unused variable: `y` + --> $DIR/lint-match-arms.rs:5:9 + | +LL | y => (), + | ^ help: consider prefixing with an underscore: `_y` + | +note: lint level defined here + --> $DIR/lint-match-arms.rs:3:16 + | +LL | #[deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + From af6a9a2c62ba2e7fe54f53884b94fcd2f9a9265b Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Tue, 2 Apr 2019 22:29:28 +0100 Subject: [PATCH 0232/3207] Handle the visibility/lint scope distinction better * Don't generate an extra lint scope for each `let` statement. * Place match guards inside the visiblility scope of the bindings for their arm. --- src/librustc/hir/lowering.rs | 8 ++--- src/librustc_mir/build/block.rs | 36 +++++++++++-------- src/librustc_mir/build/matches/mod.rs | 27 ++++---------- src/librustc_mir/build/mod.rs | 11 +++--- src/librustc_mir/hair/mod.rs | 11 ++---- src/test/mir-opt/box_expr.rs | 4 +-- src/test/mir-opt/issue-41110.rs | 7 ++-- src/test/mir-opt/issue-49232.rs | 4 +-- .../mir-opt/packed-struct-drop-aligned.rs | 4 +-- 9 files changed, 45 insertions(+), 67 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 8dba7491bf50..591f713f81f7 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1313,10 +1313,8 @@ impl<'a> LoweringContext<'a> { } fn lower_arm(&mut self, arm: &Arm) -> hir::Arm { - let LoweredNodeId { node_id: _, hir_id } = self.next_id(); - hir::Arm { - hir_id, + hir_id: self.next_id(), attrs: self.lower_attrs(&arm.attrs), pats: arm.pats.iter().map(|x| self.lower_pat(x)).collect(), guard: match arm.guard { @@ -5027,10 +5025,8 @@ impl<'a> LoweringContext<'a> { // Helper methods for building HIR. fn arm(&mut self, pats: hir::HirVec>, expr: P) -> hir::Arm { - let LoweredNodeId { node_id: _, hir_id } = self.next_id(); - hir::Arm { - hir_id, + hir_id: self.next_id(), attrs: hir_vec![], pats, guard: None, diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index d93223a4292c..b5bab1585342 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -113,31 +113,39 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let remainder_span = remainder_scope.span(this.hir.tcx(), &this.hir.region_scope_tree); - let scope; + let visibility_scope = + Some(this.new_source_scope(remainder_span, LintLevel::Inherited, None)); // Evaluate the initializer, if present. if let Some(init) = initializer { let initializer_span = init.span(); - scope = this.declare_bindings( - None, - remainder_span, - lint_level, - &pattern, - ArmHasGuard(false), - Some((None, initializer_span)), - ); unpack!(block = this.in_opt_scope( opt_destruction_scope.map(|de|(de, source_info)), |this| { let scope = (init_scope, source_info); this.in_scope(scope, lint_level, |this| { + this.declare_bindings( + visibility_scope, + remainder_span, + &pattern, + ArmHasGuard(false), + Some((None, initializer_span)), + ); this.expr_into_pattern(block, pattern, init) }) })); } else { - scope = this.declare_bindings( - None, remainder_span, lint_level, &pattern, - ArmHasGuard(false), None); + let scope = (init_scope, source_info); + unpack!(this.in_scope(scope, lint_level, |this| { + this.declare_bindings( + visibility_scope, + remainder_span, + &pattern, + ArmHasGuard(false), + None, + ); + block.unit() + })); debug!("ast_block_stmts: pattern={:?}", pattern); this.visit_bindings( @@ -149,8 +157,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }) } - // Enter the source scope, after evaluating the initializer. - if let Some(source_scope) = scope { + // Enter the visibility scope, after evaluating the initializer. + if let Some(source_scope) = visibility_scope { this.source_scope = source_scope; } } diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 51d5c96083d8..93a702dc44e2 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -259,12 +259,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let scope = self.declare_bindings( None, body.span, - LintLevel::Inherited, &arm.patterns[0], ArmHasGuard(arm.guard.is_some()), Some((Some(&scrutinee_place), scrutinee_span)), ); + if let Some(source_scope) = scope { + this.source_scope = source_scope; + } + for candidate in candidates { self.bind_and_guard_matched_candidate( candidate, @@ -275,9 +278,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ); } - if let Some(source_scope) = scope { - self.source_scope = source_scope; - } unpack!(arm_block = self.into(destination, arm_block, body)); @@ -489,33 +489,20 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { &mut self, mut visibility_scope: Option, scope_span: Span, - lint_level: LintLevel, pattern: &Pattern<'tcx>, has_guard: ArmHasGuard, opt_match_place: Option<(Option<&Place<'tcx>>, Span)>, ) -> Option { - assert!( - !(visibility_scope.is_some() && lint_level.is_explicit()), - "can't have both a visibility and a lint scope at the same time" - ); - let mut scope = self.source_scope; debug!("declare_bindings: pattern={:?}", pattern); self.visit_bindings( &pattern, UserTypeProjections::none(), &mut |this, mutability, name, mode, var, span, ty, user_ty| { if visibility_scope.is_none() { - // If we have lints, create a new source scope - // that marks the lints for the locals. See the comment - // on the `source_info` field for why this is needed. - if lint_level.is_explicit() { - scope = this.new_source_scope(scope_span, lint_level, None); - } - visibility_scope = Some(this.new_source_scope(scope_span, - LintLevel::Inherited, - None)); + visibility_scope = + Some(this.new_source_scope(scope_span, LintLevel::Inherited, None)); } - let source_info = SourceInfo { span, scope }; + let source_info = SourceInfo { span, this.source_scope }; let visibility_scope = visibility_scope.unwrap(); this.declare_binding( source_info, diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index b432ed47d0b8..8cd4ac0ad3ad 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -945,10 +945,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { self.var_indices.insert(var, LocalsForNode::One(local)); } _ => { - scope = self.declare_bindings(scope, ast_body.span, - LintLevel::Inherited, &pattern, - matches::ArmHasGuard(false), - Some((Some(&place), span))); + scope = self.declare_bindings( + scope, + ast_body.span, + &pattern, + matches::ArmHasGuard(false), + Some((Some(&place), span)), + ); unpack!(block = self.place_into_pattern(block, pattern, &place, false)); } } diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index d4f139e103a6..8e19913f4df2 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -31,15 +31,6 @@ pub enum LintLevel { Explicit(hir::HirId) } -impl LintLevel { - pub fn is_explicit(self) -> bool { - match self { - LintLevel::Inherited => false, - LintLevel::Explicit(_) => true - } - } -} - #[derive(Clone, Debug)] pub struct Block<'tcx> { pub targeted_by_break: bool, @@ -311,6 +302,8 @@ pub struct Arm<'tcx> { pub guard: Option>, pub body: ExprRef<'tcx>, pub lint_level: LintLevel, + pub scope: region::Scope, + pub span: Span, } #[derive(Clone, Debug)] diff --git a/src/test/mir-opt/box_expr.rs b/src/test/mir-opt/box_expr.rs index d4852db6d475..ee6adfefe3e3 100644 --- a/src/test/mir-opt/box_expr.rs +++ b/src/test/mir-opt/box_expr.rs @@ -22,13 +22,11 @@ impl Drop for S { // END RUST SOURCE // START rustc.main.ElaborateDrops.before.mir // let mut _0: (); +// let _1: std::boxed::Box; // let mut _2: std::boxed::Box; // let mut _3: (); // let mut _4: std::boxed::Box; // scope 1 { -// let _1: std::boxed::Box; -// } -// scope 2 { // } // bb0: { // StorageLive(_1); diff --git a/src/test/mir-opt/issue-41110.rs b/src/test/mir-opt/issue-41110.rs index 023440af0eb1..0b678be2ab31 100644 --- a/src/test/mir-opt/issue-41110.rs +++ b/src/test/mir-opt/issue-41110.rs @@ -29,27 +29,24 @@ impl S { // END RUST SOURCE // START rustc.main.ElaborateDrops.after.mir // let mut _0: (); +// let _1: (); // let mut _2: S; // let mut _3: S; // let mut _4: S; // let mut _5: bool; // scope 1 { -// let _1: (); -// } -// scope 2 { // } // ... // bb0: { // END rustc.main.ElaborateDrops.after.mir // START rustc.test.ElaborateDrops.after.mir // let mut _0: (); +// let _1: S; // let mut _3: (); // let mut _4: S; // let mut _5: S; // let mut _6: bool; // ... -// let _1: S; -// ... // let mut _2: S; // ... // bb0: { diff --git a/src/test/mir-opt/issue-49232.rs b/src/test/mir-opt/issue-49232.rs index 29446d2ecc23..3910183dee78 100644 --- a/src/test/mir-opt/issue-49232.rs +++ b/src/test/mir-opt/issue-49232.rs @@ -18,14 +18,12 @@ fn main() { // fn main() -> (){ // let mut _0: (); // let mut _1: (); +// let _2: i32; // let mut _3: bool; // let mut _4: !; // let mut _5: (); // let mut _6: &i32; // scope 1 { -// let _2: i32; -// } -// scope 2 { // } // bb0: { // goto -> bb1; diff --git a/src/test/mir-opt/packed-struct-drop-aligned.rs b/src/test/mir-opt/packed-struct-drop-aligned.rs index 7e8c58e64c28..da73cc96348f 100644 --- a/src/test/mir-opt/packed-struct-drop-aligned.rs +++ b/src/test/mir-opt/packed-struct-drop-aligned.rs @@ -18,15 +18,13 @@ impl Drop for Droppy { // START rustc.main.EraseRegions.before.mir // fn main() -> () { // let mut _0: (); +// let mut _1: Packed; // let mut _2: Aligned; // let mut _3: Droppy; // let mut _4: Aligned; // let mut _5: Droppy; // let mut _6: Aligned; // scope 1 { -// let mut _1: Packed; -// } -// scope 2 { // } // // bb0: { From f506aea1fac0977c7215b4240f4d99b45bf7ae97 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 3 Apr 2019 19:21:51 +0100 Subject: [PATCH 0233/3207] Give match arms a drop/region scope Also give arms the correct lint scope in MIR. --- src/librustc/cfg/construct.rs | 10 +- src/librustc/middle/region.rs | 34 +++-- src/librustc_mir/build/matches/mod.rs | 85 ++++++++---- src/librustc_mir/build/scope.rs | 84 +++++++++++- src/librustc_mir/hair/cx/expr.rs | 8 +- src/test/mir-opt/match_false_edges.rs | 126 +++++++++++------- src/test/mir-opt/match_test.rs | 37 ++--- src/test/mir-opt/remove_fake_borrows.rs | 50 +++---- src/test/ui/lint/lint-unused-mut-variables.rs | 8 ++ .../ui/lint/lint-unused-mut-variables.stderr | 4 +- 10 files changed, 300 insertions(+), 146 deletions(-) diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 2e54165be1f1..ef0d4be268ea 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -419,7 +419,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { for arm in arms { // Add an exit node for when we've visited all the // patterns and the guard (if there is one) in the arm. - let arm_exit = self.add_dummy_node(&[]); + let bindings_exit = self.add_dummy_node(&[]); for pat in &arm.pats { // Visit the pattern, coming from the discriminant exit @@ -453,14 +453,16 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // Add an edge from the exit of this pattern to the // exit of the arm - self.add_contained_edge(pat_exit, arm_exit); + self.add_contained_edge(pat_exit, bindings_exit); } // Visit the body of this arm - let body_exit = self.expr(&arm.body, arm_exit); + let body_exit = self.expr(&arm.body, bindings_exit); + + let arm_exit = self.add_ast_node(arm.hir_id.local_id, &[body_exit]); // Link the body to the exit of the expression - self.add_contained_edge(body_exit, expr_exit); + self.add_contained_edge(arm_exit, expr_exit); } expr_exit diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 37681ad7fcdd..fa4e8e3d4769 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -119,18 +119,18 @@ impl fmt::Debug for Scope { pub enum ScopeData { Node, - // Scope of the call-site for a function or closure - // (outlives the arguments as well as the body). + /// Scope of the call-site for a function or closure + /// (outlives the arguments as well as the body). CallSite, - // Scope of arguments passed to a function or closure - // (they outlive its body). + /// Scope of arguments passed to a function or closure + /// (they outlive its body). Arguments, - // Scope of destructors for temporaries of node-id. + /// Scope of destructors for temporaries of node-id. Destruction, - // Scope following a `let id = expr;` binding in a block. + /// Scope following a `let id = expr;` binding in a block. Remainder(FirstStatementIndex) } @@ -152,11 +152,11 @@ newtype_index! { /// /// * The subscope with `first_statement_index == 1` is scope of `c`, /// and thus does not include EXPR_2, but covers the `...`. - pub struct FirstStatementIndex { .. } + pub struct FirstStatementIndex { + derive [HashStable] + } } -impl_stable_hash_for!(struct crate::middle::region::FirstStatementIndex { private }); - // compilation error if size of `ScopeData` is not the same as a `u32` static_assert_size!(ScopeData, 4); @@ -814,6 +814,16 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk: } fn resolve_arm<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, arm: &'tcx hir::Arm) { + let prev_cx = visitor.cx; + + visitor.enter_scope( + Scope { + id: arm.hir_id.local_id, + data: ScopeData::Node, + } + ); + visitor.cx.var_parent = visitor.cx.parent; + visitor.terminating_scopes.insert(arm.body.hir_id.local_id); if let Some(hir::Guard::If(ref expr)) = arm.guard { @@ -821,6 +831,8 @@ fn resolve_arm<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, arm: & } intravisit::walk_arm(visitor, arm); + + visitor.cx = prev_cx; } fn resolve_pat<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, pat: &'tcx hir::Pat) { @@ -893,10 +905,6 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: terminating(body.hir_id.local_id); } - hir::ExprKind::Match(..) => { - visitor.cx.var_parent = visitor.cx.parent; - } - hir::ExprKind::DropTemps(ref expr) => { // `DropTemps(expr)` does not denote a conditional scope. // Rather, we want to achieve the same behavior as `{ let _t = expr; _t }`. diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 93a702dc44e2..091e39630d6c 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -12,6 +12,7 @@ use crate::build::{GuardFrame, GuardFrameLocal, LocalsForNode}; use crate::hair::{self, *}; use rustc::hir::HirId; use rustc::mir::*; +use rustc::middle::region; use rustc::ty::{self, CanonicalUserTypeAnnotation, Ty}; use rustc::ty::layout::VariantIdx; use rustc_data_structures::bit_set::BitSet; @@ -251,37 +252,39 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Step 5. Create everything else: the guards and the arms. - let outer_source_info = self.source_info(span); let arm_end_blocks: Vec<_> = arm_candidates.into_iter().map(|(arm, candidates)| { - let mut arm_block = self.cfg.start_new_block(); + let arm_source_info = self.source_info(arm.span); + let region_scope = (arm.scope, arm_source_info); + self.in_scope(region_scope, arm.lint_level, |this| { + let arm_block = this.cfg.start_new_block(); - let body = self.hir.mirror(arm.body.clone()); - let scope = self.declare_bindings( - None, - body.span, - &arm.patterns[0], - ArmHasGuard(arm.guard.is_some()), - Some((Some(&scrutinee_place), scrutinee_span)), - ); - - if let Some(source_scope) = scope { - this.source_scope = source_scope; - } - - for candidate in candidates { - self.bind_and_guard_matched_candidate( - candidate, - arm.guard.clone(), - arm_block, - &fake_borrow_temps, - scrutinee_span, + let body = this.hir.mirror(arm.body.clone()); + let scope = this.declare_bindings( + None, + arm.span, + &arm.patterns[0], + ArmHasGuard(arm.guard.is_some()), + Some((Some(&scrutinee_place), scrutinee_span)), ); - } + if let Some(source_scope) = scope { + this.source_scope = source_scope; + } - unpack!(arm_block = self.into(destination, arm_block, body)); + for candidate in candidates { + this.clear_top_scope(arm.scope); + this.bind_and_guard_matched_candidate( + candidate, + arm.guard.clone(), + arm_block, + &fake_borrow_temps, + scrutinee_span, + region_scope, + ); + } - arm_block + this.into(destination, arm_block, body) + }) }).collect(); // all the arm blocks will rejoin here @@ -289,7 +292,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { for arm_block in arm_end_blocks { self.cfg.terminate( - arm_block, + unpack!(arm_block), outer_source_info, TerminatorKind::Goto { target: end_block }, ); @@ -502,7 +505,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { visibility_scope = Some(this.new_source_scope(scope_span, LintLevel::Inherited, None)); } - let source_info = SourceInfo { span, this.source_scope }; + let source_info = SourceInfo { span, scope: this.source_scope }; let visibility_scope = visibility_scope.unwrap(); this.declare_binding( source_info, @@ -1315,6 +1318,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { arm_block: BasicBlock, fake_borrows: &Vec<(&Place<'tcx>, Local)>, scrutinee_span: Span, + region_scope: (region::Scope, SourceInfo), ) { debug!("bind_and_guard_matched_candidate(candidate={:?})", candidate); @@ -1497,17 +1501,40 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // // and that is clearly not correct. let post_guard_block = self.cfg.start_new_block(); + let otherwise_post_guard_block = self.cfg.start_new_block(); self.cfg.terminate( block, source_info, TerminatorKind::if_( self.hir.tcx(), - cond, + cond.clone(), post_guard_block, - candidate.otherwise_block.unwrap() + otherwise_post_guard_block, ), ); + self.exit_scope( + source_info.span, + region_scope, + otherwise_post_guard_block, + candidate.otherwise_block.unwrap(), + ); + + if let Operand::Copy(cond_place) | Operand::Move(cond_place) = cond { + if let Place::Base(PlaceBase::Local(cond_temp)) = cond_place { + // We will call `clear_top_scope` if there's another guard. So + // we have to drop this variable now or it will be "storage + // leaked". + self.pop_variable( + post_guard_block, + region_scope.0, + cond_temp + ); + } else { + bug!("Expected as_local_operand to produce a temporary"); + } + } + let by_value_bindings = candidate.bindings.iter().filter(|binding| { if let BindingMode::ByValue = binding.binding_mode { true } else { false } }); diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 471304012c9a..0d1d40a8af63 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -19,13 +19,18 @@ paragraph). This is because region scopes are tied to them. Eventually, when we shift to non-lexical lifetimes, there should be no need to remember this mapping. -There is one additional wrinkle, actually, that I wanted to hide from -you but duty compels me to mention. In the course of building -matches, it sometimes happen that certain code (namely guards) gets -executed multiple times. This means that the scope lexical scope may -in fact correspond to multiple, disjoint SEME regions. So in fact our +### Not so SEME Regions + +In the course of building matches, it sometimes happens that certain code +(namely guards) gets executed multiple times. This means that the scope lexical +scope may in fact correspond to multiple, disjoint SEME regions. So in fact our mapping is from one scope to a vector of SEME regions. +Also in matches, the scopes assigned to arms are not even SEME regions! Each +arm has a single region with one entry for each pattern. We manually +manipulate the scheduled drops in this scope to avoid dropping things multiple +times, although drop elaboration would clean this up for value drops. + ### Drops The primary purpose for scopes is to insert drops: while building @@ -731,7 +736,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Note that this code iterates scopes from the inner-most to the outer-most, // invalidating caches of each scope visited. This way bare minimum of the // caches gets invalidated. i.e., if a new drop is added into the middle scope, the - // cache of outer scpoe stays intact. + // cache of outer scope stays intact. scope.invalidate_cache(!needs_drop, this_scope); if this_scope { if let DropKind::Value { .. } = drop_kind { @@ -873,6 +878,73 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { success_block } + + // `match` arm scopes + // ================== + /// Unschedules any drops in the top scope. + /// + /// This is only needed for `match` arm scopes, because they have one + /// entrance per pattern, but only one exit. + pub fn clear_top_scope(&mut self, region_scope: region::Scope) { + let top_scope = self.scopes.last_mut().unwrap(); + + assert_eq!(top_scope.region_scope, region_scope); + + top_scope.drops.clear(); + top_scope.invalidate_cache(false, true); + } + + /// Drops the single variable provided + /// + /// * The scope must be the top scope. + /// * The variable must be in that scope. + /// * The variable must be at the top of that scope: it's the next thing + /// scheduled to drop. + /// * The drop must be of DropKind::Storage. + /// + /// This is used for the boolean holding the result of the match guard. We + /// do this because: + /// + /// * The boolean is different for each pattern + /// * There is only one exit for the arm scope + /// * The guard expression scope is too short, it ends just before the + /// boolean is tested. + pub fn pop_variable( + &mut self, + block: BasicBlock, + region_scope: region::Scope, + variable: Local, + ) { + let top_scope = self.scopes.last_mut().unwrap(); + + assert_eq!(top_scope.region_scope, region_scope); + + let top_drop_data = top_scope.drops.pop().unwrap(); + + match top_drop_data.kind { + DropKind::Value { .. } => { + bug!("Should not be calling pop_top_variable on non-copy type!") + } + DropKind::Storage => { + // Drop the storage for both value and storage drops. + // Only temps and vars need their storage dead. + match top_drop_data.location { + Place::Base(PlaceBase::Local(index)) => { + let source_info = top_scope.source_info(top_drop_data.span); + assert_eq!(index, variable); + self.cfg.push(block, Statement { + source_info, + kind: StatementKind::StorageDead(index) + }); + } + _ => unreachable!(), + } + } + } + + top_scope.invalidate_cache(true, true); + } + } /// Builds drops for pop_scope and exit_scope. diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 50140880a368..d623f149988c 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -879,8 +879,12 @@ fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, arm: &'tcx hir::Arm) _ => None, }, body: arm.body.to_ref(), - // BUG: fix this - lint_level: LintLevel::Inherited, + lint_level: LintLevel::Explicit(arm.hir_id), + scope: region::Scope { + id: arm.hir_id.local_id, + data: region::ScopeData::Node + }, + span: arm.span, } } diff --git a/src/test/mir-opt/match_false_edges.rs b/src/test/mir-opt/match_false_edges.rs index 7ac36a22274f..0850c552536c 100644 --- a/src/test/mir-opt/match_false_edges.rs +++ b/src/test/mir-opt/match_false_edges.rs @@ -45,13 +45,13 @@ fn main() { // _2 = std::option::Option::::Some(const 42i32,); // FakeRead(ForMatchedPlace, _2); // _3 = discriminant(_2); -// switchInt(move _3) -> [0isize: bb4, 1isize: bb2, otherwise: bb7]; +// switchInt(move _3) -> [0isize: bb4, 1isize: bb2, otherwise: bb6]; // } // bb1 (cleanup): { // resume; // } // bb2: { -// falseEdges -> [real: bb8, imaginary: bb3]; //pre_binding1 +// falseEdges -> [real: bb7, imaginary: bb3]; //pre_binding1 // } // bb3: { // falseEdges -> [real: bb11, imaginary: bb4]; //pre_binding2 @@ -62,48 +62,56 @@ fn main() { // bb5: { // unreachable; // } -// bb6: { // to pre_binding2 -// falseEdges -> [real: bb3, imaginary: bb3]; -// } -// bb7: { +// bb6: { // unreachable; // } -// bb8: { // binding1 and guard +// bb7: { // binding1 and guard // StorageLive(_6); // _6 = &(((promoted[0]: std::option::Option) as Some).0: i32); // _4 = &shallow _2; // StorageLive(_7); -// _7 = const guard() -> [return: bb9, unwind: bb1]; +// _7 = const guard() -> [return: bb8, unwind: bb1]; // } -// bb9: { +// bb8: { // end of guard // FakeRead(ForMatchGuard, _4); // FakeRead(ForGuardBinding, _6); -// switchInt(move _7) -> [false: bb6, otherwise: bb10]; +// switchInt(move _7) -> [false: bb10, otherwise: bb9]; // } -// bb10: { +// bb9: { // arm1 +// StorageDead(_7); // StorageLive(_5); // _5 = ((_2 as Some).0: i32); // StorageLive(_8); // _8 = _5; // _1 = (const 1i32, move _8); // StorageDead(_8); +// StorageDead(_5); +// StorageDead(_6); // goto -> bb13; // } -// bb11: { +// bb10: { // to pre_binding2 +// StorageDead(_7); +// StorageDead(_6); +// falseEdges -> [real: bb3, imaginary: bb3]; +// } +// bb11: { // arm2 // StorageLive(_9); // _9 = ((_2 as Some).0: i32); // StorageLive(_10); // _10 = _9; // _1 = (const 2i32, move _10); // StorageDead(_10); +// StorageDead(_9); // goto -> bb13; // } -// bb12: { +// bb12: { // arm3 // _1 = (const 3i32, const 3i32); // goto -> bb13; // } // bb13: { -// ... +// StorageDead(_1); +// StorageDead(_2); +// _0 = (); // return; // } // END rustc.full_tested_match.QualifyAndPromoteConstants.after.mir @@ -114,13 +122,13 @@ fn main() { // _2 = std::option::Option::::Some(const 42i32,); // FakeRead(ForMatchedPlace, _2); // _3 = discriminant(_2); -// switchInt(move _3) -> [0isize: bb3, 1isize: bb2, otherwise: bb7]; +// switchInt(move _3) -> [0isize: bb3, 1isize: bb2, otherwise: bb6]; // } // bb1 (cleanup): { // resume; // } // bb2: { -// falseEdges -> [real: bb8, imaginary: bb3]; +// falseEdges -> [real: bb7, imaginary: bb3]; // } // bb3: { // falseEdges -> [real: bb11, imaginary: bb4]; @@ -131,33 +139,38 @@ fn main() { // bb5: { // unreachable; // } -// bb6: { // to pre_binding3 (can skip 2 since this is `Some`) -// falseEdges -> [real: bb4, imaginary: bb3]; -// } -// bb7: { +// bb6: { // unreachable; // } -// bb8: { // binding1 and guard +// bb7: { // binding1 and guard // StorageLive(_6); // _6 = &((_2 as Some).0: i32); // _4 = &shallow _2; // StorageLive(_7); -// _7 = const guard() -> [return: bb9, unwind: bb1]; +// _7 = const guard() -> [return: bb8, unwind: bb1]; // } -// bb9: { // end of guard +// bb8: { // end of guard // FakeRead(ForMatchGuard, _4); // FakeRead(ForGuardBinding, _6); -// switchInt(move _7) -> [false: bb6, otherwise: bb10]; +// switchInt(move _7) -> [false: bb10, otherwise: bb9]; // } -// bb10: { // arm1 +// bb9: { // arm1 +// StorageDead(_7); // StorageLive(_5); // _5 = ((_2 as Some).0: i32); // StorageLive(_8); // _8 = _5; // _1 = (const 1i32, move _8); // StorageDead(_8); +// StorageDead(_5); +// StorageDead(_6); // goto -> bb13; // } +// bb10: { // to pre_binding3 (can skip 2 since this is `Some`) +// StorageDead(_7); +// StorageDead(_6); +// falseEdges -> [real: bb4, imaginary: bb3]; +// } // bb11: { // arm2 // _1 = (const 3i32, const 3i32); // goto -> bb13; @@ -169,16 +182,19 @@ fn main() { // _10 = _9; // _1 = (const 2i32, move _10); // StorageDead(_10); +// StorageDead(_9); // goto -> bb13; // } // bb13: { -// ... +// StorageDead(_1); +// StorageDead(_2); +// _0 = (); // return; // } // END rustc.full_tested_match2.QualifyAndPromoteConstants.before.mir // // START rustc.main.QualifyAndPromoteConstants.before.mir -// bb0: { +// bb0: { // ... // _2 = std::option::Option::::Some(const 1i32,); // FakeRead(ForMatchedPlace, _2); @@ -189,13 +205,13 @@ fn main() { // resume; // } // bb2: { -// falseEdges -> [real: bb9, imaginary: bb3]; +// falseEdges -> [real: bb7, imaginary: bb3]; // } // bb3: { -// falseEdges -> [real: bb12, imaginary: bb4]; +// falseEdges -> [real: bb11, imaginary: bb4]; // } // bb4: { -// falseEdges -> [real: bb13, imaginary: bb5]; +// falseEdges -> [real: bb12, imaginary: bb5]; // } // bb5: { // falseEdges -> [real: bb16, imaginary: bb6]; @@ -203,65 +219,79 @@ fn main() { // bb6: { // unreachable; // } -// bb7: { -// falseEdges -> [real: bb3, imaginary: bb3]; -// } -// bb8: { -// falseEdges -> [real: bb5, imaginary: bb5]; -// } -// bb9: { // binding1: Some(w) if guard() +// bb7: { // binding1: Some(w) if guard() // StorageLive(_7); // _7 = &((_2 as Some).0: i32); // _5 = &shallow _2; // StorageLive(_8); -// _8 = const guard() -> [return: bb10, unwind: bb1]; +// _8 = const guard() -> [return: bb8, unwind: bb1]; // } -// bb10: { //end of guard +// bb8: { //end of guard1 // FakeRead(ForMatchGuard, _5); // FakeRead(ForGuardBinding, _7); -// switchInt(move _8) -> [false: bb7, otherwise: bb11]; +// switchInt(move _8) -> [false: bb10, otherwise: bb9]; // } -// bb11: { // set up bindings for arm1 +// bb9: { +// StorageDead(_8); // StorageLive(_6); // _6 = ((_2 as Some).0: i32); // _1 = const 1i32; +// StorageDead(_6); +// StorageDead(_7); // goto -> bb17; // } -// bb12: { // binding2 & arm2 +// bb10: { +// StorageDead(_8); +// StorageDead(_7); +// falseEdges -> [real: bb3, imaginary: bb3]; +// } +// bb11: { // binding2 & arm2 // StorageLive(_9); // _9 = _2; // _1 = const 2i32; +// StorageDead(_9); // goto -> bb17; // } -// bb13: { // binding3: Some(y) if guard2(y) +// bb12: { // binding3: Some(y) if guard2(y) // StorageLive(_11); // _11 = &((_2 as Some).0: i32); // _5 = &shallow _2; // StorageLive(_12); // StorageLive(_13); // _13 = (*_11); -// _12 = const guard2(move _13) -> [return: bb14, unwind: bb1]; +// _12 = const guard2(move _13) -> [return: bb13, unwind: bb1]; // } -// bb14: { // end of guard2 +// bb13: { // end of guard2 // StorageDead(_13); // FakeRead(ForMatchGuard, _5); // FakeRead(ForGuardBinding, _11); -// switchInt(move _12) -> [false: bb8, otherwise: bb15]; +// switchInt(move _12) -> [false: bb15, otherwise: bb14]; // } -// bb15: { // binding4 & arm4 +// bb14: { // binding4 & arm4 +// StorageDead(_12); // StorageLive(_10); // _10 = ((_2 as Some).0: i32); // _1 = const 3i32; +// StorageDead(_10); +// StorageDead(_11); // goto -> bb17; // } +// bb15: { +// StorageDead(_12); +// StorageDead(_11); +// falseEdges -> [real: bb5, imaginary: bb5]; +// } // bb16: { // StorageLive(_14); // _14 = _2; // _1 = const 4i32; +// StorageDead(_14); // goto -> bb17; // } // bb17: { -// ... +// StorageDead(_1); +// StorageDead(_2); +// _0 = (); // return; // } // END rustc.main.QualifyAndPromoteConstants.before.mir diff --git a/src/test/mir-opt/match_test.rs b/src/test/mir-opt/match_test.rs index a5317f98ef18..2ef9520c12c6 100644 --- a/src/test/mir-opt/match_test.rs +++ b/src/test/mir-opt/match_test.rs @@ -20,10 +20,10 @@ fn main() { // START rustc.main.SimplifyCfg-initial.after.mir // bb0: { // ... -// switchInt(move _4) -> [false: bb7, otherwise: bb8]; +// switchInt(move _4) -> [false: bb6, otherwise: bb7]; // } // bb1: { -// falseEdges -> [real: bb12, imaginary: bb2]; +// falseEdges -> [real: bb10, imaginary: bb2]; // } // bb2: { // falseEdges -> [real: bb13, imaginary: bb3]; @@ -38,33 +38,35 @@ fn main() { // unreachable; // } // bb6: { -// falseEdges -> [real: bb4, imaginary: bb2]; +// _6 = Le(const 10i32, _1); +// switchInt(move _6) -> [false: bb8, otherwise: bb9]; // } // bb7: { -// _6 = Le(const 10i32, _1); -// switchInt(move _6) -> [false: bb9, otherwise: bb10]; +// _5 = Lt(_1, const 10i32); +// switchInt(move _5) -> [false: bb6, otherwise: bb1]; // } // bb8: { -// _5 = Lt(_1, const 10i32); -// switchInt(move _5) -> [false: bb7, otherwise: bb1]; -// } -// bb9: { // switchInt(_1) -> [-1i32: bb3, otherwise: bb4]; // } -// bb10: { +// bb9: { // _7 = Le(_1, const 20i32); -// switchInt(move _7) -> [false: bb9, otherwise: bb2]; +// switchInt(move _7) -> [false: bb8, otherwise: bb2]; // } -// bb11: { -// _3 = const 0i32; -// goto -> bb16; -// } -// bb12: { +// bb10: { // _8 = &shallow _1; // StorageLive(_9); // _9 = _2; // FakeRead(ForMatchGuard, _8); -// switchInt(move _9) -> [false: bb6, otherwise: bb11]; +// switchInt(move _9) -> [false: bb12, otherwise: bb11]; +// } +// bb11: { +// StorageDead(_9); +// _3 = const 0i32; +// goto -> bb16; +// } +// bb12: { +// StorageDead(_9); +// falseEdges -> [real: bb4, imaginary: bb2]; // } // bb13: { // _3 = const 1i32; @@ -79,7 +81,6 @@ fn main() { // goto -> bb16; // } // bb16: { -// StorageDead(_9); // _0 = (); // StorageDead(_2); // StorageDead(_1); diff --git a/src/test/mir-opt/remove_fake_borrows.rs b/src/test/mir-opt/remove_fake_borrows.rs index 8348f9a77467..6ac9cee79f53 100644 --- a/src/test/mir-opt/remove_fake_borrows.rs +++ b/src/test/mir-opt/remove_fake_borrows.rs @@ -19,10 +19,10 @@ fn main() { // bb0: { // FakeRead(ForMatchedPlace, _1); // _3 = discriminant(_1); -// switchInt(move _3) -> [1isize: bb5, otherwise: bb2]; +// switchInt(move _3) -> [1isize: bb4, otherwise: bb2]; // } // bb1: { -// goto -> bb7; +// goto -> bb5; // } // bb2: { // goto -> bb8; @@ -31,16 +31,9 @@ fn main() { // unreachable; // } // bb4: { -// goto -> bb2; -// } -// bb5: { // switchInt((*(*((_1 as Some).0: &' &' i32)))) -> [0i32: bb1, otherwise: bb2]; // } -// bb6: { -// _0 = const 0i32; -// goto -> bb9; -// } -// bb7: { +// bb5: { // _4 = &shallow _1; // _5 = &shallow ((_1 as Some).0: &' &' i32); // _6 = &shallow (*((_1 as Some).0: &' &' i32)); @@ -51,14 +44,22 @@ fn main() { // FakeRead(ForMatchGuard, _5); // FakeRead(ForMatchGuard, _6); // FakeRead(ForMatchGuard, _7); -// switchInt(move _8) -> [false: bb4, otherwise: bb6]; +// switchInt(move _8) -> [false: bb7, otherwise: bb6]; +// } +// bb6: { +// StorageDead(_8); +// _0 = const 0i32; +// goto -> bb9; +// } +// bb7: { +// StorageDead(_8); +// goto -> bb2; // } // bb8: { // _0 = const 1i32; // goto -> bb9; // } // bb9: { -// StorageDead(_8); // return; // } // bb10 (cleanup): { @@ -70,10 +71,10 @@ fn main() { // bb0: { // nop; // _3 = discriminant(_1); -// switchInt(move _3) -> [1isize: bb5, otherwise: bb2]; +// switchInt(move _3) -> [1isize: bb4, otherwise: bb2]; // } // bb1: { -// goto -> bb7; +// goto -> bb5; // } // bb2: { // goto -> bb8; @@ -82,16 +83,9 @@ fn main() { // unreachable; // } // bb4: { -// goto -> bb2; -// } -// bb5: { // switchInt((*(*((_1 as Some).0: &' &' i32)))) -> [0i32: bb1, otherwise: bb2]; // } -// bb6: { -// _0 = const 0i32; -// goto -> bb9; -// } -// bb7: { +// bb5: { // nop; // nop; // nop; @@ -102,14 +96,22 @@ fn main() { // nop; // nop; // nop; -// switchInt(move _8) -> [false: bb4, otherwise: bb6]; +// switchInt(move _8) -> [false: bb7, otherwise: bb6]; +// } +// bb6: { +// StorageDead(_8); +// _0 = const 0i32; +// goto -> bb9; +// } +// bb7: { +// StorageDead(_8); +// goto -> bb2; // } // bb8: { // _0 = const 1i32; // goto -> bb9; // } // bb9: { -// StorageDead(_8); // return; // } // bb10 (cleanup): { diff --git a/src/test/ui/lint/lint-unused-mut-variables.rs b/src/test/ui/lint/lint-unused-mut-variables.rs index da0236ac4507..78609a6e24b5 100644 --- a/src/test/ui/lint/lint-unused-mut-variables.rs +++ b/src/test/ui/lint/lint-unused-mut-variables.rs @@ -105,6 +105,14 @@ fn main() { _ => {} } + // Attribute should be respected on match arms + match 0 { + #[allow(unused_mut)] + mut x => { + let mut y = 1; + }, + } + let x = |mut y: isize| y = 32; fn nothing(mut foo: isize) { foo = 37; } diff --git a/src/test/ui/lint/lint-unused-mut-variables.stderr b/src/test/ui/lint/lint-unused-mut-variables.stderr index e41d8f8ac740..1a175c9683ec 100644 --- a/src/test/ui/lint/lint-unused-mut-variables.stderr +++ b/src/test/ui/lint/lint-unused-mut-variables.stderr @@ -133,7 +133,7 @@ LL | fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] { | help: remove this `mut` error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:130:9 + --> $DIR/lint-unused-mut-variables.rs:138:9 | LL | let mut b = vec![2]; | ----^ @@ -141,7 +141,7 @@ LL | let mut b = vec![2]; | help: remove this `mut` | note: lint level defined here - --> $DIR/lint-unused-mut-variables.rs:126:8 + --> $DIR/lint-unused-mut-variables.rs:134:8 | LL | #[deny(unused_mut)] | ^^^^^^^^^^ From 0f507246e732c302fbfde83296c03c69fafdf4ad Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 3 Apr 2019 19:30:18 +0100 Subject: [PATCH 0234/3207] Remove MIR borrowck hack for old match scopes --- src/librustc_mir/dataflow/impls/mod.rs | 39 ++++++-------------------- 1 file changed, 8 insertions(+), 31 deletions(-) diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index 4dcfb3f1a7fc..03d55b84f32e 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -11,8 +11,7 @@ use super::MoveDataParamEnv; use crate::util::elaborate_drops::DropFlagState; -use super::move_paths::{HasMoveData, MoveData, MovePathIndex, InitIndex}; -use super::move_paths::{LookupResult, InitKind}; +use super::move_paths::{HasMoveData, MoveData, MovePathIndex, InitIndex, InitKind}; use super::{BitDenotation, BlockSets, InitialFlow}; use super::drop_flag_effects_for_function_entry; @@ -470,35 +469,13 @@ impl<'a, 'gcx, 'tcx> BitDenotation<'tcx> for EverInitializedPlaces<'a, 'gcx, 'tc sets.gen_all(&init_loc_map[location]); match stmt.kind { - mir::StatementKind::StorageDead(local) | - mir::StatementKind::StorageLive(local) => { - // End inits for StorageDead and StorageLive, so that an immutable - // variable can be reinitialized on the next iteration of the loop. - // - // FIXME(#46525): We *need* to do this for StorageLive as well as - // StorageDead, because lifetimes of match bindings with guards are - // weird - i.e., this code - // - // ``` - // fn main() { - // match 0 { - // a | a - // if { println!("a={}", a); false } => {} - // _ => {} - // } - // } - // ``` - // - // runs the guard twice, using the same binding for `a`, and only - // storagedeads after everything ends, so if we don't regard the - // storagelive as killing storage, we would have a multiple assignment - // to immutable data error. - if let LookupResult::Exact(mpi) = - rev_lookup.find(&mir::Place::Base(mir::PlaceBase::Local(local))) { - debug!("stmt {:?} at loc {:?} clears the ever initialized status of {:?}", - stmt, location, &init_path_map[mpi]); - sets.kill_all(&init_path_map[mpi]); - } + mir::StatementKind::StorageDead(local) => { + // End inits for StorageDead, so that an immutable variable can + // be reinitialized on the next iteration of the loop. + let move_path_index = rev_lookup.find_local(local); + debug!("stmt {:?} at loc {:?} clears the ever initialized status of {:?}", + stmt, location, &init_path_map[move_path_index]); + sets.kill_all(&init_path_map[move_path_index]); } _ => {} } From b5643f1a490d6aa5f90fc45fd92ac34d6e8a05d8 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 3 Apr 2019 20:54:23 +0100 Subject: [PATCH 0235/3207] Emit fake borrows for all tests I was incorrectly under the impression that this would only lead to duplicates. See `mir-opt/match-arm-scope.rs` (upcomming commit) for a case where we didn't emit a fake borrow of `items.1`. --- src/librustc_mir/build/matches/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 091e39630d6c..58ca35abcb12 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -870,7 +870,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { span, untested_candidates, join_block, - &mut None, + fake_borrows, ) } From abab9efbdb82b76f418115462311f8852600c9a2 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 3 Apr 2019 21:13:51 +0100 Subject: [PATCH 0236/3207] Schedule storage-dead of temporaries sooner This ensures that we will correctly generate a storage-dead if the initializing expression diverges. --- src/librustc_mir/build/expr/as_temp.rs | 40 +++++++++++++------ src/test/mir-opt/issue-49232.rs | 1 - src/test/mir-opt/match_false_edges.rs | 6 +-- .../mir-opt/storage_live_dead_in_statics.rs | 2 +- 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index c60e19701006..ac70bf30e457 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -1,6 +1,7 @@ //! See docs in build/expr/mod.rs use crate::build::{BlockAnd, BlockAndExtension, Builder}; +use crate::build::scope::{CachedBlock, DropKind}; use crate::hair::*; use rustc::middle::region; use rustc::mir::*; @@ -63,6 +64,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } this.local_decls.push(local_decl) }; + let temp_place = &Place::Base(PlaceBase::Local(temp)); + if !expr_ty.is_never() { this.cfg.push( block, @@ -71,25 +74,38 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { kind: StatementKind::StorageLive(temp), }, ); + + // In constants, temp_lifetime is None for temporaries that live for the + // 'static lifetime. Thus we do not drop these temporaries and simply leak them. + // This is equivalent to what `let x = &foo();` does in functions. The temporary + // is lifted to their surrounding scope. In a function that means the temporary lives + // until just before the function returns. In constants that means it outlives the + // constant's initialization value computation. Anything outliving a constant + // must have the `'static` lifetime and live forever. + // Anything with a shorter lifetime (e.g the `&foo()` in `bar(&foo())` or anything + // within a block will keep the regular drops just like runtime code. + if let Some(temp_lifetime) = temp_lifetime { + this.schedule_drop( + expr_span, + temp_lifetime, + temp_place, + expr_ty, + DropKind::Storage, + ); + } } - unpack!(block = this.into(&Place::Base(PlaceBase::Local(temp)), block, expr)); + unpack!(block = this.into(temp_place, block, expr)); - // In constants, temp_lifetime is None for temporaries that live for the - // 'static lifetime. Thus we do not drop these temporaries and simply leak them. - // This is equivalent to what `let x = &foo();` does in functions. The temporary - // is lifted to their surrounding scope. In a function that means the temporary lives - // until just before the function returns. In constants that means it outlives the - // constant's initialization value computation. Anything outliving a constant - // must have the `'static` lifetime and live forever. - // Anything with a shorter lifetime (e.g the `&foo()` in `bar(&foo())` or anything - // within a block will keep the regular drops just like runtime code. if let Some(temp_lifetime) = temp_lifetime { - this.schedule_drop_storage_and_value( + this.schedule_drop( expr_span, temp_lifetime, - &Place::Base(PlaceBase::Local(temp)), + temp_place, expr_ty, + DropKind::Value { + cached_block: CachedBlock::default(), + }, ); } diff --git a/src/test/mir-opt/issue-49232.rs b/src/test/mir-opt/issue-49232.rs index 3910183dee78..bf22f00b5055 100644 --- a/src/test/mir-opt/issue-49232.rs +++ b/src/test/mir-opt/issue-49232.rs @@ -86,7 +86,6 @@ fn main() { // unreachable; // } // bb17: { -// StorageDead(_4); // goto -> bb18; // } // bb18: { diff --git a/src/test/mir-opt/match_false_edges.rs b/src/test/mir-opt/match_false_edges.rs index 0850c552536c..6979924c8cd9 100644 --- a/src/test/mir-opt/match_false_edges.rs +++ b/src/test/mir-opt/match_false_edges.rs @@ -109,8 +109,8 @@ fn main() { // goto -> bb13; // } // bb13: { -// StorageDead(_1); // StorageDead(_2); +// StorageDead(_1); // _0 = (); // return; // } @@ -186,8 +186,8 @@ fn main() { // goto -> bb13; // } // bb13: { -// StorageDead(_1); // StorageDead(_2); +// StorageDead(_1); // _0 = (); // return; // } @@ -289,8 +289,8 @@ fn main() { // goto -> bb17; // } // bb17: { -// StorageDead(_1); // StorageDead(_2); +// StorageDead(_1); // _0 = (); // return; // } diff --git a/src/test/mir-opt/storage_live_dead_in_statics.rs b/src/test/mir-opt/storage_live_dead_in_statics.rs index 10f00cf8b0c3..2ed34ecfad2c 100644 --- a/src/test/mir-opt/storage_live_dead_in_statics.rs +++ b/src/test/mir-opt/storage_live_dead_in_statics.rs @@ -182,8 +182,8 @@ fn main() { // _2 = Foo { tup: const "hi", data: move _3 }; // _1 = &_2; // _0 = &(*_1); -// StorageDead(_1); // StorageDead(_5); +// StorageDead(_1); // return; // } //} From 2420d82a7c55432071a2094dac29dfe96f303dfe Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 3 Apr 2019 21:21:53 +0100 Subject: [PATCH 0237/3207] Add a test for match scopes --- src/test/mir-opt/match-arm-scopes.rs | 245 +++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 src/test/mir-opt/match-arm-scopes.rs diff --git a/src/test/mir-opt/match-arm-scopes.rs b/src/test/mir-opt/match-arm-scopes.rs new file mode 100644 index 000000000000..0f026b8a08df --- /dev/null +++ b/src/test/mir-opt/match-arm-scopes.rs @@ -0,0 +1,245 @@ +// Test that StorageDead and Drops are generated properly for bindings in +// matches: +// * The MIR should only contain a single drop of `s` and `t`: at the end +// of their respective arms. +// * StorageDead and StorageLive statements are correctly matched up on +// non-unwind paths. +// * The visibility scopes of the match arms should be disjoint, and contain. +// all of the bindings for that scope. +// * No drop flags are used. + +#![feature(nll, bind_by_move_pattern_guards)] + +fn complicated_match(cond: bool, items: (bool, bool, String)) -> i32 { + match items { + (false, a, s) | (a, false, s) if if cond { return 3 } else { a } => 1, + (true, b, t) | (false, b, t) => 2, + } +} + +const CASES: &[(bool, bool, bool, i32)] = &[ + (false, false, false, 2), + (false, false, true, 1), + (false, true, false, 1), + (false, true, true, 2), + (true, false, false, 3), + (true, false, true, 3), + (true, true, false, 3), + (true, true, true, 2), +]; + +fn main() { + for &(cond, items_1, items_2, result) in CASES { + assert_eq!( + complicated_match(cond, (items_1, items_2, String::new())), + result, + ); + } +} + +// END RUST SOURCE +// START rustc.complicated_match.SimplifyCfg-initial.after.mir +// let mut _0: i32; +// let mut _3: &bool; // Temp for fake borrow of `items.0` +// let mut _4: &bool; // Temp for fake borrow of `items.1` +// let _5: bool; // `a` in arm +// let _6: &bool; // `a` in guard +// let _7: std::string::String; // `s` in arm +// let _8: &std::string::String; // `s` in guard +// let mut _9: bool; // `if cond { return 3 } else { a }` +// let mut _10: bool; // `cond` +// let mut _11: !; // `return 3` +// let mut _12: bool; // `if cond { return 3 } else { a }` +// let mut _13: bool; // `cond` +// let mut _14: !; // `return 3` +// let _15: bool; // `b` +// let _16: std::string::String; // `t` +// scope 1 { +// } +// scope 2 { +// } +// bb0: { +// FakeRead(ForMatchedPlace, _2); +// switchInt((_2.0: bool)) -> [false: bb2, otherwise: bb7]; +// } +// bb1 (cleanup): { +// resume; +// } +// bb2: { +// falseEdges -> [real: bb10, imaginary: bb3]; +// } +// bb3: { +// falseEdges -> [real: bb21, imaginary: bb4]; +// } +// bb4: { +// falseEdges -> [real: bb31, imaginary: bb5]; +// } +// bb5: { +// falseEdges -> [real: bb32, imaginary: bb6]; +// } +// bb6: { +// unreachable; +// } +// bb7: { +// switchInt((_2.1: bool)) -> [false: bb3, otherwise: bb8]; +// } +// bb8: { +// switchInt((_2.0: bool)) -> [false: bb5, otherwise: bb4]; +// } +// bb9: { // arm 1 +// _0 = const 1i32; +// drop(_7) -> [return: bb29, unwind: bb16]; +// } +// bb10: { // guard - first time +// StorageLive(_6); +// _6 = &(_2.1: bool); +// StorageLive(_8); +// _8 = &(_2.2: std::string::String); +// _3 = &shallow (_2.0: bool); +// _4 = &shallow (_2.1: bool); +// StorageLive(_9); +// StorageLive(_10); +// _10 = _1; +// FakeRead(ForMatchedPlace, _10); +// switchInt(_10) -> [false: bb12, otherwise: bb11]; +// } +// bb11: { +// falseEdges -> [real: bb14, imaginary: bb12]; +// } +// bb12: { +// falseEdges -> [real: bb18, imaginary: bb13]; +// } +// bb13: { +// unreachable; +// } +// bb14: { // `return 3` - first time +// _0 = const 3i32; +// StorageDead(_10); +// StorageDead(_9); +// StorageDead(_8); +// StorageDead(_6); +// goto -> bb17; +// } +// bb15: { +// return; +// } +// bb16 (cleanup): { +// drop(_2) -> bb1; +// } +// bb17: { +// drop(_2) -> [return: bb15, unwind: bb1]; +// } +// bb18: { // `else` block - first time +// _9 = (*_6); +// StorageDead(_10); +// FakeRead(ForMatchGuard, _3); +// FakeRead(ForMatchGuard, _4); +// FakeRead(ForGuardBinding, _6); +// FakeRead(ForGuardBinding, _8); +// switchInt(move _9) -> [false: bb20, otherwise: bb19]; +// } +// bb19: { +// StorageDead(_9); +// StorageLive(_5); +// _5 = (_2.1: bool); +// StorageLive(_7); +// _7 = move (_2.2: std::string::String); +// goto -> bb9; +// } +// bb20: { // guard otherwise case - first time +// StorageDead(_9); +// StorageDead(_8); +// StorageDead(_6); +// falseEdges -> [real: bb7, imaginary: bb3]; +// } +// bb21: { // guard - second time +// StorageLive(_6); +// _6 = &(_2.0: bool); +// StorageLive(_8); +// _8 = &(_2.2: std::string::String); +// _3 = &shallow (_2.0: bool); +// _4 = &shallow (_2.1: bool); +// StorageLive(_12); +// StorageLive(_13); +// _13 = _1; +// FakeRead(ForMatchedPlace, _13); +// switchInt(_13) -> [false: bb23, otherwise: bb22]; +// } +// bb22: { +// falseEdges -> [real: bb25, imaginary: bb23]; +// } +// bb23: { +// falseEdges -> [real: bb26, imaginary: bb24]; +// } +// bb24: { +// unreachable; +// } +// bb25: { // `return 3` - second time +// _0 = const 3i32; +// StorageDead(_13); +// StorageDead(_12); +// StorageDead(_8); +// StorageDead(_6); +// goto -> bb17; +// } +// bb26: { // `else` block - second time +// _12 = (*_6); +// StorageDead(_13); +// FakeRead(ForMatchGuard, _3); +// FakeRead(ForMatchGuard, _4); +// FakeRead(ForGuardBinding, _6); +// FakeRead(ForGuardBinding, _8); +// switchInt(move _12) -> [false: bb28, otherwise: bb27]; +// } +// bb27: { // Guard otherwise case - second time +// StorageDead(_12); +// StorageLive(_5); +// _5 = (_2.0: bool); +// StorageLive(_7); +// _7 = move (_2.2: std::string::String); +// goto -> bb9; +// } +// bb28: { // rest of arm 1 +// StorageDead(_12); +// StorageDead(_8); +// StorageDead(_6); +// falseEdges -> [real: bb8, imaginary: bb4]; +// } +// bb29: { +// StorageDead(_7); +// StorageDead(_5); +// StorageDead(_8); +// StorageDead(_6); +// goto -> bb34; +// } +// bb30: { // arm 2 +// _0 = const 2i32; +// drop(_16) -> [return: bb33, unwind: bb16]; +// } +// bb31: { // bindings for arm 2 - first pattern +// StorageLive(_15); +// _15 = (_2.1: bool); +// StorageLive(_16); +// _16 = move (_2.2: std::string::String); +// goto -> bb30; +// } +// bb32: { // bindings for arm 2 - first pattern +// StorageLive(_15); +// _15 = (_2.1: bool); +// StorageLive(_16); +// _16 = move (_2.2: std::string::String); +// goto -> bb30; +// } +// bb33: { // rest of arm 2 +// StorageDead(_16); +// StorageDead(_15); +// goto -> bb34; +// } +// bb34: { // end of match +// drop(_2) -> [return: bb15, unwind: bb1]; +// } +// END rustc.complicated_match.SimplifyCfg-initial.after.mir +// START rustc.complicated_match.ElaborateDrops.after.mir +// let _16: std::string::String; // No drop flags, which would come after this. +// scope 1 { +// END rustc.complicated_match.ElaborateDrops.after.mir From 015a45156f7ae9c1c0af86795409d892832aaa71 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 22 Apr 2019 20:35:00 +0200 Subject: [PATCH 0238/3207] Comment style fixes Co-Authored-By: matthewjasper --- src/librustc_mir/build/expr/as_temp.rs | 4 ++-- src/librustc_mir/build/scope.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index ac70bf30e457..cffd8fb2892f 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -75,8 +75,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }, ); - // In constants, temp_lifetime is None for temporaries that live for the - // 'static lifetime. Thus we do not drop these temporaries and simply leak them. + // In constants, `temp_lifetime` is `None` for temporaries that live for the + // `'static` lifetime. Thus we do not drop these temporaries and simply leak them. // This is equivalent to what `let x = &foo();` does in functions. The temporary // is lifted to their surrounding scope. In a function that means the temporary lives // until just before the function returns. In constants that means it outlives the diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 0d1d40a8af63..34df40ae180a 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -900,7 +900,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// * The variable must be in that scope. /// * The variable must be at the top of that scope: it's the next thing /// scheduled to drop. - /// * The drop must be of DropKind::Storage. + /// * The drop must be of `DropKind::Storage`. /// /// This is used for the boolean holding the result of the match guard. We /// do this because: From 0835048ea0fc724163b5032112df3c7555a2073b Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 5 May 2019 17:32:52 +0100 Subject: [PATCH 0239/3207] Fix match ergonomics suggestion --- src/librustc_typeck/check/_match.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 99b350b83327..e4b431e6e68f 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -540,7 +540,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { err.help(&format!("did you mean `{}: &{}`?", snippet, expected)); } } - hir::Node::Expr(hir::Expr { node: hir::ExprKind::Match(..), .. }) | + hir::Node::Arm(_) | hir::Node::Pat(_) => { // rely on match ergonomics or it might be nested `&&pat` if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) { From 7b7e172f6d5d603c9d266e0c660a5649eb845126 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 21 May 2019 12:06:47 -0700 Subject: [PATCH 0240/3207] Place timeouts at the job level --- .azure-pipelines/try.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.azure-pipelines/try.yml b/.azure-pipelines/try.yml index 3ef24d2de973..5c76d2053345 100644 --- a/.azure-pipelines/try.yml +++ b/.azure-pipelines/try.yml @@ -11,6 +11,7 @@ variables: jobs: - job: Linux + timeoutInMinutes: 600 pool: vmImage: ubuntu-16.04 steps: @@ -144,6 +145,7 @@ jobs: IMAGE: mingw-check - job: macOS + timeoutInMinutes: 600 pool: vmImage: macos-10.13 steps: @@ -204,6 +206,7 @@ jobs: DIST_REQUIRE_ALL_TOOLS: 1 - job: Windows + timeoutInMinutes: 600 pool: vmImage: 'vs2017-win2016' steps: From 0f4b546af3c6ce6fc201ee4b283a6600b49ea1d2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 21 May 2019 12:09:44 -0700 Subject: [PATCH 0241/3207] Go back to fewer builders to test on `try` --- .azure-pipelines/try.yml | 498 +++++++++++++++++++-------------------- 1 file changed, 249 insertions(+), 249 deletions(-) diff --git a/.azure-pipelines/try.yml b/.azure-pipelines/try.yml index 5c76d2053345..135fec5f8327 100644 --- a/.azure-pipelines/try.yml +++ b/.azure-pipelines/try.yml @@ -18,131 +18,131 @@ jobs: - template: steps/run.yml strategy: matrix: - x86_64-gnu-llvm-6.0: - IMAGE: x86_64-gnu-llvm-6.0 - RUST_BACKTRACE: 1 + # x86_64-gnu-llvm-6.0: + # IMAGE: x86_64-gnu-llvm-6.0 + # RUST_BACKTRACE: 1 dist-x86_64-linux: IMAGE: dist-x86_64-linux DEPLOY: 1 - dist-x86_64-linux-alt: - IMAGE: dist-x86_64-linux - DEPLOY_ALT: 1 + # dist-x86_64-linux-alt: + # IMAGE: dist-x86_64-linux + # DEPLOY_ALT: 1 - arm-android: - IMAGE: arm-android - - armhf-gnu: - IMAGE: armhf-gnu - - dist-various-1: - IMAGE: dist-various-1 - DEPLOY: 1 - - dist-various-2: - IMAGE: dist-various-2 - DEPLOY: 1 - - dist-aarch64-linux: - IMAGE: dist-aarch64-linux - DEPLOY: 1 - - dist-android: - IMAGE: dist-android - DEPLOY: 1 - - dist-arm-linux: - IMAGE: dist-arm-linux - DEPLOY: 1 - - dist-armhf-linux: - IMAGE: dist-armhf-linux - DEPLOY: 1 - - dist-armv7-linux: - IMAGE: dist-armv7-linux - DEPLOY: 1 - - dist-i586-gnu-i586-i686-musl: - IMAGE: dist-i586-gnu-i586-i686-musl - DEPLOY: 1 - - dist-i686-freebsd: - IMAGE: dist-i686-freebsd - DEPLOY: 1 - - dist-i686-linux: - IMAGE: dist-i686-linux - DEPLOY: 1 - - dist-mips-linux: - IMAGE: dist-mips-linux - DEPLOY: 1 - - dist-mips64-linux: - IMAGE: dist-mips64-linux - DEPLOY: 1 - - dist-mips64el-linux: - IMAGE: dist-mips64el-linux - DEPLOY: 1 - - dist-mipsel-linux: - IMAGE: dist-mipsel-linux - DEPLOY: 1 - - dist-powerpc-linux: - IMAGE: dist-powerpc-linux - DEPLOY: 1 - - dist-powerpc64-linux: - IMAGE: dist-powerpc64-linux - DEPLOY: 1 - - dist-powerpc64le-linux: - IMAGE: dist-powerpc64le-linux - DEPLOY: 1 - - dist-s390x-linux: - IMAGE: dist-s390x-linux - DEPLOY: 1 - - dist-x86_64-freebsd: - IMAGE: dist-x86_64-freebsd - DEPLOY: 1 - - dist-x86_64-musl: - IMAGE: dist-x86_64-musl - DEPLOY: 1 - - dist-x86_64-netbsd: - IMAGE: dist-x86_64-netbsd - DEPLOY: 1 - - asmjs: - IMAGE: asmjs - i686-gnu: - IMAGE: i686-gnu - i686-gnu-nopt: - IMAGE: i686-gnu-nopt - test-various: - IMAGE: test-various + # arm-android: + # IMAGE: arm-android + # + # armhf-gnu: + # IMAGE: armhf-gnu + # + # dist-various-1: + # IMAGE: dist-various-1 + # DEPLOY: 1 + # + # dist-various-2: + # IMAGE: dist-various-2 + # DEPLOY: 1 + # + # dist-aarch64-linux: + # IMAGE: dist-aarch64-linux + # DEPLOY: 1 + # + # dist-android: + # IMAGE: dist-android + # DEPLOY: 1 + # + # dist-arm-linux: + # IMAGE: dist-arm-linux + # DEPLOY: 1 + # + # dist-armhf-linux: + # IMAGE: dist-armhf-linux + # DEPLOY: 1 + # + # dist-armv7-linux: + # IMAGE: dist-armv7-linux + # DEPLOY: 1 + # + # dist-i586-gnu-i586-i686-musl: + # IMAGE: dist-i586-gnu-i586-i686-musl + # DEPLOY: 1 + # + # dist-i686-freebsd: + # IMAGE: dist-i686-freebsd + # DEPLOY: 1 + # + # dist-i686-linux: + # IMAGE: dist-i686-linux + # DEPLOY: 1 + # + # dist-mips-linux: + # IMAGE: dist-mips-linux + # DEPLOY: 1 + # + # dist-mips64-linux: + # IMAGE: dist-mips64-linux + # DEPLOY: 1 + # + # dist-mips64el-linux: + # IMAGE: dist-mips64el-linux + # DEPLOY: 1 + # + # dist-mipsel-linux: + # IMAGE: dist-mipsel-linux + # DEPLOY: 1 + # + # dist-powerpc-linux: + # IMAGE: dist-powerpc-linux + # DEPLOY: 1 + # + # dist-powerpc64-linux: + # IMAGE: dist-powerpc64-linux + # DEPLOY: 1 + # + # dist-powerpc64le-linux: + # IMAGE: dist-powerpc64le-linux + # DEPLOY: 1 + # + # dist-s390x-linux: + # IMAGE: dist-s390x-linux + # DEPLOY: 1 + # + # dist-x86_64-freebsd: + # IMAGE: dist-x86_64-freebsd + # DEPLOY: 1 + # + # dist-x86_64-musl: + # IMAGE: dist-x86_64-musl + # DEPLOY: 1 + # + # dist-x86_64-netbsd: + # IMAGE: dist-x86_64-netbsd + # DEPLOY: 1 + # + # asmjs: + # IMAGE: asmjs + # i686-gnu: + # IMAGE: i686-gnu + # i686-gnu-nopt: + # IMAGE: i686-gnu-nopt + # test-various: + # IMAGE: test-various x86_64-gnu: IMAGE: x86_64-gnu - x86_64-gnu-full-bootstrap: - IMAGE: x86_64-gnu-full-bootstrap - x86_64-gnu-aux: - IMAGE: x86_64-gnu-aux - x86_64-gnu-tools: - IMAGE: x86_64-gnu-tools - x86_64-gnu-debug: - IMAGE: x86_64-gnu-debug - x86_64-gnu-nopt: - IMAGE: x86_64-gnu-nopt - x86_64-gnu-distcheck: - IMAGE: x86_64-gnu-distcheck - mingw-check: - IMAGE: mingw-check + # x86_64-gnu-full-bootstrap: + # IMAGE: x86_64-gnu-full-bootstrap + # x86_64-gnu-aux: + # IMAGE: x86_64-gnu-aux + # x86_64-gnu-tools: + # IMAGE: x86_64-gnu-tools + # x86_64-gnu-debug: + # IMAGE: x86_64-gnu-debug + # x86_64-gnu-nopt: + # IMAGE: x86_64-gnu-nopt + # x86_64-gnu-distcheck: + # IMAGE: x86_64-gnu-distcheck + # mingw-check: + # IMAGE: mingw-check - job: macOS timeoutInMinutes: 600 @@ -177,33 +177,33 @@ jobs: NO_DEBUG_ASSERTIONS: 1 DIST_REQUIRE_ALL_TOOLS: 1 - dist-x86_64-apple-alt: - RUST_CHECK_TARGET: dist - RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --enable-lldb --set rust.jemalloc - DEPLOY_ALT: 1 - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - - i686-apple: - RUST_CHECK_TARGET: check - RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.8 - MACOSX_STD_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - - dist-i686-apple: - RUST_CHECK_TARGET: dist - RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb --set rust.jemalloc - DEPLOY: 1 - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - DIST_REQUIRE_ALL_TOOLS: 1 + # dist-x86_64-apple-alt: + # RUST_CHECK_TARGET: dist + # RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --enable-lldb --set rust.jemalloc + # DEPLOY_ALT: 1 + # RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + # MACOSX_DEPLOYMENT_TARGET: 10.7 + # NO_LLVM_ASSERTIONS: 1 + # NO_DEBUG_ASSERTIONS: 1 + # + # i686-apple: + # RUST_CHECK_TARGET: check + # RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --set rust.jemalloc + # RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + # MACOSX_DEPLOYMENT_TARGET: 10.8 + # MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + # NO_LLVM_ASSERTIONS: 1 + # NO_DEBUG_ASSERTIONS: 1 + # + # dist-i686-apple: + # RUST_CHECK_TARGET: dist + # RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb --set rust.jemalloc + # DEPLOY: 1 + # RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + # MACOSX_DEPLOYMENT_TARGET: 10.7 + # NO_LLVM_ASSERTIONS: 1 + # NO_DEBUG_ASSERTIONS: 1 + # DIST_REQUIRE_ALL_TOOLS: 1 - job: Windows timeoutInMinutes: 600 @@ -225,77 +225,77 @@ jobs: MSYS_BITS: 64 RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler SCRIPT: make ci-subset-2 - i686-msvc-1: - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc - SCRIPT: make ci-subset-1 - i686-msvc-2: - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc - SCRIPT: make ci-subset-2 - # MSVC aux tests - x86_64-msvc-aux: - MSYS_BITS: 64 - RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc - x86_64-msvc-cargo: - MSYS_BITS: 64 - SCRIPT: python x.py test src/tools/cargotest src/tools/cargo - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc - VCVARS_BAT: vcvars64.bat - # MSVC tools tests - x86_64-msvc-tools: - MSYS_BITS: 64 - SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri - - # 32/64-bit MinGW builds. + # i686-msvc-1: + # MSYS_BITS: 32 + # RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc + # SCRIPT: make ci-subset-1 + # i686-msvc-2: + # MSYS_BITS: 32 + # RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc + # SCRIPT: make ci-subset-2 + # # MSVC aux tests + # x86_64-msvc-aux: + # MSYS_BITS: 64 + # RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1 + # RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + # x86_64-msvc-cargo: + # MSYS_BITS: 64 + # SCRIPT: python x.py test src/tools/cargotest src/tools/cargo + # RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + # VCVARS_BAT: vcvars64.bat + # # MSVC tools tests + # x86_64-msvc-tools: + # MSYS_BITS: 64 + # SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows + # RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri # - # We are using MinGW with posix threads since LLVM does not compile with - # the win32 threads version due to missing support for C++'s std::thread. - # - # Instead of relying on the MinGW version installed on appveryor we download - # and install one ourselves so we won't be surprised by changes to appveyor's - # build image. - # - # Finally, note that the downloads below are all in the `rust-lang-ci` S3 - # bucket, but they cleraly didn't originate there! The downloads originally - # came from the mingw-w64 SourceForge download site. Unfortunately - # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. - i686-mingw-1: - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - SCRIPT: make ci-subset-1 - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z - MINGW_DIR: mingw32 - # FIXME(#59637) - NO_DEBUG_ASSERTIONS: 1 - NO_LLVM_ASSERTIONS: 1 - i686-mingw-2: - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - SCRIPT: make ci-subset-2 - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z - MINGW_DIR: mingw32 - x86_64-mingw-1: - MSYS_BITS: 64 - SCRIPT: make ci-subset-1 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z - MINGW_DIR: mingw64 - # FIXME(#59637) - NO_DEBUG_ASSERTIONS: 1 - NO_LLVM_ASSERTIONS: 1 - x86_64-mingw-2: - MSYS_BITS: 64 - SCRIPT: make ci-subset-2 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z - MINGW_DIR: mingw64 + # # 32/64-bit MinGW builds. + # # + # # We are using MinGW with posix threads since LLVM does not compile with + # # the win32 threads version due to missing support for C++'s std::thread. + # # + # # Instead of relying on the MinGW version installed on appveryor we download + # # and install one ourselves so we won't be surprised by changes to appveyor's + # # build image. + # # + # # Finally, note that the downloads below are all in the `rust-lang-ci` S3 + # # bucket, but they cleraly didn't originate there! The downloads originally + # # came from the mingw-w64 SourceForge download site. Unfortunately + # # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. + # i686-mingw-1: + # MSYS_BITS: 32 + # RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + # SCRIPT: make ci-subset-1 + # MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + # MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z + # MINGW_DIR: mingw32 + # # FIXME(#59637) + # NO_DEBUG_ASSERTIONS: 1 + # NO_LLVM_ASSERTIONS: 1 + # i686-mingw-2: + # MSYS_BITS: 32 + # RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + # SCRIPT: make ci-subset-2 + # MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + # MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z + # MINGW_DIR: mingw32 + # x86_64-mingw-1: + # MSYS_BITS: 64 + # SCRIPT: make ci-subset-1 + # RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + # MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + # MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z + # MINGW_DIR: mingw64 + # # FIXME(#59637) + # NO_DEBUG_ASSERTIONS: 1 + # NO_LLVM_ASSERTIONS: 1 + # x86_64-mingw-2: + # MSYS_BITS: 64 + # SCRIPT: make ci-subset-2 + # RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + # MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + # MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z + # MINGW_DIR: mingw64 # 32/64 bit MSVC and GNU deployment dist-x86_64-msvc: @@ -307,37 +307,37 @@ jobs: SCRIPT: python x.py dist DIST_REQUIRE_ALL_TOOLS: 1 DEPLOY: 1 - dist-i686-msvc: - RUST_CONFIGURE_ARGS: > - --build=i686-pc-windows-msvc - --target=i586-pc-windows-msvc - --enable-full-tools - --enable-profiler - SCRIPT: python x.py dist - DIST_REQUIRE_ALL_TOOLS: 1 - DEPLOY: 1 - dist-i686-mingw: - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools - SCRIPT: python x.py dist - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z - MINGW_DIR: mingw32 - DIST_REQUIRE_ALL_TOOLS: 1 - DEPLOY: 1 - dist-x86_64-mingw: - MSYS_BITS: 64 - SCRIPT: python x.py dist - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z - MINGW_DIR: mingw64 - DIST_REQUIRE_ALL_TOOLS: 1 - DEPLOY: 1 - - # "alternate" deployment, see .travis.yml for more info - dist-x86_64-msvc-alt: - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler - SCRIPT: python x.py dist - DEPLOY_ALT: 1 + # dist-i686-msvc: + # RUST_CONFIGURE_ARGS: > + # --build=i686-pc-windows-msvc + # --target=i586-pc-windows-msvc + # --enable-full-tools + # --enable-profiler + # SCRIPT: python x.py dist + # DIST_REQUIRE_ALL_TOOLS: 1 + # DEPLOY: 1 + # dist-i686-mingw: + # MSYS_BITS: 32 + # RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools + # SCRIPT: python x.py dist + # MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + # MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z + # MINGW_DIR: mingw32 + # DIST_REQUIRE_ALL_TOOLS: 1 + # DEPLOY: 1 + # dist-x86_64-mingw: + # MSYS_BITS: 64 + # SCRIPT: python x.py dist + # RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools + # MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + # MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z + # MINGW_DIR: mingw64 + # DIST_REQUIRE_ALL_TOOLS: 1 + # DEPLOY: 1 + # + # # "alternate" deployment, see .travis.yml for more info + # dist-x86_64-msvc-alt: + # MSYS_BITS: 64 + # RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler + # SCRIPT: python x.py dist + # DEPLOY_ALT: 1 From 8d42b87ac041dc05c9ae8c060aaa8864826639d4 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 21 May 2019 12:20:50 -0700 Subject: [PATCH 0242/3207] Use new-style s3 urls in docker download script --- src/ci/docker/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 0e1485601e96..c9642dbf60c6 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -42,7 +42,7 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then awk '{print $1}') s3url="s3://$SCCACHE_BUCKET/docker/$cksum" - url="https://s3-us-west-1.amazonaws.com/$SCCACHE_BUCKET/docker/$cksum" + url="https://$SCCACHE_BUCKET.s3.amazonaws.com/docker/$cksum" upload="aws s3 cp - $s3url" echo "Attempting to download $url" From 190d1988e010db8e09e07324f7a41dd927d0c580 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 21 May 2019 21:24:34 +0200 Subject: [PATCH 0243/3207] ci: switch to xcode 9.3 on azure --- .azure-pipelines/steps/run.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.azure-pipelines/steps/run.yml b/.azure-pipelines/steps/run.yml index 3516ca598075..22ffa1010e49 100644 --- a/.azure-pipelines/steps/run.yml +++ b/.azure-pipelines/steps/run.yml @@ -35,6 +35,12 @@ steps: displayName: Install build dependencies (OSX) condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin'), eq(variables['RUST_CHECK_TARGET'],'dist')) +- bash: | + set -e + sudo xcode-select --switch /Applications/Xcode_9.3.app + displayName: Switch to Xcode 9.3 (OSX) + condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin'), eq(variables['RUST_CHECK_TARGET'],'dist')) + - template: install-windows-build-deps.yml # Looks like docker containers have IPv6 disabled by default, so let's turn it From ebd6c7164ee7d8f85a640858f1cad1f56cc11a35 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Fri, 3 May 2019 22:24:52 +0100 Subject: [PATCH 0244/3207] Dont show variables from desugarings in borrowck errors --- src/librustc/mir/mod.rs | 7 +++ .../borrow_check/error_reporting.rs | 8 ++-- .../borrow_check/mutability_errors.rs | 47 ++++++++++--------- .../borrow_check/nll/explain_borrow/mod.rs | 4 +- src/libsyntax/parse/parser.rs | 9 ++-- src/test/ui/nll/dont-print-desugared-async.rs | 9 ++++ .../ui/nll/dont-print-desugared-async.stderr | 12 +++++ src/test/ui/nll/dont-print-desugared.rs | 21 +++++++++ src/test/ui/nll/dont-print-desugared.stderr | 27 +++++++++++ 9 files changed, 112 insertions(+), 32 deletions(-) create mode 100644 src/test/ui/nll/dont-print-desugared-async.rs create mode 100644 src/test/ui/nll/dont-print-desugared-async.stderr create mode 100644 src/test/ui/nll/dont-print-desugared.rs create mode 100644 src/test/ui/nll/dont-print-desugared.stderr diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index dd43cb2f18ec..aab9d5e3a02b 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -915,6 +915,13 @@ impl<'tcx> LocalDecl<'tcx> { } } + /// Returns `true` is the local is from a compiler desugaring, e.g., + /// `__next` from a `for` loop. + #[inline] + pub fn from_compiler_desugaring(&self) -> bool { + self.source_info.span.compiler_desugaring_kind().is_some() + } + /// Creates a new `LocalDecl` for a temporary. #[inline] pub fn new_temp(ty: Ty<'tcx>, span: Span) -> Self { diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 1a1000f0bb41..d78418076245 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -1760,15 +1760,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } /// Appends end-user visible description of the `local` place to `buf`. If `local` doesn't have - /// a name, then `Err` is returned + /// a name, or its name was generated by the compiler, then `Err` is returned fn append_local_to_string(&self, local_index: Local, buf: &mut String) -> Result<(), ()> { let local = &self.mir.local_decls[local_index]; match local.name { - Some(name) => { - buf.push_str(&name.to_string()); + Some(name) if !local.from_compiler_desugaring() => { + buf.push_str(name.as_str().get()); Ok(()) } - None => Err(()), + _ => Err(()), } } diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 32088ff9f61e..f0b4efe26309 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -420,28 +420,31 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { ); } - if let Some(name) = local_decl.name { - err.span_label( - span, - format!( - "`{NAME}` is a `{SIGIL}` {DESC}, \ - so the data it refers to cannot be {ACTED_ON}", - NAME = name, - SIGIL = pointer_sigil, - DESC = pointer_desc, - ACTED_ON = acted_on - ), - ); - } else { - err.span_label( - span, - format!( - "cannot {ACT} through `{SIGIL}` {DESC}", - ACT = act, - SIGIL = pointer_sigil, - DESC = pointer_desc - ), - ); + match local_decl.name { + Some(name) if !local_decl.from_compiler_desugaring() => { + err.span_label( + span, + format!( + "`{NAME}` is a `{SIGIL}` {DESC}, \ + so the data it refers to cannot be {ACTED_ON}", + NAME = name, + SIGIL = pointer_sigil, + DESC = pointer_desc, + ACTED_ON = acted_on + ), + ); + } + _ => { + err.span_label( + span, + format!( + "cannot {ACT} through `{SIGIL}` {DESC}", + ACT = act, + SIGIL = pointer_sigil, + DESC = pointer_desc + ), + ); + } } } diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index 35efc6195be3..6bca470bf3e5 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -112,7 +112,7 @@ impl BorrowExplanation { }; match local_decl.name { - Some(local_name) => { + Some(local_name) if !local_decl.from_compiler_desugaring() => { let message = format!( "{B}borrow might be used here, when `{LOC}` is dropped \ and runs the {DTOR} for {TYPE}", @@ -130,7 +130,7 @@ impl BorrowExplanation { ); } } - None => { + _ => { err.span_label( local_decl.source_info.span, format!( diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 24d120376def..8083e00f6077 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -8423,6 +8423,8 @@ impl<'a> Parser<'a> { for (index, input) in decl.inputs.iter_mut().enumerate() { let id = ast::DUMMY_NODE_ID; let span = input.pat.span; + let desugared_span = self.sess.source_map() + .mark_span_with_reason(CompilerDesugaringKind::Async, span, None); // Construct a name for our temporary argument. let name = format!("__arg{}", index); @@ -8439,8 +8441,7 @@ impl<'a> Parser<'a> { // this would affect the input to procedural macros, but they can have // their span marked as being the result of a compiler desugaring so // that they aren't linted against. - input.pat.span = self.sess.source_map().mark_span_with_reason( - CompilerDesugaringKind::Async, span, None); + input.pat.span = desugared_span; (binding_mode, ident, true) } @@ -8460,7 +8461,7 @@ impl<'a> Parser<'a> { node: PatKind::Ident( BindingMode::ByValue(Mutability::Immutable), ident, None, ), - span, + span: desugared_span, }), source: ArgSource::AsyncFn(input.pat.clone()), }) @@ -8473,7 +8474,7 @@ impl<'a> Parser<'a> { pat: P(Pat { id, node: PatKind::Ident(binding_mode, ident, None), - span, + span: desugared_span, }), // We explicitly do not specify the type for this statement. When the user's // argument type is `impl Trait` then this would require the diff --git a/src/test/ui/nll/dont-print-desugared-async.rs b/src/test/ui/nll/dont-print-desugared-async.rs new file mode 100644 index 000000000000..8150a260866b --- /dev/null +++ b/src/test/ui/nll/dont-print-desugared-async.rs @@ -0,0 +1,9 @@ +// Test that we don't show variables with from async fn desugaring + +// edition:2018 +#![feature(async_await)] + +async fn async_fn(&ref mut s: &[i32]) {} +//~^ ERROR cannot borrow data in a `&` reference as mutable [E0596] + +fn main() {} diff --git a/src/test/ui/nll/dont-print-desugared-async.stderr b/src/test/ui/nll/dont-print-desugared-async.stderr new file mode 100644 index 000000000000..47726ba65df9 --- /dev/null +++ b/src/test/ui/nll/dont-print-desugared-async.stderr @@ -0,0 +1,12 @@ +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/dont-print-desugared-async.rs:6:20 + | +LL | async fn async_fn(&ref mut s: &[i32]) {} + | -^^^^^^^^^ + | || + | |cannot borrow as mutable through `&` reference + | help: consider changing this to be a mutable reference: `&mut ref mut s` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/nll/dont-print-desugared.rs b/src/test/ui/nll/dont-print-desugared.rs new file mode 100644 index 000000000000..829d78ed4c3b --- /dev/null +++ b/src/test/ui/nll/dont-print-desugared.rs @@ -0,0 +1,21 @@ +// Test that we don't show variables with from for loop desugaring + +fn for_loop(s: &[i32]) { + for &ref mut x in s {} + //~^ ERROR cannot borrow data in a `&` reference as mutable [E0596] +} + +struct D<'a>(&'a ()); + +impl Drop for D<'_> { + fn drop(&mut self) {} +} + +fn for_loop_dropck(v: Vec>) { + for ref mut d in v { + let y = (); + *d = D(&y); //~ ERROR `y` does not live long enough + } +} + +fn main() {} diff --git a/src/test/ui/nll/dont-print-desugared.stderr b/src/test/ui/nll/dont-print-desugared.stderr new file mode 100644 index 000000000000..45d7cbcdfbe7 --- /dev/null +++ b/src/test/ui/nll/dont-print-desugared.stderr @@ -0,0 +1,27 @@ +error[E0596]: cannot borrow data in a `&` reference as mutable + --> $DIR/dont-print-desugared.rs:4:10 + | +LL | for &ref mut x in s {} + | -^^^^^^^^^ + | || + | |cannot borrow as mutable through `&` reference + | help: consider changing this to be a mutable reference: `&mut ref mut x` + +error[E0597]: `y` does not live long enough + --> $DIR/dont-print-desugared.rs:17:16 + | +LL | for ref mut d in v { + | - a temporary with access to the borrow is created here ... +LL | let y = (); +LL | *d = D(&y); + | ^^ borrowed value does not live long enough +LL | } + | - + | | + | `y` dropped here while still borrowed + | ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0596, E0597. +For more information about an error, try `rustc --explain E0596`. From df5d07217271401217fce2d79f3ec75fa0e2b207 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 4 May 2019 08:40:07 +0100 Subject: [PATCH 0245/3207] Move conflict error reporting to its own module --- .../borrow_check/conflict_errors.rs | 1991 ++++++++++++++++ .../borrow_check/error_reporting.rs | 1998 +---------------- src/librustc_mir/borrow_check/mod.rs | 1 + 3 files changed, 2002 insertions(+), 1988 deletions(-) create mode 100644 src/librustc_mir/borrow_check/conflict_errors.rs diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs new file mode 100644 index 000000000000..19f29f346f96 --- /dev/null +++ b/src/librustc_mir/borrow_check/conflict_errors.rs @@ -0,0 +1,1991 @@ +use rustc::hir; +use rustc::hir::def_id::DefId; +use rustc::middle::region::ScopeTree; +use rustc::mir::{ + self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory, Local, + LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, PlaceProjection, + ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm, +}; +use rustc::ty::{self, Ty}; +use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::indexed_vec::Idx; +use rustc_errors::{Applicability, DiagnosticBuilder}; +use syntax_pos::Span; +use syntax::source_map::CompilerDesugaringKind; + +use super::nll::explain_borrow::BorrowExplanation; +use super::nll::region_infer::{RegionName, RegionNameSource}; +use super::prefixes::IsPrefixOf; +use super::WriteKind; +use super::borrow_set::BorrowData; +use super::MirBorrowckCtxt; +use super::{InitializationRequiringAction, PrefixSet}; +use super::error_reporting::{IncludingDowncast, UseSpans}; +use crate::dataflow::drop_flag_effects; +use crate::dataflow::indexes::{MovePathIndex, MoveOutIndex}; +use crate::util::borrowck_errors::{BorrowckErrors, Origin}; + +#[derive(Debug)] +struct MoveSite { + /// Index of the "move out" that we found. The `MoveData` can + /// then tell us where the move occurred. + moi: MoveOutIndex, + + /// `true` if we traversed a back edge while walking from the point + /// of error to the move site. + traversed_back_edge: bool +} + +/// Which case a StorageDeadOrDrop is for. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +enum StorageDeadOrDrop<'tcx> { + LocalStorageDead, + BoxedStorageDead, + Destructor(Ty<'tcx>), +} + +impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { + pub(super) fn report_use_of_moved_or_uninitialized( + &mut self, + location: Location, + desired_action: InitializationRequiringAction, + (moved_place, used_place, span): (&Place<'tcx>, &Place<'tcx>, Span), + mpi: MovePathIndex, + ) { + debug!( + "report_use_of_moved_or_uninitialized: location={:?} desired_action={:?} \ + moved_place={:?} used_place={:?} span={:?} mpi={:?}", + location, desired_action, moved_place, used_place, span, mpi + ); + + let use_spans = self.move_spans(moved_place, location) + .or_else(|| self.borrow_spans(span, location)); + let span = use_spans.args_or_use(); + + let move_site_vec = self.get_moved_indexes(location, mpi); + debug!( + "report_use_of_moved_or_uninitialized: move_site_vec={:?}", + move_site_vec + ); + let move_out_indices: Vec<_> = move_site_vec + .iter() + .map(|move_site| move_site.moi) + .collect(); + + if move_out_indices.is_empty() { + let root_place = self.prefixes(&used_place, PrefixSet::All).last().unwrap(); + + if self.uninitialized_error_reported.contains(root_place) { + debug!( + "report_use_of_moved_or_uninitialized place: error about {:?} suppressed", + root_place + ); + return; + } + + self.uninitialized_error_reported.insert(root_place.clone()); + + let item_msg = match self.describe_place_with_options(used_place, + IncludingDowncast(true)) { + Some(name) => format!("`{}`", name), + None => "value".to_owned(), + }; + let mut err = self.infcx.tcx.cannot_act_on_uninitialized_variable( + span, + desired_action.as_noun(), + &self.describe_place_with_options(moved_place, IncludingDowncast(true)) + .unwrap_or_else(|| "_".to_owned()), + Origin::Mir, + ); + err.span_label(span, format!("use of possibly uninitialized {}", item_msg)); + + use_spans.var_span_label( + &mut err, + format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()), + ); + + err.buffer(&mut self.errors_buffer); + } else { + if let Some((reported_place, _)) = self.move_error_reported.get(&move_out_indices) { + if self.prefixes(&reported_place, PrefixSet::All) + .any(|p| p == used_place) + { + debug!( + "report_use_of_moved_or_uninitialized place: error suppressed \ + mois={:?}", + move_out_indices + ); + return; + } + } + + let msg = ""; //FIXME: add "partially " or "collaterally " + + let mut err = self.infcx.tcx.cannot_act_on_moved_value( + span, + desired_action.as_noun(), + msg, + self.describe_place_with_options(&moved_place, IncludingDowncast(true)), + Origin::Mir, + ); + + self.add_moved_or_invoked_closure_note( + location, + used_place, + &mut err, + ); + + let mut is_loop_move = false; + let is_partial_move = move_site_vec.iter().any(|move_site| { + let move_out = self.move_data.moves[(*move_site).moi]; + let moved_place = &self.move_data.move_paths[move_out.path].place; + used_place != moved_place && used_place.is_prefix_of(moved_place) + }); + for move_site in &move_site_vec { + let move_out = self.move_data.moves[(*move_site).moi]; + let moved_place = &self.move_data.move_paths[move_out.path].place; + + let move_spans = self.move_spans(moved_place, move_out.source); + let move_span = move_spans.args_or_use(); + + let move_msg = if move_spans.for_closure() { + " into closure" + } else { + "" + }; + + if span == move_span { + err.span_label( + span, + format!("value moved{} here, in previous iteration of loop", move_msg), + ); + if Some(CompilerDesugaringKind::ForLoop) == span.compiler_desugaring_kind() { + if let Ok(snippet) = self.infcx.tcx.sess.source_map() + .span_to_snippet(span) + { + err.span_suggestion( + move_span, + "consider borrowing this to avoid moving it into the for loop", + format!("&{}", snippet), + Applicability::MaybeIncorrect, + ); + } + } + is_loop_move = true; + } else if move_site.traversed_back_edge { + err.span_label( + move_span, + format!( + "value moved{} here, in previous iteration of loop", + move_msg + ), + ); + } else { + err.span_label(move_span, format!("value moved{} here", move_msg)); + move_spans.var_span_label( + &mut err, + format!("variable moved due to use{}", move_spans.describe()), + ); + }; + } + + use_spans.var_span_label( + &mut err, + format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()), + ); + + if !is_loop_move { + err.span_label( + span, + format!( + "value {} here {}", + desired_action.as_verb_in_past_tense(), + if is_partial_move { "after partial move" } else { "after move" }, + ), + ); + } + + let ty = used_place.ty(self.mir, self.infcx.tcx).ty; + let needs_note = match ty.sty { + ty::Closure(id, _) => { + let tables = self.infcx.tcx.typeck_tables_of(id); + let hir_id = self.infcx.tcx.hir().as_local_hir_id(id).unwrap(); + + tables.closure_kind_origins().get(hir_id).is_none() + } + _ => true, + }; + + if needs_note { + let mpi = self.move_data.moves[move_out_indices[0]].path; + let place = &self.move_data.move_paths[mpi].place; + + let ty = place.ty(self.mir, self.infcx.tcx).ty; + let opt_name = self.describe_place_with_options(place, IncludingDowncast(true)); + let note_msg = match opt_name { + Some(ref name) => format!("`{}`", name), + None => "value".to_owned(), + }; + if let ty::Param(param_ty) = ty.sty { + let tcx = self.infcx.tcx; + let generics = tcx.generics_of(self.mir_def_id); + let def_id = generics.type_param(¶m_ty, tcx).def_id; + if let Some(sp) = tcx.hir().span_if_local(def_id) { + err.span_label( + sp, + "consider adding a `Copy` constraint to this type argument", + ); + } + } + if let Place::Base(PlaceBase::Local(local)) = place { + let decl = &self.mir.local_decls[*local]; + err.span_label( + decl.source_info.span, + format!( + "move occurs because {} has type `{}`, \ + which does not implement the `Copy` trait", + note_msg, ty, + )); + } else { + err.note(&format!( + "move occurs because {} has type `{}`, \ + which does not implement the `Copy` trait", + note_msg, ty + )); + } + } + + if let Some((_, mut old_err)) = self.move_error_reported + .insert(move_out_indices, (used_place.clone(), err)) + { + // Cancel the old error so it doesn't ICE. + old_err.cancel(); + } + } + } + + pub(super) fn report_move_out_while_borrowed( + &mut self, + location: Location, + (place, span): (&Place<'tcx>, Span), + borrow: &BorrowData<'tcx>, + ) { + debug!( + "report_move_out_while_borrowed: location={:?} place={:?} span={:?} borrow={:?}", + location, place, span, borrow + ); + let tcx = self.infcx.tcx; + let value_msg = match self.describe_place(place) { + Some(name) => format!("`{}`", name), + None => "value".to_owned(), + }; + let borrow_msg = match self.describe_place(&borrow.borrowed_place) { + Some(name) => format!("`{}`", name), + None => "value".to_owned(), + }; + + let borrow_spans = self.retrieve_borrow_spans(borrow); + let borrow_span = borrow_spans.args_or_use(); + + let move_spans = self.move_spans(place, location); + let span = move_spans.args_or_use(); + + let mut err = tcx.cannot_move_when_borrowed( + span, + &self.describe_place(place).unwrap_or_else(|| "_".to_owned()), + Origin::Mir, + ); + err.span_label(borrow_span, format!("borrow of {} occurs here", borrow_msg)); + err.span_label(span, format!("move out of {} occurs here", value_msg)); + + borrow_spans.var_span_label( + &mut err, + format!("borrow occurs due to use{}", borrow_spans.describe()) + ); + + move_spans.var_span_label( + &mut err, + format!("move occurs due to use{}", move_spans.describe()) + ); + + self.explain_why_borrow_contains_point( + location, + borrow, + None, + ).add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", Some(borrow_span)); + err.buffer(&mut self.errors_buffer); + } + + pub(super) fn report_use_while_mutably_borrowed( + &mut self, + location: Location, + (place, _span): (&Place<'tcx>, Span), + borrow: &BorrowData<'tcx>, + ) -> DiagnosticBuilder<'cx> { + let tcx = self.infcx.tcx; + + let borrow_spans = self.retrieve_borrow_spans(borrow); + let borrow_span = borrow_spans.args_or_use(); + + // Conflicting borrows are reported separately, so only check for move + // captures. + let use_spans = self.move_spans(place, location); + let span = use_spans.var_or_use(); + + let mut err = tcx.cannot_use_when_mutably_borrowed( + span, + &self.describe_place(place).unwrap_or_else(|| "_".to_owned()), + borrow_span, + &self.describe_place(&borrow.borrowed_place) + .unwrap_or_else(|| "_".to_owned()), + Origin::Mir, + ); + + borrow_spans.var_span_label(&mut err, { + let place = &borrow.borrowed_place; + let desc_place = self.describe_place(place).unwrap_or_else(|| "_".to_owned()); + + format!("borrow occurs due to use of `{}`{}", desc_place, borrow_spans.describe()) + }); + + self.explain_why_borrow_contains_point(location, borrow, None) + .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None); + err + } + + pub(super) fn report_conflicting_borrow( + &mut self, + location: Location, + (place, span): (&Place<'tcx>, Span), + gen_borrow_kind: BorrowKind, + issued_borrow: &BorrowData<'tcx>, + ) -> DiagnosticBuilder<'cx> { + let issued_spans = self.retrieve_borrow_spans(issued_borrow); + let issued_span = issued_spans.args_or_use(); + + let borrow_spans = self.borrow_spans(span, location); + let span = borrow_spans.args_or_use(); + + let container_name = if issued_spans.for_generator() || borrow_spans.for_generator() { + "generator" + } else { + "closure" + }; + + let (desc_place, msg_place, msg_borrow, union_type_name) = + self.describe_place_for_conflicting_borrow(place, &issued_borrow.borrowed_place); + + let explanation = self.explain_why_borrow_contains_point(location, issued_borrow, None); + let second_borrow_desc = if explanation.is_explained() { + "second " + } else { + "" + }; + + // FIXME: supply non-"" `opt_via` when appropriate + let tcx = self.infcx.tcx; + let first_borrow_desc; + let mut err = match ( + gen_borrow_kind, + "immutable", + "mutable", + issued_borrow.kind, + "immutable", + "mutable", + ) { + (BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt) => { + first_borrow_desc = "mutable "; + tcx.cannot_reborrow_already_borrowed( + span, + &desc_place, + &msg_place, + lft, + issued_span, + "it", + rgt, + &msg_borrow, + None, + Origin::Mir, + ) + } + (BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => { + first_borrow_desc = "immutable "; + tcx.cannot_reborrow_already_borrowed( + span, + &desc_place, + &msg_place, + lft, + issued_span, + "it", + rgt, + &msg_borrow, + None, + Origin::Mir, + ) + } + + (BorrowKind::Mut { .. }, _, _, BorrowKind::Mut { .. }, _, _) => { + first_borrow_desc = "first "; + tcx.cannot_mutably_borrow_multiply( + span, + &desc_place, + &msg_place, + issued_span, + &msg_borrow, + None, + Origin::Mir, + ) + } + + (BorrowKind::Unique, _, _, BorrowKind::Unique, _, _) => { + first_borrow_desc = "first "; + tcx.cannot_uniquely_borrow_by_two_closures( + span, + &desc_place, + issued_span, + None, + Origin::Mir, + ) + } + + (BorrowKind::Mut { .. }, _, _, BorrowKind::Shallow, _, _) + | (BorrowKind::Unique, _, _, BorrowKind::Shallow, _, _) => { + let mut err = tcx.cannot_mutate_in_match_guard( + span, + issued_span, + &desc_place, + "mutably borrow", + Origin::Mir, + ); + borrow_spans.var_span_label( + &mut err, + format!( + "borrow occurs due to use of `{}`{}", desc_place, borrow_spans.describe() + ), + ); + + return err; + } + + (BorrowKind::Unique, _, _, _, _, _) => { + first_borrow_desc = "first "; + tcx.cannot_uniquely_borrow_by_one_closure( + span, + container_name, + &desc_place, + "", + issued_span, + "it", + "", + None, + Origin::Mir, + ) + }, + + (BorrowKind::Shared, lft, _, BorrowKind::Unique, _, _) => { + first_borrow_desc = "first "; + tcx.cannot_reborrow_already_uniquely_borrowed( + span, + container_name, + &desc_place, + "", + lft, + issued_span, + "", + None, + second_borrow_desc, + Origin::Mir, + ) + } + + (BorrowKind::Mut { .. }, _, lft, BorrowKind::Unique, _, _) => { + first_borrow_desc = "first "; + tcx.cannot_reborrow_already_uniquely_borrowed( + span, + container_name, + &desc_place, + "", + lft, + issued_span, + "", + None, + second_borrow_desc, + Origin::Mir, + ) + } + + (BorrowKind::Shared, _, _, BorrowKind::Shared, _, _) + | (BorrowKind::Shared, _, _, BorrowKind::Shallow, _, _) + | (BorrowKind::Shallow, _, _, BorrowKind::Mut { .. }, _, _) + | (BorrowKind::Shallow, _, _, BorrowKind::Unique, _, _) + | (BorrowKind::Shallow, _, _, BorrowKind::Shared, _, _) + | (BorrowKind::Shallow, _, _, BorrowKind::Shallow, _, _) => unreachable!(), + }; + + if issued_spans == borrow_spans { + borrow_spans.var_span_label( + &mut err, + format!("borrows occur due to use of `{}`{}", desc_place, borrow_spans.describe()), + ); + } else { + let borrow_place = &issued_borrow.borrowed_place; + let borrow_place_desc = self.describe_place(borrow_place) + .unwrap_or_else(|| "_".to_owned()); + issued_spans.var_span_label( + &mut err, + format!( + "first borrow occurs due to use of `{}`{}", + borrow_place_desc, + issued_spans.describe(), + ), + ); + + borrow_spans.var_span_label( + &mut err, + format!( + "second borrow occurs due to use of `{}`{}", + desc_place, + borrow_spans.describe(), + ), + ); + } + + if union_type_name != "" { + err.note(&format!( + "`{}` is a field of the union `{}`, so it overlaps the field `{}`", + msg_place, union_type_name, msg_borrow, + )); + } + + explanation.add_explanation_to_diagnostic( + self.infcx.tcx, + self.mir, + &mut err, + first_borrow_desc, + None, + ); + + err + } + + /// Returns the description of the root place for a conflicting borrow and the full + /// descriptions of the places that caused the conflict. + /// + /// In the simplest case, where there are no unions involved, if a mutable borrow of `x` is + /// attempted while a shared borrow is live, then this function will return: + /// + /// ("x", "", "") + /// + /// In the simple union case, if a mutable borrow of a union field `x.z` is attempted while + /// a shared borrow of another field `x.y`, then this function will return: + /// + /// ("x", "x.z", "x.y") + /// + /// In the more complex union case, where the union is a field of a struct, then if a mutable + /// borrow of a union field in a struct `x.u.z` is attempted while a shared borrow of + /// another field `x.u.y`, then this function will return: + /// + /// ("x.u", "x.u.z", "x.u.y") + /// + /// This is used when creating error messages like below: + /// + /// > cannot borrow `a.u` (via `a.u.z.c`) as immutable because it is also borrowed as + /// > mutable (via `a.u.s.b`) [E0502] + pub(super) fn describe_place_for_conflicting_borrow( + &self, + first_borrowed_place: &Place<'tcx>, + second_borrowed_place: &Place<'tcx>, + ) -> (String, String, String, String) { + // Define a small closure that we can use to check if the type of a place + // is a union. + let is_union = |place: &Place<'tcx>| -> bool { + place.ty(self.mir, self.infcx.tcx).ty + .ty_adt_def() + .map(|adt| adt.is_union()) + .unwrap_or(false) + }; + + // Start with an empty tuple, so we can use the functions on `Option` to reduce some + // code duplication (particularly around returning an empty description in the failure + // case). + Some(()) + .filter(|_| { + // If we have a conflicting borrow of the same place, then we don't want to add + // an extraneous "via x.y" to our diagnostics, so filter out this case. + first_borrowed_place != second_borrowed_place + }) + .and_then(|_| { + // We're going to want to traverse the first borrowed place to see if we can find + // field access to a union. If we find that, then we will keep the place of the + // union being accessed and the field that was being accessed so we can check the + // second borrowed place for the same union and a access to a different field. + let mut current = first_borrowed_place; + while let Place::Projection(box PlaceProjection { base, elem }) = current { + match elem { + ProjectionElem::Field(field, _) if is_union(base) => { + return Some((base, field)); + }, + _ => current = base, + } + } + None + }) + .and_then(|(target_base, target_field)| { + // With the place of a union and a field access into it, we traverse the second + // borrowed place and look for a access to a different field of the same union. + let mut current = second_borrowed_place; + while let Place::Projection(box PlaceProjection { base, elem }) = current { + match elem { + ProjectionElem::Field(field, _) if { + is_union(base) && field != target_field && base == target_base + } => { + let desc_base = self.describe_place(base) + .unwrap_or_else(|| "_".to_owned()); + let desc_first = self.describe_place(first_borrowed_place) + .unwrap_or_else(|| "_".to_owned()); + let desc_second = self.describe_place(second_borrowed_place) + .unwrap_or_else(|| "_".to_owned()); + + // Also compute the name of the union type, eg. `Foo` so we + // can add a helpful note with it. + let ty = base.ty(self.mir, self.infcx.tcx).ty; + + return Some((desc_base, desc_first, desc_second, ty.to_string())); + }, + _ => current = base, + } + } + None + }) + .unwrap_or_else(|| { + // If we didn't find a field access into a union, or both places match, then + // only return the description of the first place. + let desc_place = self.describe_place(first_borrowed_place) + .unwrap_or_else(|| "_".to_owned()); + (desc_place, "".to_string(), "".to_string(), "".to_string()) + }) + } + + /// Reports StorageDeadOrDrop of `place` conflicts with `borrow`. + /// + /// This means that some data referenced by `borrow` needs to live + /// past the point where the StorageDeadOrDrop of `place` occurs. + /// This is usually interpreted as meaning that `place` has too + /// short a lifetime. (But sometimes it is more useful to report + /// it as a more direct conflict between the execution of a + /// `Drop::drop` with an aliasing borrow.) + pub(super) fn report_borrowed_value_does_not_live_long_enough( + &mut self, + location: Location, + borrow: &BorrowData<'tcx>, + place_span: (&Place<'tcx>, Span), + kind: Option, + ) { + debug!( + "report_borrowed_value_does_not_live_long_enough(\ + {:?}, {:?}, {:?}, {:?}\ + )", + location, borrow, place_span, kind + ); + + let drop_span = place_span.1; + let scope_tree = self.infcx.tcx.region_scope_tree(self.mir_def_id); + let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All) + .last() + .unwrap(); + + let borrow_spans = self.retrieve_borrow_spans(borrow); + let borrow_span = borrow_spans.var_or_use(); + + let proper_span = match *root_place { + Place::Base(PlaceBase::Local(local)) => self.mir.local_decls[local].source_info.span, + _ => drop_span, + }; + + if self.access_place_error_reported + .contains(&(root_place.clone(), borrow_span)) + { + debug!( + "suppressing access_place error when borrow doesn't live long enough for {:?}", + borrow_span + ); + return; + } + + self.access_place_error_reported + .insert((root_place.clone(), borrow_span)); + + if let StorageDeadOrDrop::Destructor(dropped_ty) = + self.classify_drop_access_kind(&borrow.borrowed_place) + { + // If a borrow of path `B` conflicts with drop of `D` (and + // we're not in the uninteresting case where `B` is a + // prefix of `D`), then report this as a more interesting + // destructor conflict. + if !borrow.borrowed_place.is_prefix_of(place_span.0) { + self.report_borrow_conflicts_with_destructor( + location, borrow, place_span, kind, dropped_ty, + ); + return; + } + } + + let place_desc = self.describe_place(&borrow.borrowed_place); + + let kind_place = kind.filter(|_| place_desc.is_some()).map(|k| (k, place_span.0)); + let explanation = self.explain_why_borrow_contains_point(location, &borrow, kind_place); + + let err = match (place_desc, explanation) { + (Some(_), _) if self.is_place_thread_local(root_place) => { + self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span) + } + // If the outlives constraint comes from inside the closure, + // for example: + // + // let x = 0; + // let y = &x; + // Box::new(|| y) as Box &'static i32> + // + // then just use the normal error. The closure isn't escaping + // and `move` will not help here. + ( + Some(ref name), + BorrowExplanation::MustBeValidFor { + category: category @ ConstraintCategory::Return, + from_closure: false, + ref region_name, + span, + .. + }, + ) + | ( + Some(ref name), + BorrowExplanation::MustBeValidFor { + category: category @ ConstraintCategory::CallArgument, + from_closure: false, + ref region_name, + span, + .. + }, + ) if borrow_spans.for_closure() => self.report_escaping_closure_capture( + borrow_spans.args_or_use(), + borrow_span, + region_name, + category, + span, + &format!("`{}`", name), + ), + ( + ref name, + BorrowExplanation::MustBeValidFor { + category: ConstraintCategory::Assignment, + from_closure: false, + region_name: RegionName { + source: RegionNameSource::AnonRegionFromUpvar(upvar_span, ref upvar_name), + .. + }, + span, + .. + }, + ) => self.report_escaping_data(borrow_span, name, upvar_span, upvar_name, span), + (Some(name), explanation) => self.report_local_value_does_not_live_long_enough( + location, + &name, + &scope_tree, + &borrow, + drop_span, + borrow_spans, + explanation, + ), + (None, explanation) => self.report_temporary_value_does_not_live_long_enough( + location, + &scope_tree, + &borrow, + drop_span, + borrow_spans, + proper_span, + explanation, + ), + }; + + err.buffer(&mut self.errors_buffer); + } + + fn report_local_value_does_not_live_long_enough( + &mut self, + location: Location, + name: &str, + scope_tree: &'tcx ScopeTree, + borrow: &BorrowData<'tcx>, + drop_span: Span, + borrow_spans: UseSpans, + explanation: BorrowExplanation, + ) -> DiagnosticBuilder<'cx> { + debug!( + "report_local_value_does_not_live_long_enough(\ + {:?}, {:?}, {:?}, {:?}, {:?}, {:?}\ + )", + location, name, scope_tree, borrow, drop_span, borrow_spans + ); + + let borrow_span = borrow_spans.var_or_use(); + if let BorrowExplanation::MustBeValidFor { + category, + span, + ref opt_place_desc, + from_closure: false, + .. + } = explanation { + if let Some(diag) = self.try_report_cannot_return_reference_to_local( + borrow, + borrow_span, + span, + category, + opt_place_desc.as_ref(), + ) { + return diag; + } + } + + let mut err = self.infcx.tcx.path_does_not_live_long_enough( + borrow_span, + &format!("`{}`", name), + Origin::Mir, + ); + + if let Some(annotation) = self.annotate_argument_and_return_for_borrow(borrow) { + let region_name = annotation.emit(self, &mut err); + + err.span_label( + borrow_span, + format!("`{}` would have to be valid for `{}`...", name, region_name), + ); + + if let Some(fn_hir_id) = self.infcx.tcx.hir().as_local_hir_id(self.mir_def_id) { + err.span_label( + drop_span, + format!( + "...but `{}` will be dropped here, when the function `{}` returns", + name, + self.infcx.tcx.hir().name_by_hir_id(fn_hir_id), + ), + ); + + err.note( + "functions cannot return a borrow to data owned within the function's scope, \ + functions can only return borrows to data passed as arguments", + ); + err.note( + "to learn more, visit ", + ); + } else { + err.span_label( + drop_span, + format!("...but `{}` dropped here while still borrowed", name), + ); + } + + if let BorrowExplanation::MustBeValidFor { .. } = explanation { + } else { + explanation.add_explanation_to_diagnostic( + self.infcx.tcx, + self.mir, + &mut err, + "", + None, + ); + } + } else { + err.span_label(borrow_span, "borrowed value does not live long enough"); + err.span_label( + drop_span, + format!("`{}` dropped here while still borrowed", name), + ); + + let within = if borrow_spans.for_generator() { + " by generator" + } else { + "" + }; + + borrow_spans.args_span_label( + &mut err, + format!("value captured here{}", within), + ); + + explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None); + } + + err + } + + fn report_borrow_conflicts_with_destructor( + &mut self, + location: Location, + borrow: &BorrowData<'tcx>, + (place, drop_span): (&Place<'tcx>, Span), + kind: Option, + dropped_ty: Ty<'tcx>, + ) { + debug!( + "report_borrow_conflicts_with_destructor(\ + {:?}, {:?}, ({:?}, {:?}), {:?}\ + )", + location, borrow, place, drop_span, kind, + ); + + let borrow_spans = self.retrieve_borrow_spans(borrow); + let borrow_span = borrow_spans.var_or_use(); + + let mut err = self.infcx + .tcx + .cannot_borrow_across_destructor(borrow_span, Origin::Mir); + + let what_was_dropped = match self.describe_place(place) { + Some(name) => format!("`{}`", name.as_str()), + None => String::from("temporary value"), + }; + + let label = match self.describe_place(&borrow.borrowed_place) { + Some(borrowed) => format!( + "here, drop of {D} needs exclusive access to `{B}`, \ + because the type `{T}` implements the `Drop` trait", + D = what_was_dropped, + T = dropped_ty, + B = borrowed + ), + None => format!( + "here is drop of {D}; whose type `{T}` implements the `Drop` trait", + D = what_was_dropped, + T = dropped_ty + ), + }; + err.span_label(drop_span, label); + + // Only give this note and suggestion if they could be relevant. + let explanation = + self.explain_why_borrow_contains_point(location, borrow, kind.map(|k| (k, place))); + match explanation { + BorrowExplanation::UsedLater { .. } + | BorrowExplanation::UsedLaterWhenDropped { .. } => { + err.note("consider using a `let` binding to create a longer lived value"); + } + _ => {} + } + + explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None); + + err.buffer(&mut self.errors_buffer); + } + + fn report_thread_local_value_does_not_live_long_enough( + &mut self, + drop_span: Span, + borrow_span: Span, + ) -> DiagnosticBuilder<'cx> { + debug!( + "report_thread_local_value_does_not_live_long_enough(\ + {:?}, {:?}\ + )", + drop_span, borrow_span + ); + + let mut err = self.infcx + .tcx + .thread_local_value_does_not_live_long_enough(borrow_span, Origin::Mir); + + err.span_label( + borrow_span, + "thread-local variables cannot be borrowed beyond the end of the function", + ); + err.span_label(drop_span, "end of enclosing function is here"); + + err + } + + fn report_temporary_value_does_not_live_long_enough( + &mut self, + location: Location, + scope_tree: &'tcx ScopeTree, + borrow: &BorrowData<'tcx>, + drop_span: Span, + borrow_spans: UseSpans, + proper_span: Span, + explanation: BorrowExplanation, + ) -> DiagnosticBuilder<'cx> { + debug!( + "report_temporary_value_does_not_live_long_enough(\ + {:?}, {:?}, {:?}, {:?}, {:?}\ + )", + location, scope_tree, borrow, drop_span, proper_span + ); + + if let BorrowExplanation::MustBeValidFor { + category, + span, + from_closure: false, + .. + } = explanation { + if let Some(diag) = self.try_report_cannot_return_reference_to_local( + borrow, + proper_span, + span, + category, + None, + ) { + return diag; + } + } + + let tcx = self.infcx.tcx; + let mut err = tcx.temporary_value_borrowed_for_too_long(proper_span, Origin::Mir); + err.span_label( + proper_span, + "creates a temporary which is freed while still in use", + ); + err.span_label( + drop_span, + "temporary value is freed at the end of this statement", + ); + + match explanation { + BorrowExplanation::UsedLater(..) + | BorrowExplanation::UsedLaterInLoop(..) + | BorrowExplanation::UsedLaterWhenDropped { .. } => { + // Only give this note and suggestion if it could be relevant. + err.note("consider using a `let` binding to create a longer lived value"); + } + _ => {} + } + explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None); + + let within = if borrow_spans.for_generator() { + " by generator" + } else { + "" + }; + + borrow_spans.args_span_label( + &mut err, + format!("value captured here{}", within), + ); + + err + } + + fn try_report_cannot_return_reference_to_local( + &self, + borrow: &BorrowData<'tcx>, + borrow_span: Span, + return_span: Span, + category: ConstraintCategory, + opt_place_desc: Option<&String>, + ) -> Option> { + let tcx = self.infcx.tcx; + + let return_kind = match category { + ConstraintCategory::Return => "return", + ConstraintCategory::Yield => "yield", + _ => return None, + }; + + // FIXME use a better heuristic than Spans + let reference_desc = if return_span == self.mir.source_info(borrow.reserve_location).span { + "reference to" + } else { + "value referencing" + }; + + let (place_desc, note) = if let Some(place_desc) = opt_place_desc { + let local_kind = match borrow.borrowed_place { + Place::Base(PlaceBase::Local(local)) => { + match self.mir.local_kind(local) { + LocalKind::ReturnPointer + | LocalKind::Temp => bug!("temporary or return pointer with a name"), + LocalKind::Var => "local variable ", + LocalKind::Arg + if !self.upvars.is_empty() + && local == Local::new(1) => { + "variable captured by `move` " + } + LocalKind::Arg => { + "function parameter " + } + } + } + _ => "local data ", + }; + ( + format!("{}`{}`", local_kind, place_desc), + format!("`{}` is borrowed here", place_desc), + ) + } else { + let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All) + .last() + .unwrap(); + let local = if let Place::Base(PlaceBase::Local(local)) = *root_place { + local + } else { + bug!("try_report_cannot_return_reference_to_local: not a local") + }; + match self.mir.local_kind(local) { + LocalKind::ReturnPointer | LocalKind::Temp => { + ( + "temporary value".to_string(), + "temporary value created here".to_string(), + ) + } + LocalKind::Arg => { + ( + "function parameter".to_string(), + "function parameter borrowed here".to_string(), + ) + }, + LocalKind::Var => bug!("local variable without a name"), + } + }; + + let mut err = tcx.cannot_return_reference_to_local( + return_span, + return_kind, + reference_desc, + &place_desc, + Origin::Mir, + ); + + if return_span != borrow_span { + err.span_label(borrow_span, note); + } + + Some(err) + } + + fn report_escaping_closure_capture( + &mut self, + args_span: Span, + var_span: Span, + fr_name: &RegionName, + category: ConstraintCategory, + constraint_span: Span, + captured_var: &str, + ) -> DiagnosticBuilder<'cx> { + let tcx = self.infcx.tcx; + + let mut err = tcx.cannot_capture_in_long_lived_closure( + args_span, + captured_var, + var_span, + Origin::Mir, + ); + + let suggestion = match tcx.sess.source_map().span_to_snippet(args_span) { + Ok(string) => format!("move {}", string), + Err(_) => "move || ".to_string() + }; + + err.span_suggestion( + args_span, + &format!("to force the closure to take ownership of {} (and any \ + other referenced variables), use the `move` keyword", + captured_var), + suggestion, + Applicability::MachineApplicable, + ); + + match category { + ConstraintCategory::Return => { + err.span_note(constraint_span, "closure is returned here"); + } + ConstraintCategory::CallArgument => { + fr_name.highlight_region_name(&mut err); + err.span_note( + constraint_span, + &format!("function requires argument type to outlive `{}`", fr_name), + ); + } + _ => bug!("report_escaping_closure_capture called with unexpected constraint \ + category: `{:?}`", category), + } + err + } + + fn report_escaping_data( + &mut self, + borrow_span: Span, + name: &Option, + upvar_span: Span, + upvar_name: &str, + escape_span: Span, + ) -> DiagnosticBuilder<'cx> { + let tcx = self.infcx.tcx; + + let escapes_from = if tcx.is_closure(self.mir_def_id) { + let tables = tcx.typeck_tables_of(self.mir_def_id); + let mir_hir_id = tcx.hir().def_index_to_hir_id(self.mir_def_id.index); + match tables.node_type(mir_hir_id).sty { + ty::Closure(..) => "closure", + ty::Generator(..) => "generator", + _ => bug!("Closure body doesn't have a closure or generator type"), + } + } else { + "function" + }; + + let mut err = tcx.borrowed_data_escapes_closure(escape_span, escapes_from, Origin::Mir); + + err.span_label( + upvar_span, + format!( + "`{}` is declared here, outside of the {} body", + upvar_name, escapes_from + ), + ); + + err.span_label( + borrow_span, + format!( + "borrow is only valid in the {} body", + escapes_from + ), + ); + + if let Some(name) = name { + err.span_label( + escape_span, + format!("reference to `{}` escapes the {} body here", name, escapes_from), + ); + } else { + err.span_label( + escape_span, + format!("reference escapes the {} body here", escapes_from), + ); + } + + err + } + + fn get_moved_indexes(&mut self, location: Location, mpi: MovePathIndex) -> Vec { + let mir = self.mir; + + let mut stack = Vec::new(); + stack.extend(mir.predecessor_locations(location).map(|predecessor| { + let is_back_edge = location.dominates(predecessor, &self.dominators); + (predecessor, is_back_edge) + })); + + let mut visited = FxHashSet::default(); + let mut result = vec![]; + + 'dfs: while let Some((location, is_back_edge)) = stack.pop() { + debug!( + "report_use_of_moved_or_uninitialized: (current_location={:?}, back_edge={})", + location, is_back_edge + ); + + if !visited.insert(location) { + continue; + } + + // check for moves + let stmt_kind = mir[location.block] + .statements + .get(location.statement_index) + .map(|s| &s.kind); + if let Some(StatementKind::StorageDead(..)) = stmt_kind { + // this analysis only tries to find moves explicitly + // written by the user, so we ignore the move-outs + // created by `StorageDead` and at the beginning + // of a function. + } else { + // If we are found a use of a.b.c which was in error, then we want to look for + // moves not only of a.b.c but also a.b and a. + // + // Note that the moves data already includes "parent" paths, so we don't have to + // worry about the other case: that is, if there is a move of a.b.c, it is already + // marked as a move of a.b and a as well, so we will generate the correct errors + // there. + let mut mpis = vec![mpi]; + let move_paths = &self.move_data.move_paths; + mpis.extend(move_paths[mpi].parents(move_paths)); + + for moi in &self.move_data.loc_map[location] { + debug!("report_use_of_moved_or_uninitialized: moi={:?}", moi); + if mpis.contains(&self.move_data.moves[*moi].path) { + debug!("report_use_of_moved_or_uninitialized: found"); + result.push(MoveSite { + moi: *moi, + traversed_back_edge: is_back_edge, + }); + + // Strictly speaking, we could continue our DFS here. There may be + // other moves that can reach the point of error. But it is kind of + // confusing to highlight them. + // + // Example: + // + // ``` + // let a = vec![]; + // let b = a; + // let c = a; + // drop(a); // <-- current point of error + // ``` + // + // Because we stop the DFS here, we only highlight `let c = a`, + // and not `let b = a`. We will of course also report an error at + // `let c = a` which highlights `let b = a` as the move. + continue 'dfs; + } + } + } + + // check for inits + let mut any_match = false; + drop_flag_effects::for_location_inits( + self.infcx.tcx, + self.mir, + self.move_data, + location, + |m| { + if m == mpi { + any_match = true; + } + }, + ); + if any_match { + continue 'dfs; + } + + stack.extend(mir.predecessor_locations(location).map(|predecessor| { + let back_edge = location.dominates(predecessor, &self.dominators); + (predecessor, is_back_edge || back_edge) + })); + } + + result + } + + pub(super) fn report_illegal_mutation_of_borrowed( + &mut self, + location: Location, + (place, span): (&Place<'tcx>, Span), + loan: &BorrowData<'tcx>, + ) { + let loan_spans = self.retrieve_borrow_spans(loan); + let loan_span = loan_spans.args_or_use(); + + let tcx = self.infcx.tcx; + if loan.kind == BorrowKind::Shallow { + let mut err = tcx.cannot_mutate_in_match_guard( + span, + loan_span, + &self.describe_place(place).unwrap_or_else(|| "_".to_owned()), + "assign", + Origin::Mir, + ); + loan_spans.var_span_label( + &mut err, + format!("borrow occurs due to use{}", loan_spans.describe()), + ); + + err.buffer(&mut self.errors_buffer); + + return; + } + + let mut err = tcx.cannot_assign_to_borrowed( + span, + loan_span, + &self.describe_place(place).unwrap_or_else(|| "_".to_owned()), + Origin::Mir, + ); + + loan_spans.var_span_label( + &mut err, + format!("borrow occurs due to use{}", loan_spans.describe()), + ); + + self.explain_why_borrow_contains_point(location, loan, None) + .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None); + + err.buffer(&mut self.errors_buffer); + } + + /// Reports an illegal reassignment; for example, an assignment to + /// (part of) a non-`mut` local that occurs potentially after that + /// local has already been initialized. `place` is the path being + /// assigned; `err_place` is a place providing a reason why + /// `place` is not mutable (e.g., the non-`mut` local `x` in an + /// assignment to `x.f`). + pub(super) fn report_illegal_reassignment( + &mut self, + _location: Location, + (place, span): (&Place<'tcx>, Span), + assigned_span: Span, + err_place: &Place<'tcx>, + ) { + let (from_arg, local_decl) = if let Place::Base(PlaceBase::Local(local)) = *err_place { + if let LocalKind::Arg = self.mir.local_kind(local) { + (true, Some(&self.mir.local_decls[local])) + } else { + (false, Some(&self.mir.local_decls[local])) + } + } else { + (false, None) + }; + + // If root local is initialized immediately (everything apart from let + // PATTERN;) then make the error refer to that local, rather than the + // place being assigned later. + let (place_description, assigned_span) = match local_decl { + Some(LocalDecl { + is_user_variable: Some(ClearCrossCrate::Clear), + .. + }) + | Some(LocalDecl { + is_user_variable: + Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { + opt_match_place: None, + .. + }))), + .. + }) + | Some(LocalDecl { + is_user_variable: None, + .. + }) + | None => (self.describe_place(place), assigned_span), + Some(decl) => (self.describe_place(err_place), decl.source_info.span), + }; + + let mut err = self.infcx.tcx.cannot_reassign_immutable( + span, + place_description.as_ref().map(AsRef::as_ref).unwrap_or("_"), + from_arg, + Origin::Mir, + ); + let msg = if from_arg { + "cannot assign to immutable argument" + } else { + "cannot assign twice to immutable variable" + }; + if span != assigned_span { + if !from_arg { + let value_msg = match place_description { + Some(name) => format!("`{}`", name), + None => "value".to_owned(), + }; + err.span_label(assigned_span, format!("first assignment to {}", value_msg)); + } + } + if let Some(decl) = local_decl { + if let Some(name) = decl.name { + if decl.can_be_made_mutable() { + err.span_suggestion( + decl.source_info.span, + "make this binding mutable", + format!("mut {}", name), + Applicability::MachineApplicable, + ); + } + } + } + err.span_label(span, msg); + err.buffer(&mut self.errors_buffer); + } + + fn classify_drop_access_kind(&self, place: &Place<'tcx>) -> StorageDeadOrDrop<'tcx> { + let tcx = self.infcx.tcx; + match place { + Place::Base(PlaceBase::Local(_)) | + Place::Base(PlaceBase::Static(_)) => { + StorageDeadOrDrop::LocalStorageDead + } + Place::Projection(box PlaceProjection { base, elem }) => { + let base_access = self.classify_drop_access_kind(base); + match elem { + ProjectionElem::Deref => match base_access { + StorageDeadOrDrop::LocalStorageDead + | StorageDeadOrDrop::BoxedStorageDead => { + assert!( + base.ty(self.mir, tcx).ty.is_box(), + "Drop of value behind a reference or raw pointer" + ); + StorageDeadOrDrop::BoxedStorageDead + } + StorageDeadOrDrop::Destructor(_) => base_access, + }, + ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => { + let base_ty = base.ty(self.mir, tcx).ty; + match base_ty.sty { + ty::Adt(def, _) if def.has_dtor(tcx) => { + // Report the outermost adt with a destructor + match base_access { + StorageDeadOrDrop::Destructor(_) => base_access, + StorageDeadOrDrop::LocalStorageDead + | StorageDeadOrDrop::BoxedStorageDead => { + StorageDeadOrDrop::Destructor(base_ty) + } + } + } + _ => base_access, + } + } + + ProjectionElem::ConstantIndex { .. } + | ProjectionElem::Subslice { .. } + | ProjectionElem::Index(_) => base_access, + } + } + } + } + + /// Annotate argument and return type of function and closure with (synthesized) lifetime for + /// borrow of local value that does not live long enough. + fn annotate_argument_and_return_for_borrow( + &self, + borrow: &BorrowData<'tcx>, + ) -> Option> { + // Define a fallback for when we can't match a closure. + let fallback = || { + let is_closure = self.infcx.tcx.is_closure(self.mir_def_id); + if is_closure { + None + } else { + let ty = self.infcx.tcx.type_of(self.mir_def_id); + match ty.sty { + ty::FnDef(_, _) | ty::FnPtr(_) => self.annotate_fn_sig( + self.mir_def_id, + self.infcx.tcx.fn_sig(self.mir_def_id), + ), + _ => None, + } + } + }; + + // In order to determine whether we need to annotate, we need to check whether the reserve + // place was an assignment into a temporary. + // + // If it was, we check whether or not that temporary is eventually assigned into the return + // place. If it was, we can add annotations about the function's return type and arguments + // and it'll make sense. + let location = borrow.reserve_location; + debug!( + "annotate_argument_and_return_for_borrow: location={:?}", + location + ); + if let Some(&Statement { kind: StatementKind::Assign(ref reservation, _), ..}) + = &self.mir[location.block].statements.get(location.statement_index) + { + debug!( + "annotate_argument_and_return_for_borrow: reservation={:?}", + reservation + ); + // Check that the initial assignment of the reserve location is into a temporary. + let mut target = *match reservation { + Place::Base(PlaceBase::Local(local)) + if self.mir.local_kind(*local) == LocalKind::Temp => local, + _ => return None, + }; + + // Next, look through the rest of the block, checking if we are assigning the + // `target` (that is, the place that contains our borrow) to anything. + let mut annotated_closure = None; + for stmt in &self.mir[location.block].statements[location.statement_index + 1..] { + debug!( + "annotate_argument_and_return_for_borrow: target={:?} stmt={:?}", + target, stmt + ); + if let StatementKind::Assign( + Place::Base(PlaceBase::Local(assigned_to)), + box rvalue + ) = &stmt.kind { + debug!( + "annotate_argument_and_return_for_borrow: assigned_to={:?} \ + rvalue={:?}", + assigned_to, rvalue + ); + // Check if our `target` was captured by a closure. + if let Rvalue::Aggregate( + box AggregateKind::Closure(def_id, substs), + operands, + ) = rvalue + { + for operand in operands { + let assigned_from = match operand { + Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { + assigned_from + } + _ => continue, + }; + debug!( + "annotate_argument_and_return_for_borrow: assigned_from={:?}", + assigned_from + ); + + // Find the local from the operand. + let assigned_from_local = match assigned_from.local() { + Some(local) => local, + None => continue, + }; + + if assigned_from_local != target { + continue; + } + + // If a closure captured our `target` and then assigned + // into a place then we should annotate the closure in + // case it ends up being assigned into the return place. + annotated_closure = self.annotate_fn_sig( + *def_id, + self.infcx.closure_sig(*def_id, *substs), + ); + debug!( + "annotate_argument_and_return_for_borrow: \ + annotated_closure={:?} assigned_from_local={:?} \ + assigned_to={:?}", + annotated_closure, assigned_from_local, assigned_to + ); + + if *assigned_to == mir::RETURN_PLACE { + // If it was assigned directly into the return place, then + // return now. + return annotated_closure; + } else { + // Otherwise, update the target. + target = *assigned_to; + } + } + + // If none of our closure's operands matched, then skip to the next + // statement. + continue; + } + + // Otherwise, look at other types of assignment. + let assigned_from = match rvalue { + Rvalue::Ref(_, _, assigned_from) => assigned_from, + Rvalue::Use(operand) => match operand { + Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { + assigned_from + } + _ => continue, + }, + _ => continue, + }; + debug!( + "annotate_argument_and_return_for_borrow: \ + assigned_from={:?}", + assigned_from, + ); + + // Find the local from the rvalue. + let assigned_from_local = match assigned_from.local() { + Some(local) => local, + None => continue, + }; + debug!( + "annotate_argument_and_return_for_borrow: \ + assigned_from_local={:?}", + assigned_from_local, + ); + + // Check if our local matches the target - if so, we've assigned our + // borrow to a new place. + if assigned_from_local != target { + continue; + } + + // If we assigned our `target` into a new place, then we should + // check if it was the return place. + debug!( + "annotate_argument_and_return_for_borrow: \ + assigned_from_local={:?} assigned_to={:?}", + assigned_from_local, assigned_to + ); + if *assigned_to == mir::RETURN_PLACE { + // If it was then return the annotated closure if there was one, + // else, annotate this function. + return annotated_closure.or_else(fallback); + } + + // If we didn't assign into the return place, then we just update + // the target. + target = *assigned_to; + } + } + + // Check the terminator if we didn't find anything in the statements. + let terminator = &self.mir[location.block].terminator(); + debug!( + "annotate_argument_and_return_for_borrow: target={:?} terminator={:?}", + target, terminator + ); + if let TerminatorKind::Call { + destination: Some((Place::Base(PlaceBase::Local(assigned_to)), _)), + args, + .. + } = &terminator.kind + { + debug!( + "annotate_argument_and_return_for_borrow: assigned_to={:?} args={:?}", + assigned_to, args + ); + for operand in args { + let assigned_from = match operand { + Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { + assigned_from + } + _ => continue, + }; + debug!( + "annotate_argument_and_return_for_borrow: assigned_from={:?}", + assigned_from, + ); + + if let Some(assigned_from_local) = assigned_from.local() { + debug!( + "annotate_argument_and_return_for_borrow: assigned_from_local={:?}", + assigned_from_local, + ); + + if *assigned_to == mir::RETURN_PLACE && assigned_from_local == target { + return annotated_closure.or_else(fallback); + } + } + } + } + } + + // If we haven't found an assignment into the return place, then we need not add + // any annotations. + debug!("annotate_argument_and_return_for_borrow: none found"); + None + } + + /// Annotate the first argument and return type of a function signature if they are + /// references. + fn annotate_fn_sig( + &self, + did: DefId, + sig: ty::PolyFnSig<'tcx>, + ) -> Option> { + debug!("annotate_fn_sig: did={:?} sig={:?}", did, sig); + let is_closure = self.infcx.tcx.is_closure(did); + let fn_hir_id = self.infcx.tcx.hir().as_local_hir_id(did)?; + let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(fn_hir_id)?; + + // We need to work out which arguments to highlight. We do this by looking + // at the return type, where there are three cases: + // + // 1. If there are named arguments, then we should highlight the return type and + // highlight any of the arguments that are also references with that lifetime. + // If there are no arguments that have the same lifetime as the return type, + // then don't highlight anything. + // 2. The return type is a reference with an anonymous lifetime. If this is + // the case, then we can take advantage of (and teach) the lifetime elision + // rules. + // + // We know that an error is being reported. So the arguments and return type + // must satisfy the elision rules. Therefore, if there is a single argument + // then that means the return type and first (and only) argument have the same + // lifetime and the borrow isn't meeting that, we can highlight the argument + // and return type. + // + // If there are multiple arguments then the first argument must be self (else + // it would not satisfy the elision rules), so we can highlight self and the + // return type. + // 3. The return type is not a reference. In this case, we don't highlight + // anything. + let return_ty = sig.output(); + match return_ty.skip_binder().sty { + ty::Ref(return_region, _, _) if return_region.has_name() && !is_closure => { + // This is case 1 from above, return type is a named reference so we need to + // search for relevant arguments. + let mut arguments = Vec::new(); + for (index, argument) in sig.inputs().skip_binder().iter().enumerate() { + if let ty::Ref(argument_region, _, _) = argument.sty { + if argument_region == return_region { + // Need to use the `rustc::ty` types to compare against the + // `return_region`. Then use the `rustc::hir` type to get only + // the lifetime span. + if let hir::TyKind::Rptr(lifetime, _) = &fn_decl.inputs[index].node { + // With access to the lifetime, we can get + // the span of it. + arguments.push((*argument, lifetime.span)); + } else { + bug!("ty type is a ref but hir type is not"); + } + } + } + } + + // We need to have arguments. This shouldn't happen, but it's worth checking. + if arguments.is_empty() { + return None; + } + + // We use a mix of the HIR and the Ty types to get information + // as the HIR doesn't have full types for closure arguments. + let return_ty = *sig.output().skip_binder(); + let mut return_span = fn_decl.output.span(); + if let hir::FunctionRetTy::Return(ty) = fn_decl.output { + if let hir::TyKind::Rptr(lifetime, _) = ty.into_inner().node { + return_span = lifetime.span; + } + } + + Some(AnnotatedBorrowFnSignature::NamedFunction { + arguments, + return_ty, + return_span, + }) + } + ty::Ref(_, _, _) if is_closure => { + // This is case 2 from above but only for closures, return type is anonymous + // reference so we select + // the first argument. + let argument_span = fn_decl.inputs.first()?.span; + let argument_ty = sig.inputs().skip_binder().first()?; + + // Closure arguments are wrapped in a tuple, so we need to get the first + // from that. + if let ty::Tuple(elems) = argument_ty.sty { + let argument_ty = elems.first()?.expect_ty(); + if let ty::Ref(_, _, _) = argument_ty.sty { + return Some(AnnotatedBorrowFnSignature::Closure { + argument_ty, + argument_span, + }); + } + } + + None + } + ty::Ref(_, _, _) => { + // This is also case 2 from above but for functions, return type is still an + // anonymous reference so we select the first argument. + let argument_span = fn_decl.inputs.first()?.span; + let argument_ty = sig.inputs().skip_binder().first()?; + + let return_span = fn_decl.output.span(); + let return_ty = *sig.output().skip_binder(); + + // We expect the first argument to be a reference. + match argument_ty.sty { + ty::Ref(_, _, _) => {} + _ => return None, + } + + Some(AnnotatedBorrowFnSignature::AnonymousFunction { + argument_ty, + argument_span, + return_ty, + return_span, + }) + } + _ => { + // This is case 3 from above, return type is not a reference so don't highlight + // anything. + None + } + } + } +} + +#[derive(Debug)] +enum AnnotatedBorrowFnSignature<'tcx> { + NamedFunction { + arguments: Vec<(Ty<'tcx>, Span)>, + return_ty: Ty<'tcx>, + return_span: Span, + }, + AnonymousFunction { + argument_ty: Ty<'tcx>, + argument_span: Span, + return_ty: Ty<'tcx>, + return_span: Span, + }, + Closure { + argument_ty: Ty<'tcx>, + argument_span: Span, + }, +} + +impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { + /// Annotate the provided diagnostic with information about borrow from the fn signature that + /// helps explain. + pub(super) fn emit( + &self, + cx: &mut MirBorrowckCtxt<'_, '_, 'tcx>, + diag: &mut DiagnosticBuilder<'_>, + ) -> String { + match self { + AnnotatedBorrowFnSignature::Closure { + argument_ty, + argument_span, + } => { + diag.span_label( + *argument_span, + format!("has type `{}`", cx.get_name_for_ty(argument_ty, 0)), + ); + + cx.get_region_name_for_ty(argument_ty, 0) + } + AnnotatedBorrowFnSignature::AnonymousFunction { + argument_ty, + argument_span, + return_ty, + return_span, + } => { + let argument_ty_name = cx.get_name_for_ty(argument_ty, 0); + diag.span_label(*argument_span, format!("has type `{}`", argument_ty_name)); + + let return_ty_name = cx.get_name_for_ty(return_ty, 0); + let types_equal = return_ty_name == argument_ty_name; + diag.span_label( + *return_span, + format!( + "{}has type `{}`", + if types_equal { "also " } else { "" }, + return_ty_name, + ), + ); + + diag.note( + "argument and return type have the same lifetime due to lifetime elision rules", + ); + diag.note( + "to learn more, visit ", + ); + + cx.get_region_name_for_ty(return_ty, 0) + } + AnnotatedBorrowFnSignature::NamedFunction { + arguments, + return_ty, + return_span, + } => { + // Region of return type and arguments checked to be the same earlier. + let region_name = cx.get_region_name_for_ty(return_ty, 0); + for (_, argument_span) in arguments { + diag.span_label(*argument_span, format!("has lifetime `{}`", region_name)); + } + + diag.span_label( + *return_span, + format!("also has lifetime `{}`", region_name,), + ); + + diag.help(&format!( + "use data from the highlighted arguments which match the `{}` lifetime of \ + the return type", + region_name, + )); + + region_name + } + } + } +} diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index d78418076245..e7eef813e337 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -1,1505 +1,22 @@ -use crate::borrow_check::nll::explain_borrow::BorrowExplanation; -use crate::borrow_check::nll::region_infer::{RegionName, RegionNameSource}; -use crate::borrow_check::prefixes::IsPrefixOf; -use crate::borrow_check::WriteKind; use rustc::hir; use rustc::hir::def::Namespace; use rustc::hir::def_id::DefId; -use rustc::middle::region::ScopeTree; use rustc::mir::{ - self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, Constant, - ConstraintCategory, Field, Local, LocalDecl, LocalKind, Location, Operand, - Place, PlaceBase, PlaceProjection, ProjectionElem, Rvalue, Statement, StatementKind, - Static, StaticKind, TerminatorKind, VarBindingForm, + AggregateKind, BindingForm, ClearCrossCrate, Constant, Field, Local, + LocalKind, Location, Operand, Place, PlaceBase, ProjectionElem, Rvalue, + Statement, StatementKind, Static, StaticKind, TerminatorKind, }; use rustc::ty::{self, DefIdTree, Ty}; use rustc::ty::layout::VariantIdx; use rustc::ty::print::Print; -use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::indexed_vec::Idx; -use rustc_errors::{Applicability, DiagnosticBuilder}; +use rustc_errors::DiagnosticBuilder; use syntax_pos::Span; -use syntax::source_map::CompilerDesugaringKind; use syntax::symbol::sym; use super::borrow_set::BorrowData; use super::{MirBorrowckCtxt}; -use super::{InitializationRequiringAction, PrefixSet}; -use crate::dataflow::drop_flag_effects; -use crate::dataflow::indexes::{MovePathIndex, MoveOutIndex}; -use crate::util::borrowck_errors::{BorrowckErrors, Origin}; -#[derive(Debug)] -struct MoveSite { - /// Index of the "move out" that we found. The `MoveData` can - /// then tell us where the move occurred. - moi: MoveOutIndex, - - /// `true` if we traversed a back edge while walking from the point - /// of error to the move site. - traversed_back_edge: bool -} - -impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { - pub(super) fn report_use_of_moved_or_uninitialized( - &mut self, - location: Location, - desired_action: InitializationRequiringAction, - (moved_place, used_place, span): (&Place<'tcx>, &Place<'tcx>, Span), - mpi: MovePathIndex, - ) { - debug!( - "report_use_of_moved_or_uninitialized: location={:?} desired_action={:?} \ - moved_place={:?} used_place={:?} span={:?} mpi={:?}", - location, desired_action, moved_place, used_place, span, mpi - ); - - let use_spans = self.move_spans(moved_place, location) - .or_else(|| self.borrow_spans(span, location)); - let span = use_spans.args_or_use(); - - let move_site_vec = self.get_moved_indexes(location, mpi); - debug!( - "report_use_of_moved_or_uninitialized: move_site_vec={:?}", - move_site_vec - ); - let move_out_indices: Vec<_> = move_site_vec - .iter() - .map(|move_site| move_site.moi) - .collect(); - - if move_out_indices.is_empty() { - let root_place = self.prefixes(&used_place, PrefixSet::All).last().unwrap(); - - if self.uninitialized_error_reported.contains(root_place) { - debug!( - "report_use_of_moved_or_uninitialized place: error about {:?} suppressed", - root_place - ); - return; - } - - self.uninitialized_error_reported.insert(root_place.clone()); - - let item_msg = match self.describe_place_with_options(used_place, - IncludingDowncast(true)) { - Some(name) => format!("`{}`", name), - None => "value".to_owned(), - }; - let mut err = self.infcx.tcx.cannot_act_on_uninitialized_variable( - span, - desired_action.as_noun(), - &self.describe_place_with_options(moved_place, IncludingDowncast(true)) - .unwrap_or_else(|| "_".to_owned()), - Origin::Mir, - ); - err.span_label(span, format!("use of possibly uninitialized {}", item_msg)); - - use_spans.var_span_label( - &mut err, - format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()), - ); - - err.buffer(&mut self.errors_buffer); - } else { - if let Some((reported_place, _)) = self.move_error_reported.get(&move_out_indices) { - if self.prefixes(&reported_place, PrefixSet::All) - .any(|p| p == used_place) - { - debug!( - "report_use_of_moved_or_uninitialized place: error suppressed \ - mois={:?}", - move_out_indices - ); - return; - } - } - - let msg = ""; //FIXME: add "partially " or "collaterally " - - let mut err = self.infcx.tcx.cannot_act_on_moved_value( - span, - desired_action.as_noun(), - msg, - self.describe_place_with_options(&moved_place, IncludingDowncast(true)), - Origin::Mir, - ); - - self.add_moved_or_invoked_closure_note( - location, - used_place, - &mut err, - ); - - let mut is_loop_move = false; - let is_partial_move = move_site_vec.iter().any(|move_site| { - let move_out = self.move_data.moves[(*move_site).moi]; - let moved_place = &self.move_data.move_paths[move_out.path].place; - used_place != moved_place && used_place.is_prefix_of(moved_place) - }); - for move_site in &move_site_vec { - let move_out = self.move_data.moves[(*move_site).moi]; - let moved_place = &self.move_data.move_paths[move_out.path].place; - - let move_spans = self.move_spans(moved_place, move_out.source); - let move_span = move_spans.args_or_use(); - - let move_msg = if move_spans.for_closure() { - " into closure" - } else { - "" - }; - - if span == move_span { - err.span_label( - span, - format!("value moved{} here, in previous iteration of loop", move_msg), - ); - if Some(CompilerDesugaringKind::ForLoop) == span.compiler_desugaring_kind() { - if let Ok(snippet) = self.infcx.tcx.sess.source_map() - .span_to_snippet(span) - { - err.span_suggestion( - move_span, - "consider borrowing this to avoid moving it into the for loop", - format!("&{}", snippet), - Applicability::MaybeIncorrect, - ); - } - } - is_loop_move = true; - } else if move_site.traversed_back_edge { - err.span_label( - move_span, - format!( - "value moved{} here, in previous iteration of loop", - move_msg - ), - ); - } else { - err.span_label(move_span, format!("value moved{} here", move_msg)); - move_spans.var_span_label( - &mut err, - format!("variable moved due to use{}", move_spans.describe()), - ); - }; - } - - use_spans.var_span_label( - &mut err, - format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()), - ); - - if !is_loop_move { - err.span_label( - span, - format!( - "value {} here {}", - desired_action.as_verb_in_past_tense(), - if is_partial_move { "after partial move" } else { "after move" }, - ), - ); - } - - let ty = used_place.ty(self.mir, self.infcx.tcx).ty; - let needs_note = match ty.sty { - ty::Closure(id, _) => { - let tables = self.infcx.tcx.typeck_tables_of(id); - let hir_id = self.infcx.tcx.hir().as_local_hir_id(id).unwrap(); - - tables.closure_kind_origins().get(hir_id).is_none() - } - _ => true, - }; - - if needs_note { - let mpi = self.move_data.moves[move_out_indices[0]].path; - let place = &self.move_data.move_paths[mpi].place; - - let ty = place.ty(self.mir, self.infcx.tcx).ty; - let opt_name = self.describe_place_with_options(place, IncludingDowncast(true)); - let note_msg = match opt_name { - Some(ref name) => format!("`{}`", name), - None => "value".to_owned(), - }; - if let ty::Param(param_ty) = ty.sty { - let tcx = self.infcx.tcx; - let generics = tcx.generics_of(self.mir_def_id); - let def_id = generics.type_param(¶m_ty, tcx).def_id; - if let Some(sp) = tcx.hir().span_if_local(def_id) { - err.span_label( - sp, - "consider adding a `Copy` constraint to this type argument", - ); - } - } - if let Place::Base(PlaceBase::Local(local)) = place { - let decl = &self.mir.local_decls[*local]; - err.span_label( - decl.source_info.span, - format!( - "move occurs because {} has type `{}`, \ - which does not implement the `Copy` trait", - note_msg, ty, - )); - } else { - err.note(&format!( - "move occurs because {} has type `{}`, \ - which does not implement the `Copy` trait", - note_msg, ty - )); - } - } - - if let Some((_, mut old_err)) = self.move_error_reported - .insert(move_out_indices, (used_place.clone(), err)) - { - // Cancel the old error so it doesn't ICE. - old_err.cancel(); - } - } - } - - pub(super) fn report_move_out_while_borrowed( - &mut self, - location: Location, - (place, span): (&Place<'tcx>, Span), - borrow: &BorrowData<'tcx>, - ) { - debug!( - "report_move_out_while_borrowed: location={:?} place={:?} span={:?} borrow={:?}", - location, place, span, borrow - ); - let tcx = self.infcx.tcx; - let value_msg = match self.describe_place(place) { - Some(name) => format!("`{}`", name), - None => "value".to_owned(), - }; - let borrow_msg = match self.describe_place(&borrow.borrowed_place) { - Some(name) => format!("`{}`", name), - None => "value".to_owned(), - }; - - let borrow_spans = self.retrieve_borrow_spans(borrow); - let borrow_span = borrow_spans.args_or_use(); - - let move_spans = self.move_spans(place, location); - let span = move_spans.args_or_use(); - - let mut err = tcx.cannot_move_when_borrowed( - span, - &self.describe_place(place).unwrap_or_else(|| "_".to_owned()), - Origin::Mir, - ); - err.span_label(borrow_span, format!("borrow of {} occurs here", borrow_msg)); - err.span_label(span, format!("move out of {} occurs here", value_msg)); - - borrow_spans.var_span_label( - &mut err, - format!("borrow occurs due to use{}", borrow_spans.describe()) - ); - - move_spans.var_span_label( - &mut err, - format!("move occurs due to use{}", move_spans.describe()) - ); - - self.explain_why_borrow_contains_point( - location, - borrow, - None, - ).add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", Some(borrow_span)); - err.buffer(&mut self.errors_buffer); - } - - pub(super) fn report_use_while_mutably_borrowed( - &mut self, - location: Location, - (place, _span): (&Place<'tcx>, Span), - borrow: &BorrowData<'tcx>, - ) -> DiagnosticBuilder<'cx> { - let tcx = self.infcx.tcx; - - let borrow_spans = self.retrieve_borrow_spans(borrow); - let borrow_span = borrow_spans.args_or_use(); - - // Conflicting borrows are reported separately, so only check for move - // captures. - let use_spans = self.move_spans(place, location); - let span = use_spans.var_or_use(); - - let mut err = tcx.cannot_use_when_mutably_borrowed( - span, - &self.describe_place(place).unwrap_or_else(|| "_".to_owned()), - borrow_span, - &self.describe_place(&borrow.borrowed_place) - .unwrap_or_else(|| "_".to_owned()), - Origin::Mir, - ); - - borrow_spans.var_span_label(&mut err, { - let place = &borrow.borrowed_place; - let desc_place = self.describe_place(place).unwrap_or_else(|| "_".to_owned()); - - format!("borrow occurs due to use of `{}`{}", desc_place, borrow_spans.describe()) - }); - - self.explain_why_borrow_contains_point(location, borrow, None) - .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None); - err - } - - pub(super) fn report_conflicting_borrow( - &mut self, - location: Location, - (place, span): (&Place<'tcx>, Span), - gen_borrow_kind: BorrowKind, - issued_borrow: &BorrowData<'tcx>, - ) -> DiagnosticBuilder<'cx> { - let issued_spans = self.retrieve_borrow_spans(issued_borrow); - let issued_span = issued_spans.args_or_use(); - - let borrow_spans = self.borrow_spans(span, location); - let span = borrow_spans.args_or_use(); - - let container_name = if issued_spans.for_generator() || borrow_spans.for_generator() { - "generator" - } else { - "closure" - }; - - let (desc_place, msg_place, msg_borrow, union_type_name) = - self.describe_place_for_conflicting_borrow(place, &issued_borrow.borrowed_place); - - let explanation = self.explain_why_borrow_contains_point(location, issued_borrow, None); - let second_borrow_desc = if explanation.is_explained() { - "second " - } else { - "" - }; - - // FIXME: supply non-"" `opt_via` when appropriate - let tcx = self.infcx.tcx; - let first_borrow_desc; - let mut err = match ( - gen_borrow_kind, - "immutable", - "mutable", - issued_borrow.kind, - "immutable", - "mutable", - ) { - (BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt) => { - first_borrow_desc = "mutable "; - tcx.cannot_reborrow_already_borrowed( - span, - &desc_place, - &msg_place, - lft, - issued_span, - "it", - rgt, - &msg_borrow, - None, - Origin::Mir, - ) - } - (BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => { - first_borrow_desc = "immutable "; - tcx.cannot_reborrow_already_borrowed( - span, - &desc_place, - &msg_place, - lft, - issued_span, - "it", - rgt, - &msg_borrow, - None, - Origin::Mir, - ) - } - - (BorrowKind::Mut { .. }, _, _, BorrowKind::Mut { .. }, _, _) => { - first_borrow_desc = "first "; - tcx.cannot_mutably_borrow_multiply( - span, - &desc_place, - &msg_place, - issued_span, - &msg_borrow, - None, - Origin::Mir, - ) - } - - (BorrowKind::Unique, _, _, BorrowKind::Unique, _, _) => { - first_borrow_desc = "first "; - tcx.cannot_uniquely_borrow_by_two_closures( - span, - &desc_place, - issued_span, - None, - Origin::Mir, - ) - } - - (BorrowKind::Mut { .. }, _, _, BorrowKind::Shallow, _, _) - | (BorrowKind::Unique, _, _, BorrowKind::Shallow, _, _) => { - let mut err = tcx.cannot_mutate_in_match_guard( - span, - issued_span, - &desc_place, - "mutably borrow", - Origin::Mir, - ); - borrow_spans.var_span_label( - &mut err, - format!( - "borrow occurs due to use of `{}`{}", desc_place, borrow_spans.describe() - ), - ); - - return err; - } - - (BorrowKind::Unique, _, _, _, _, _) => { - first_borrow_desc = "first "; - tcx.cannot_uniquely_borrow_by_one_closure( - span, - container_name, - &desc_place, - "", - issued_span, - "it", - "", - None, - Origin::Mir, - ) - }, - - (BorrowKind::Shared, lft, _, BorrowKind::Unique, _, _) => { - first_borrow_desc = "first "; - tcx.cannot_reborrow_already_uniquely_borrowed( - span, - container_name, - &desc_place, - "", - lft, - issued_span, - "", - None, - second_borrow_desc, - Origin::Mir, - ) - } - - (BorrowKind::Mut { .. }, _, lft, BorrowKind::Unique, _, _) => { - first_borrow_desc = "first "; - tcx.cannot_reborrow_already_uniquely_borrowed( - span, - container_name, - &desc_place, - "", - lft, - issued_span, - "", - None, - second_borrow_desc, - Origin::Mir, - ) - } - - (BorrowKind::Shared, _, _, BorrowKind::Shared, _, _) - | (BorrowKind::Shared, _, _, BorrowKind::Shallow, _, _) - | (BorrowKind::Shallow, _, _, BorrowKind::Mut { .. }, _, _) - | (BorrowKind::Shallow, _, _, BorrowKind::Unique, _, _) - | (BorrowKind::Shallow, _, _, BorrowKind::Shared, _, _) - | (BorrowKind::Shallow, _, _, BorrowKind::Shallow, _, _) => unreachable!(), - }; - - if issued_spans == borrow_spans { - borrow_spans.var_span_label( - &mut err, - format!("borrows occur due to use of `{}`{}", desc_place, borrow_spans.describe()), - ); - } else { - let borrow_place = &issued_borrow.borrowed_place; - let borrow_place_desc = self.describe_place(borrow_place) - .unwrap_or_else(|| "_".to_owned()); - issued_spans.var_span_label( - &mut err, - format!( - "first borrow occurs due to use of `{}`{}", - borrow_place_desc, - issued_spans.describe(), - ), - ); - - borrow_spans.var_span_label( - &mut err, - format!( - "second borrow occurs due to use of `{}`{}", - desc_place, - borrow_spans.describe(), - ), - ); - } - - if union_type_name != "" { - err.note(&format!( - "`{}` is a field of the union `{}`, so it overlaps the field `{}`", - msg_place, union_type_name, msg_borrow, - )); - } - - explanation.add_explanation_to_diagnostic( - self.infcx.tcx, - self.mir, - &mut err, - first_borrow_desc, - None, - ); - - err - } - - /// Returns the description of the root place for a conflicting borrow and the full - /// descriptions of the places that caused the conflict. - /// - /// In the simplest case, where there are no unions involved, if a mutable borrow of `x` is - /// attempted while a shared borrow is live, then this function will return: - /// - /// ("x", "", "") - /// - /// In the simple union case, if a mutable borrow of a union field `x.z` is attempted while - /// a shared borrow of another field `x.y`, then this function will return: - /// - /// ("x", "x.z", "x.y") - /// - /// In the more complex union case, where the union is a field of a struct, then if a mutable - /// borrow of a union field in a struct `x.u.z` is attempted while a shared borrow of - /// another field `x.u.y`, then this function will return: - /// - /// ("x.u", "x.u.z", "x.u.y") - /// - /// This is used when creating error messages like below: - /// - /// > cannot borrow `a.u` (via `a.u.z.c`) as immutable because it is also borrowed as - /// > mutable (via `a.u.s.b`) [E0502] - pub(super) fn describe_place_for_conflicting_borrow( - &self, - first_borrowed_place: &Place<'tcx>, - second_borrowed_place: &Place<'tcx>, - ) -> (String, String, String, String) { - // Define a small closure that we can use to check if the type of a place - // is a union. - let is_union = |place: &Place<'tcx>| -> bool { - place.ty(self.mir, self.infcx.tcx).ty - .ty_adt_def() - .map(|adt| adt.is_union()) - .unwrap_or(false) - }; - - // Start with an empty tuple, so we can use the functions on `Option` to reduce some - // code duplication (particularly around returning an empty description in the failure - // case). - Some(()) - .filter(|_| { - // If we have a conflicting borrow of the same place, then we don't want to add - // an extraneous "via x.y" to our diagnostics, so filter out this case. - first_borrowed_place != second_borrowed_place - }) - .and_then(|_| { - // We're going to want to traverse the first borrowed place to see if we can find - // field access to a union. If we find that, then we will keep the place of the - // union being accessed and the field that was being accessed so we can check the - // second borrowed place for the same union and a access to a different field. - let mut current = first_borrowed_place; - while let Place::Projection(box PlaceProjection { base, elem }) = current { - match elem { - ProjectionElem::Field(field, _) if is_union(base) => { - return Some((base, field)); - }, - _ => current = base, - } - } - None - }) - .and_then(|(target_base, target_field)| { - // With the place of a union and a field access into it, we traverse the second - // borrowed place and look for a access to a different field of the same union. - let mut current = second_borrowed_place; - while let Place::Projection(box PlaceProjection { base, elem }) = current { - match elem { - ProjectionElem::Field(field, _) if { - is_union(base) && field != target_field && base == target_base - } => { - let desc_base = self.describe_place(base) - .unwrap_or_else(|| "_".to_owned()); - let desc_first = self.describe_place(first_borrowed_place) - .unwrap_or_else(|| "_".to_owned()); - let desc_second = self.describe_place(second_borrowed_place) - .unwrap_or_else(|| "_".to_owned()); - - // Also compute the name of the union type, eg. `Foo` so we - // can add a helpful note with it. - let ty = base.ty(self.mir, self.infcx.tcx).ty; - - return Some((desc_base, desc_first, desc_second, ty.to_string())); - }, - _ => current = base, - } - } - None - }) - .unwrap_or_else(|| { - // If we didn't find a field access into a union, or both places match, then - // only return the description of the first place. - let desc_place = self.describe_place(first_borrowed_place) - .unwrap_or_else(|| "_".to_owned()); - (desc_place, "".to_string(), "".to_string(), "".to_string()) - }) - } - - /// Reports StorageDeadOrDrop of `place` conflicts with `borrow`. - /// - /// This means that some data referenced by `borrow` needs to live - /// past the point where the StorageDeadOrDrop of `place` occurs. - /// This is usually interpreted as meaning that `place` has too - /// short a lifetime. (But sometimes it is more useful to report - /// it as a more direct conflict between the execution of a - /// `Drop::drop` with an aliasing borrow.) - pub(super) fn report_borrowed_value_does_not_live_long_enough( - &mut self, - location: Location, - borrow: &BorrowData<'tcx>, - place_span: (&Place<'tcx>, Span), - kind: Option, - ) { - debug!( - "report_borrowed_value_does_not_live_long_enough(\ - {:?}, {:?}, {:?}, {:?}\ - )", - location, borrow, place_span, kind - ); - - let drop_span = place_span.1; - let scope_tree = self.infcx.tcx.region_scope_tree(self.mir_def_id); - let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All) - .last() - .unwrap(); - - let borrow_spans = self.retrieve_borrow_spans(borrow); - let borrow_span = borrow_spans.var_or_use(); - - let proper_span = match *root_place { - Place::Base(PlaceBase::Local(local)) => self.mir.local_decls[local].source_info.span, - _ => drop_span, - }; - - if self.access_place_error_reported - .contains(&(root_place.clone(), borrow_span)) - { - debug!( - "suppressing access_place error when borrow doesn't live long enough for {:?}", - borrow_span - ); - return; - } - - self.access_place_error_reported - .insert((root_place.clone(), borrow_span)); - - if let StorageDeadOrDrop::Destructor(dropped_ty) = - self.classify_drop_access_kind(&borrow.borrowed_place) - { - // If a borrow of path `B` conflicts with drop of `D` (and - // we're not in the uninteresting case where `B` is a - // prefix of `D`), then report this as a more interesting - // destructor conflict. - if !borrow.borrowed_place.is_prefix_of(place_span.0) { - self.report_borrow_conflicts_with_destructor( - location, borrow, place_span, kind, dropped_ty, - ); - return; - } - } - - let place_desc = self.describe_place(&borrow.borrowed_place); - - let kind_place = kind.filter(|_| place_desc.is_some()).map(|k| (k, place_span.0)); - let explanation = self.explain_why_borrow_contains_point(location, &borrow, kind_place); - - let err = match (place_desc, explanation) { - (Some(_), _) if self.is_place_thread_local(root_place) => { - self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span) - } - // If the outlives constraint comes from inside the closure, - // for example: - // - // let x = 0; - // let y = &x; - // Box::new(|| y) as Box &'static i32> - // - // then just use the normal error. The closure isn't escaping - // and `move` will not help here. - ( - Some(ref name), - BorrowExplanation::MustBeValidFor { - category: category @ ConstraintCategory::Return, - from_closure: false, - ref region_name, - span, - .. - }, - ) - | ( - Some(ref name), - BorrowExplanation::MustBeValidFor { - category: category @ ConstraintCategory::CallArgument, - from_closure: false, - ref region_name, - span, - .. - }, - ) if borrow_spans.for_closure() => self.report_escaping_closure_capture( - borrow_spans.args_or_use(), - borrow_span, - region_name, - category, - span, - &format!("`{}`", name), - ), - ( - ref name, - BorrowExplanation::MustBeValidFor { - category: ConstraintCategory::Assignment, - from_closure: false, - region_name: RegionName { - source: RegionNameSource::AnonRegionFromUpvar(upvar_span, ref upvar_name), - .. - }, - span, - .. - }, - ) => self.report_escaping_data(borrow_span, name, upvar_span, upvar_name, span), - (Some(name), explanation) => self.report_local_value_does_not_live_long_enough( - location, - &name, - &scope_tree, - &borrow, - drop_span, - borrow_spans, - explanation, - ), - (None, explanation) => self.report_temporary_value_does_not_live_long_enough( - location, - &scope_tree, - &borrow, - drop_span, - borrow_spans, - proper_span, - explanation, - ), - }; - - err.buffer(&mut self.errors_buffer); - } - - fn report_local_value_does_not_live_long_enough( - &mut self, - location: Location, - name: &str, - scope_tree: &'tcx ScopeTree, - borrow: &BorrowData<'tcx>, - drop_span: Span, - borrow_spans: UseSpans, - explanation: BorrowExplanation, - ) -> DiagnosticBuilder<'cx> { - debug!( - "report_local_value_does_not_live_long_enough(\ - {:?}, {:?}, {:?}, {:?}, {:?}, {:?}\ - )", - location, name, scope_tree, borrow, drop_span, borrow_spans - ); - - let borrow_span = borrow_spans.var_or_use(); - if let BorrowExplanation::MustBeValidFor { - category, - span, - ref opt_place_desc, - from_closure: false, - .. - } = explanation { - if let Some(diag) = self.try_report_cannot_return_reference_to_local( - borrow, - borrow_span, - span, - category, - opt_place_desc.as_ref(), - ) { - return diag; - } - } - - let mut err = self.infcx.tcx.path_does_not_live_long_enough( - borrow_span, - &format!("`{}`", name), - Origin::Mir, - ); - - if let Some(annotation) = self.annotate_argument_and_return_for_borrow(borrow) { - let region_name = annotation.emit(self, &mut err); - - err.span_label( - borrow_span, - format!("`{}` would have to be valid for `{}`...", name, region_name), - ); - - if let Some(fn_hir_id) = self.infcx.tcx.hir().as_local_hir_id(self.mir_def_id) { - err.span_label( - drop_span, - format!( - "...but `{}` will be dropped here, when the function `{}` returns", - name, - self.infcx.tcx.hir().name_by_hir_id(fn_hir_id), - ), - ); - - err.note( - "functions cannot return a borrow to data owned within the function's scope, \ - functions can only return borrows to data passed as arguments", - ); - err.note( - "to learn more, visit ", - ); - } else { - err.span_label( - drop_span, - format!("...but `{}` dropped here while still borrowed", name), - ); - } - - if let BorrowExplanation::MustBeValidFor { .. } = explanation { - } else { - explanation.add_explanation_to_diagnostic( - self.infcx.tcx, - self.mir, - &mut err, - "", - None, - ); - } - } else { - err.span_label(borrow_span, "borrowed value does not live long enough"); - err.span_label( - drop_span, - format!("`{}` dropped here while still borrowed", name), - ); - - let within = if borrow_spans.for_generator() { - " by generator" - } else { - "" - }; - - borrow_spans.args_span_label( - &mut err, - format!("value captured here{}", within), - ); - - explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None); - } - - err - } - - fn report_borrow_conflicts_with_destructor( - &mut self, - location: Location, - borrow: &BorrowData<'tcx>, - (place, drop_span): (&Place<'tcx>, Span), - kind: Option, - dropped_ty: Ty<'tcx>, - ) { - debug!( - "report_borrow_conflicts_with_destructor(\ - {:?}, {:?}, ({:?}, {:?}), {:?}\ - )", - location, borrow, place, drop_span, kind, - ); - - let borrow_spans = self.retrieve_borrow_spans(borrow); - let borrow_span = borrow_spans.var_or_use(); - - let mut err = self.infcx - .tcx - .cannot_borrow_across_destructor(borrow_span, Origin::Mir); - - let what_was_dropped = match self.describe_place(place) { - Some(name) => format!("`{}`", name.as_str()), - None => String::from("temporary value"), - }; - - let label = match self.describe_place(&borrow.borrowed_place) { - Some(borrowed) => format!( - "here, drop of {D} needs exclusive access to `{B}`, \ - because the type `{T}` implements the `Drop` trait", - D = what_was_dropped, - T = dropped_ty, - B = borrowed - ), - None => format!( - "here is drop of {D}; whose type `{T}` implements the `Drop` trait", - D = what_was_dropped, - T = dropped_ty - ), - }; - err.span_label(drop_span, label); - - // Only give this note and suggestion if they could be relevant. - let explanation = - self.explain_why_borrow_contains_point(location, borrow, kind.map(|k| (k, place))); - match explanation { - BorrowExplanation::UsedLater { .. } - | BorrowExplanation::UsedLaterWhenDropped { .. } => { - err.note("consider using a `let` binding to create a longer lived value"); - } - _ => {} - } - - explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None); - - err.buffer(&mut self.errors_buffer); - } - - fn report_thread_local_value_does_not_live_long_enough( - &mut self, - drop_span: Span, - borrow_span: Span, - ) -> DiagnosticBuilder<'cx> { - debug!( - "report_thread_local_value_does_not_live_long_enough(\ - {:?}, {:?}\ - )", - drop_span, borrow_span - ); - - let mut err = self.infcx - .tcx - .thread_local_value_does_not_live_long_enough(borrow_span, Origin::Mir); - - err.span_label( - borrow_span, - "thread-local variables cannot be borrowed beyond the end of the function", - ); - err.span_label(drop_span, "end of enclosing function is here"); - - err - } - - fn report_temporary_value_does_not_live_long_enough( - &mut self, - location: Location, - scope_tree: &'tcx ScopeTree, - borrow: &BorrowData<'tcx>, - drop_span: Span, - borrow_spans: UseSpans, - proper_span: Span, - explanation: BorrowExplanation, - ) -> DiagnosticBuilder<'cx> { - debug!( - "report_temporary_value_does_not_live_long_enough(\ - {:?}, {:?}, {:?}, {:?}, {:?}\ - )", - location, scope_tree, borrow, drop_span, proper_span - ); - - if let BorrowExplanation::MustBeValidFor { - category, - span, - from_closure: false, - .. - } = explanation { - if let Some(diag) = self.try_report_cannot_return_reference_to_local( - borrow, - proper_span, - span, - category, - None, - ) { - return diag; - } - } - - let tcx = self.infcx.tcx; - let mut err = tcx.temporary_value_borrowed_for_too_long(proper_span, Origin::Mir); - err.span_label( - proper_span, - "creates a temporary which is freed while still in use", - ); - err.span_label( - drop_span, - "temporary value is freed at the end of this statement", - ); - - match explanation { - BorrowExplanation::UsedLater(..) - | BorrowExplanation::UsedLaterInLoop(..) - | BorrowExplanation::UsedLaterWhenDropped { .. } => { - // Only give this note and suggestion if it could be relevant. - err.note("consider using a `let` binding to create a longer lived value"); - } - _ => {} - } - explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None); - - let within = if borrow_spans.for_generator() { - " by generator" - } else { - "" - }; - - borrow_spans.args_span_label( - &mut err, - format!("value captured here{}", within), - ); - - err - } - - fn try_report_cannot_return_reference_to_local( - &self, - borrow: &BorrowData<'tcx>, - borrow_span: Span, - return_span: Span, - category: ConstraintCategory, - opt_place_desc: Option<&String>, - ) -> Option> { - let tcx = self.infcx.tcx; - - let return_kind = match category { - ConstraintCategory::Return => "return", - ConstraintCategory::Yield => "yield", - _ => return None, - }; - - // FIXME use a better heuristic than Spans - let reference_desc = if return_span == self.mir.source_info(borrow.reserve_location).span { - "reference to" - } else { - "value referencing" - }; - - let (place_desc, note) = if let Some(place_desc) = opt_place_desc { - let local_kind = match borrow.borrowed_place { - Place::Base(PlaceBase::Local(local)) => { - match self.mir.local_kind(local) { - LocalKind::ReturnPointer - | LocalKind::Temp => bug!("temporary or return pointer with a name"), - LocalKind::Var => "local variable ", - LocalKind::Arg - if !self.upvars.is_empty() - && local == Local::new(1) => { - "variable captured by `move` " - } - LocalKind::Arg => { - "function parameter " - } - } - } - _ => "local data ", - }; - ( - format!("{}`{}`", local_kind, place_desc), - format!("`{}` is borrowed here", place_desc), - ) - } else { - let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All) - .last() - .unwrap(); - let local = if let Place::Base(PlaceBase::Local(local)) = *root_place { - local - } else { - bug!("try_report_cannot_return_reference_to_local: not a local") - }; - match self.mir.local_kind(local) { - LocalKind::ReturnPointer | LocalKind::Temp => { - ( - "temporary value".to_string(), - "temporary value created here".to_string(), - ) - } - LocalKind::Arg => { - ( - "function parameter".to_string(), - "function parameter borrowed here".to_string(), - ) - }, - LocalKind::Var => bug!("local variable without a name"), - } - }; - - let mut err = tcx.cannot_return_reference_to_local( - return_span, - return_kind, - reference_desc, - &place_desc, - Origin::Mir, - ); - - if return_span != borrow_span { - err.span_label(borrow_span, note); - } - - Some(err) - } - - fn report_escaping_closure_capture( - &mut self, - args_span: Span, - var_span: Span, - fr_name: &RegionName, - category: ConstraintCategory, - constraint_span: Span, - captured_var: &str, - ) -> DiagnosticBuilder<'cx> { - let tcx = self.infcx.tcx; - - let mut err = tcx.cannot_capture_in_long_lived_closure( - args_span, - captured_var, - var_span, - Origin::Mir, - ); - - let suggestion = match tcx.sess.source_map().span_to_snippet(args_span) { - Ok(string) => format!("move {}", string), - Err(_) => "move || ".to_string() - }; - - err.span_suggestion( - args_span, - &format!("to force the closure to take ownership of {} (and any \ - other referenced variables), use the `move` keyword", - captured_var), - suggestion, - Applicability::MachineApplicable, - ); - - match category { - ConstraintCategory::Return => { - err.span_note(constraint_span, "closure is returned here"); - } - ConstraintCategory::CallArgument => { - fr_name.highlight_region_name(&mut err); - err.span_note( - constraint_span, - &format!("function requires argument type to outlive `{}`", fr_name), - ); - } - _ => bug!("report_escaping_closure_capture called with unexpected constraint \ - category: `{:?}`", category), - } - err - } - - fn report_escaping_data( - &mut self, - borrow_span: Span, - name: &Option, - upvar_span: Span, - upvar_name: &str, - escape_span: Span, - ) -> DiagnosticBuilder<'cx> { - let tcx = self.infcx.tcx; - - let escapes_from = if tcx.is_closure(self.mir_def_id) { - let tables = tcx.typeck_tables_of(self.mir_def_id); - let mir_hir_id = tcx.hir().def_index_to_hir_id(self.mir_def_id.index); - match tables.node_type(mir_hir_id).sty { - ty::Closure(..) => "closure", - ty::Generator(..) => "generator", - _ => bug!("Closure body doesn't have a closure or generator type"), - } - } else { - "function" - }; - - let mut err = tcx.borrowed_data_escapes_closure(escape_span, escapes_from, Origin::Mir); - - err.span_label( - upvar_span, - format!( - "`{}` is declared here, outside of the {} body", - upvar_name, escapes_from - ), - ); - - err.span_label( - borrow_span, - format!( - "borrow is only valid in the {} body", - escapes_from - ), - ); - - if let Some(name) = name { - err.span_label( - escape_span, - format!("reference to `{}` escapes the {} body here", name, escapes_from), - ); - } else { - err.span_label( - escape_span, - format!("reference escapes the {} body here", escapes_from), - ); - } - - err - } - - fn get_moved_indexes(&mut self, location: Location, mpi: MovePathIndex) -> Vec { - let mir = self.mir; - - let mut stack = Vec::new(); - stack.extend(mir.predecessor_locations(location).map(|predecessor| { - let is_back_edge = location.dominates(predecessor, &self.dominators); - (predecessor, is_back_edge) - })); - - let mut visited = FxHashSet::default(); - let mut result = vec![]; - - 'dfs: while let Some((location, is_back_edge)) = stack.pop() { - debug!( - "report_use_of_moved_or_uninitialized: (current_location={:?}, back_edge={})", - location, is_back_edge - ); - - if !visited.insert(location) { - continue; - } - - // check for moves - let stmt_kind = mir[location.block] - .statements - .get(location.statement_index) - .map(|s| &s.kind); - if let Some(StatementKind::StorageDead(..)) = stmt_kind { - // this analysis only tries to find moves explicitly - // written by the user, so we ignore the move-outs - // created by `StorageDead` and at the beginning - // of a function. - } else { - // If we are found a use of a.b.c which was in error, then we want to look for - // moves not only of a.b.c but also a.b and a. - // - // Note that the moves data already includes "parent" paths, so we don't have to - // worry about the other case: that is, if there is a move of a.b.c, it is already - // marked as a move of a.b and a as well, so we will generate the correct errors - // there. - let mut mpis = vec![mpi]; - let move_paths = &self.move_data.move_paths; - mpis.extend(move_paths[mpi].parents(move_paths)); - - for moi in &self.move_data.loc_map[location] { - debug!("report_use_of_moved_or_uninitialized: moi={:?}", moi); - if mpis.contains(&self.move_data.moves[*moi].path) { - debug!("report_use_of_moved_or_uninitialized: found"); - result.push(MoveSite { - moi: *moi, - traversed_back_edge: is_back_edge, - }); - - // Strictly speaking, we could continue our DFS here. There may be - // other moves that can reach the point of error. But it is kind of - // confusing to highlight them. - // - // Example: - // - // ``` - // let a = vec![]; - // let b = a; - // let c = a; - // drop(a); // <-- current point of error - // ``` - // - // Because we stop the DFS here, we only highlight `let c = a`, - // and not `let b = a`. We will of course also report an error at - // `let c = a` which highlights `let b = a` as the move. - continue 'dfs; - } - } - } - - // check for inits - let mut any_match = false; - drop_flag_effects::for_location_inits( - self.infcx.tcx, - self.mir, - self.move_data, - location, - |m| { - if m == mpi { - any_match = true; - } - }, - ); - if any_match { - continue 'dfs; - } - - stack.extend(mir.predecessor_locations(location).map(|predecessor| { - let back_edge = location.dominates(predecessor, &self.dominators); - (predecessor, is_back_edge || back_edge) - })); - } - - result - } - - pub(super) fn report_illegal_mutation_of_borrowed( - &mut self, - location: Location, - (place, span): (&Place<'tcx>, Span), - loan: &BorrowData<'tcx>, - ) { - let loan_spans = self.retrieve_borrow_spans(loan); - let loan_span = loan_spans.args_or_use(); - - let tcx = self.infcx.tcx; - if loan.kind == BorrowKind::Shallow { - let mut err = tcx.cannot_mutate_in_match_guard( - span, - loan_span, - &self.describe_place(place).unwrap_or_else(|| "_".to_owned()), - "assign", - Origin::Mir, - ); - loan_spans.var_span_label( - &mut err, - format!("borrow occurs due to use{}", loan_spans.describe()), - ); - - err.buffer(&mut self.errors_buffer); - - return; - } - - let mut err = tcx.cannot_assign_to_borrowed( - span, - loan_span, - &self.describe_place(place).unwrap_or_else(|| "_".to_owned()), - Origin::Mir, - ); - - loan_spans.var_span_label( - &mut err, - format!("borrow occurs due to use{}", loan_spans.describe()), - ); - - self.explain_why_borrow_contains_point(location, loan, None) - .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "", None); - - err.buffer(&mut self.errors_buffer); - } - - /// Reports an illegal reassignment; for example, an assignment to - /// (part of) a non-`mut` local that occurs potentially after that - /// local has already been initialized. `place` is the path being - /// assigned; `err_place` is a place providing a reason why - /// `place` is not mutable (e.g., the non-`mut` local `x` in an - /// assignment to `x.f`). - pub(super) fn report_illegal_reassignment( - &mut self, - _location: Location, - (place, span): (&Place<'tcx>, Span), - assigned_span: Span, - err_place: &Place<'tcx>, - ) { - let (from_arg, local_decl) = if let Place::Base(PlaceBase::Local(local)) = *err_place { - if let LocalKind::Arg = self.mir.local_kind(local) { - (true, Some(&self.mir.local_decls[local])) - } else { - (false, Some(&self.mir.local_decls[local])) - } - } else { - (false, None) - }; - - // If root local is initialized immediately (everything apart from let - // PATTERN;) then make the error refer to that local, rather than the - // place being assigned later. - let (place_description, assigned_span) = match local_decl { - Some(LocalDecl { - is_user_variable: Some(ClearCrossCrate::Clear), - .. - }) - | Some(LocalDecl { - is_user_variable: - Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm { - opt_match_place: None, - .. - }))), - .. - }) - | Some(LocalDecl { - is_user_variable: None, - .. - }) - | None => (self.describe_place(place), assigned_span), - Some(decl) => (self.describe_place(err_place), decl.source_info.span), - }; - - let mut err = self.infcx.tcx.cannot_reassign_immutable( - span, - place_description.as_ref().map(AsRef::as_ref).unwrap_or("_"), - from_arg, - Origin::Mir, - ); - let msg = if from_arg { - "cannot assign to immutable argument" - } else { - "cannot assign twice to immutable variable" - }; - if span != assigned_span { - if !from_arg { - let value_msg = match place_description { - Some(name) => format!("`{}`", name), - None => "value".to_owned(), - }; - err.span_label(assigned_span, format!("first assignment to {}", value_msg)); - } - } - if let Some(decl) = local_decl { - if let Some(name) = decl.name { - if decl.can_be_made_mutable() { - err.span_suggestion( - decl.source_info.span, - "make this binding mutable", - format!("mut {}", name), - Applicability::MachineApplicable, - ); - } - } - } - err.span_label(span, msg); - err.buffer(&mut self.errors_buffer); - } -} - -pub(super) struct IncludingDowncast(bool); - -/// Which case a StorageDeadOrDrop is for. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -enum StorageDeadOrDrop<'tcx> { - LocalStorageDead, - BoxedStorageDead, - Destructor(Ty<'tcx>), -} +pub(super) struct IncludingDowncast(pub(super) bool); impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { @@ -1866,507 +383,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { false } } - - fn classify_drop_access_kind(&self, place: &Place<'tcx>) -> StorageDeadOrDrop<'tcx> { - let tcx = self.infcx.tcx; - match place { - Place::Base(PlaceBase::Local(_)) | - Place::Base(PlaceBase::Static(_)) => { - StorageDeadOrDrop::LocalStorageDead - } - Place::Projection(box PlaceProjection { base, elem }) => { - let base_access = self.classify_drop_access_kind(base); - match elem { - ProjectionElem::Deref => match base_access { - StorageDeadOrDrop::LocalStorageDead - | StorageDeadOrDrop::BoxedStorageDead => { - assert!( - base.ty(self.mir, tcx).ty.is_box(), - "Drop of value behind a reference or raw pointer" - ); - StorageDeadOrDrop::BoxedStorageDead - } - StorageDeadOrDrop::Destructor(_) => base_access, - }, - ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => { - let base_ty = base.ty(self.mir, tcx).ty; - match base_ty.sty { - ty::Adt(def, _) if def.has_dtor(tcx) => { - // Report the outermost adt with a destructor - match base_access { - StorageDeadOrDrop::Destructor(_) => base_access, - StorageDeadOrDrop::LocalStorageDead - | StorageDeadOrDrop::BoxedStorageDead => { - StorageDeadOrDrop::Destructor(base_ty) - } - } - } - _ => base_access, - } - } - - ProjectionElem::ConstantIndex { .. } - | ProjectionElem::Subslice { .. } - | ProjectionElem::Index(_) => base_access, - } - } - } - } - - /// Annotate argument and return type of function and closure with (synthesized) lifetime for - /// borrow of local value that does not live long enough. - fn annotate_argument_and_return_for_borrow( - &self, - borrow: &BorrowData<'tcx>, - ) -> Option> { - // Define a fallback for when we can't match a closure. - let fallback = || { - let is_closure = self.infcx.tcx.is_closure(self.mir_def_id); - if is_closure { - None - } else { - let ty = self.infcx.tcx.type_of(self.mir_def_id); - match ty.sty { - ty::FnDef(_, _) | ty::FnPtr(_) => self.annotate_fn_sig( - self.mir_def_id, - self.infcx.tcx.fn_sig(self.mir_def_id), - ), - _ => None, - } - } - }; - - // In order to determine whether we need to annotate, we need to check whether the reserve - // place was an assignment into a temporary. - // - // If it was, we check whether or not that temporary is eventually assigned into the return - // place. If it was, we can add annotations about the function's return type and arguments - // and it'll make sense. - let location = borrow.reserve_location; - debug!( - "annotate_argument_and_return_for_borrow: location={:?}", - location - ); - if let Some(&Statement { kind: StatementKind::Assign(ref reservation, _), ..}) - = &self.mir[location.block].statements.get(location.statement_index) - { - debug!( - "annotate_argument_and_return_for_borrow: reservation={:?}", - reservation - ); - // Check that the initial assignment of the reserve location is into a temporary. - let mut target = *match reservation { - Place::Base(PlaceBase::Local(local)) - if self.mir.local_kind(*local) == LocalKind::Temp => local, - _ => return None, - }; - - // Next, look through the rest of the block, checking if we are assigning the - // `target` (that is, the place that contains our borrow) to anything. - let mut annotated_closure = None; - for stmt in &self.mir[location.block].statements[location.statement_index + 1..] { - debug!( - "annotate_argument_and_return_for_borrow: target={:?} stmt={:?}", - target, stmt - ); - if let StatementKind::Assign( - Place::Base(PlaceBase::Local(assigned_to)), - box rvalue - ) = &stmt.kind { - debug!( - "annotate_argument_and_return_for_borrow: assigned_to={:?} \ - rvalue={:?}", - assigned_to, rvalue - ); - // Check if our `target` was captured by a closure. - if let Rvalue::Aggregate( - box AggregateKind::Closure(def_id, substs), - operands, - ) = rvalue - { - for operand in operands { - let assigned_from = match operand { - Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { - assigned_from - } - _ => continue, - }; - debug!( - "annotate_argument_and_return_for_borrow: assigned_from={:?}", - assigned_from - ); - - // Find the local from the operand. - let assigned_from_local = match assigned_from.local() { - Some(local) => local, - None => continue, - }; - - if assigned_from_local != target { - continue; - } - - // If a closure captured our `target` and then assigned - // into a place then we should annotate the closure in - // case it ends up being assigned into the return place. - annotated_closure = self.annotate_fn_sig( - *def_id, - self.infcx.closure_sig(*def_id, *substs), - ); - debug!( - "annotate_argument_and_return_for_borrow: \ - annotated_closure={:?} assigned_from_local={:?} \ - assigned_to={:?}", - annotated_closure, assigned_from_local, assigned_to - ); - - if *assigned_to == mir::RETURN_PLACE { - // If it was assigned directly into the return place, then - // return now. - return annotated_closure; - } else { - // Otherwise, update the target. - target = *assigned_to; - } - } - - // If none of our closure's operands matched, then skip to the next - // statement. - continue; - } - - // Otherwise, look at other types of assignment. - let assigned_from = match rvalue { - Rvalue::Ref(_, _, assigned_from) => assigned_from, - Rvalue::Use(operand) => match operand { - Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { - assigned_from - } - _ => continue, - }, - _ => continue, - }; - debug!( - "annotate_argument_and_return_for_borrow: \ - assigned_from={:?}", - assigned_from, - ); - - // Find the local from the rvalue. - let assigned_from_local = match assigned_from.local() { - Some(local) => local, - None => continue, - }; - debug!( - "annotate_argument_and_return_for_borrow: \ - assigned_from_local={:?}", - assigned_from_local, - ); - - // Check if our local matches the target - if so, we've assigned our - // borrow to a new place. - if assigned_from_local != target { - continue; - } - - // If we assigned our `target` into a new place, then we should - // check if it was the return place. - debug!( - "annotate_argument_and_return_for_borrow: \ - assigned_from_local={:?} assigned_to={:?}", - assigned_from_local, assigned_to - ); - if *assigned_to == mir::RETURN_PLACE { - // If it was then return the annotated closure if there was one, - // else, annotate this function. - return annotated_closure.or_else(fallback); - } - - // If we didn't assign into the return place, then we just update - // the target. - target = *assigned_to; - } - } - - // Check the terminator if we didn't find anything in the statements. - let terminator = &self.mir[location.block].terminator(); - debug!( - "annotate_argument_and_return_for_borrow: target={:?} terminator={:?}", - target, terminator - ); - if let TerminatorKind::Call { - destination: Some((Place::Base(PlaceBase::Local(assigned_to)), _)), - args, - .. - } = &terminator.kind - { - debug!( - "annotate_argument_and_return_for_borrow: assigned_to={:?} args={:?}", - assigned_to, args - ); - for operand in args { - let assigned_from = match operand { - Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { - assigned_from - } - _ => continue, - }; - debug!( - "annotate_argument_and_return_for_borrow: assigned_from={:?}", - assigned_from, - ); - - if let Some(assigned_from_local) = assigned_from.local() { - debug!( - "annotate_argument_and_return_for_borrow: assigned_from_local={:?}", - assigned_from_local, - ); - - if *assigned_to == mir::RETURN_PLACE && assigned_from_local == target { - return annotated_closure.or_else(fallback); - } - } - } - } - } - - // If we haven't found an assignment into the return place, then we need not add - // any annotations. - debug!("annotate_argument_and_return_for_borrow: none found"); - None - } - - /// Annotate the first argument and return type of a function signature if they are - /// references. - fn annotate_fn_sig( - &self, - did: DefId, - sig: ty::PolyFnSig<'tcx>, - ) -> Option> { - debug!("annotate_fn_sig: did={:?} sig={:?}", did, sig); - let is_closure = self.infcx.tcx.is_closure(did); - let fn_hir_id = self.infcx.tcx.hir().as_local_hir_id(did)?; - let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(fn_hir_id)?; - - // We need to work out which arguments to highlight. We do this by looking - // at the return type, where there are three cases: - // - // 1. If there are named arguments, then we should highlight the return type and - // highlight any of the arguments that are also references with that lifetime. - // If there are no arguments that have the same lifetime as the return type, - // then don't highlight anything. - // 2. The return type is a reference with an anonymous lifetime. If this is - // the case, then we can take advantage of (and teach) the lifetime elision - // rules. - // - // We know that an error is being reported. So the arguments and return type - // must satisfy the elision rules. Therefore, if there is a single argument - // then that means the return type and first (and only) argument have the same - // lifetime and the borrow isn't meeting that, we can highlight the argument - // and return type. - // - // If there are multiple arguments then the first argument must be self (else - // it would not satisfy the elision rules), so we can highlight self and the - // return type. - // 3. The return type is not a reference. In this case, we don't highlight - // anything. - let return_ty = sig.output(); - match return_ty.skip_binder().sty { - ty::Ref(return_region, _, _) if return_region.has_name() && !is_closure => { - // This is case 1 from above, return type is a named reference so we need to - // search for relevant arguments. - let mut arguments = Vec::new(); - for (index, argument) in sig.inputs().skip_binder().iter().enumerate() { - if let ty::Ref(argument_region, _, _) = argument.sty { - if argument_region == return_region { - // Need to use the `rustc::ty` types to compare against the - // `return_region`. Then use the `rustc::hir` type to get only - // the lifetime span. - if let hir::TyKind::Rptr(lifetime, _) = &fn_decl.inputs[index].node { - // With access to the lifetime, we can get - // the span of it. - arguments.push((*argument, lifetime.span)); - } else { - bug!("ty type is a ref but hir type is not"); - } - } - } - } - - // We need to have arguments. This shouldn't happen, but it's worth checking. - if arguments.is_empty() { - return None; - } - - // We use a mix of the HIR and the Ty types to get information - // as the HIR doesn't have full types for closure arguments. - let return_ty = *sig.output().skip_binder(); - let mut return_span = fn_decl.output.span(); - if let hir::FunctionRetTy::Return(ty) = fn_decl.output { - if let hir::TyKind::Rptr(lifetime, _) = ty.into_inner().node { - return_span = lifetime.span; - } - } - - Some(AnnotatedBorrowFnSignature::NamedFunction { - arguments, - return_ty, - return_span, - }) - } - ty::Ref(_, _, _) if is_closure => { - // This is case 2 from above but only for closures, return type is anonymous - // reference so we select - // the first argument. - let argument_span = fn_decl.inputs.first()?.span; - let argument_ty = sig.inputs().skip_binder().first()?; - - // Closure arguments are wrapped in a tuple, so we need to get the first - // from that. - if let ty::Tuple(elems) = argument_ty.sty { - let argument_ty = elems.first()?.expect_ty(); - if let ty::Ref(_, _, _) = argument_ty.sty { - return Some(AnnotatedBorrowFnSignature::Closure { - argument_ty, - argument_span, - }); - } - } - - None - } - ty::Ref(_, _, _) => { - // This is also case 2 from above but for functions, return type is still an - // anonymous reference so we select the first argument. - let argument_span = fn_decl.inputs.first()?.span; - let argument_ty = sig.inputs().skip_binder().first()?; - - let return_span = fn_decl.output.span(); - let return_ty = *sig.output().skip_binder(); - - // We expect the first argument to be a reference. - match argument_ty.sty { - ty::Ref(_, _, _) => {} - _ => return None, - } - - Some(AnnotatedBorrowFnSignature::AnonymousFunction { - argument_ty, - argument_span, - return_ty, - return_span, - }) - } - _ => { - // This is case 3 from above, return type is not a reference so don't highlight - // anything. - None - } - } - } -} - -#[derive(Debug)] -enum AnnotatedBorrowFnSignature<'tcx> { - NamedFunction { - arguments: Vec<(Ty<'tcx>, Span)>, - return_ty: Ty<'tcx>, - return_span: Span, - }, - AnonymousFunction { - argument_ty: Ty<'tcx>, - argument_span: Span, - return_ty: Ty<'tcx>, - return_span: Span, - }, - Closure { - argument_ty: Ty<'tcx>, - argument_span: Span, - }, -} - -impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { - /// Annotate the provided diagnostic with information about borrow from the fn signature that - /// helps explain. - fn emit( - &self, - cx: &mut MirBorrowckCtxt<'_, '_, 'tcx>, - diag: &mut DiagnosticBuilder<'_>, - ) -> String { - match self { - AnnotatedBorrowFnSignature::Closure { - argument_ty, - argument_span, - } => { - diag.span_label( - *argument_span, - format!("has type `{}`", cx.get_name_for_ty(argument_ty, 0)), - ); - - cx.get_region_name_for_ty(argument_ty, 0) - } - AnnotatedBorrowFnSignature::AnonymousFunction { - argument_ty, - argument_span, - return_ty, - return_span, - } => { - let argument_ty_name = cx.get_name_for_ty(argument_ty, 0); - diag.span_label(*argument_span, format!("has type `{}`", argument_ty_name)); - - let return_ty_name = cx.get_name_for_ty(return_ty, 0); - let types_equal = return_ty_name == argument_ty_name; - diag.span_label( - *return_span, - format!( - "{}has type `{}`", - if types_equal { "also " } else { "" }, - return_ty_name, - ), - ); - - diag.note( - "argument and return type have the same lifetime due to lifetime elision rules", - ); - diag.note( - "to learn more, visit ", - ); - - cx.get_region_name_for_ty(return_ty, 0) - } - AnnotatedBorrowFnSignature::NamedFunction { - arguments, - return_ty, - return_span, - } => { - // Region of return type and arguments checked to be the same earlier. - let region_name = cx.get_region_name_for_ty(return_ty, 0); - for (_, argument_span) in arguments { - diag.span_label(*argument_span, format!("has lifetime `{}`", region_name)); - } - - diag.span_label( - *return_span, - format!("also has lifetime `{}`", region_name,), - ); - - diag.help(&format!( - "use data from the highlighted arguments which match the `{}` lifetime of \ - the return type", - region_name, - )); - - region_name - } - } - } } impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// Return the name of the provided `Ty` (that must be a reference) with a synthesized lifetime /// name where required. - fn get_name_for_ty(&self, ty: Ty<'tcx>, counter: usize) -> String { + pub(super) fn get_name_for_ty(&self, ty: Ty<'tcx>, counter: usize) -> String { let mut s = String::new(); let mut printer = ty::print::FmtPrinter::new(self.infcx.tcx, &mut s, Namespace::TypeNS); @@ -2389,7 +411,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// Returns the name of the provided `Ty` (that must be a reference)'s region with a /// synthesized lifetime name where required. - fn get_region_name_for_ty(&self, ty: Ty<'tcx>, counter: usize) -> String { + pub(super) fn get_region_name_for_ty(&self, ty: Ty<'tcx>, counter: usize) -> String { let mut s = String::new(); let mut printer = ty::print::FmtPrinter::new(self.infcx.tcx, &mut s, Namespace::TypeNS); @@ -2469,7 +491,7 @@ impl UseSpans { } /// Returns `false` if this place is not used in a closure. - fn for_closure(&self) -> bool { + pub(super) fn for_closure(&self) -> bool { match *self { UseSpans::ClosureUse { is_generator, .. } => !is_generator, _ => false, @@ -2477,7 +499,7 @@ impl UseSpans { } /// Returns `false` if this place is not used in a generator. - fn for_generator(&self) -> bool { + pub(super) fn for_generator(&self) -> bool { match *self { UseSpans::ClosureUse { is_generator, .. } => is_generator, _ => false, @@ -2485,7 +507,7 @@ impl UseSpans { } /// Describe the span associated with a use of a place. - fn describe(&self) -> String { + pub(super) fn describe(&self) -> String { match *self { UseSpans::ClosureUse { is_generator, .. } => if is_generator { " in generator".to_string() diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index fc1f5eb5d5a7..eb8e5fa5e25a 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -54,6 +54,7 @@ crate mod borrow_set; mod error_reporting; mod flows; mod location; +mod conflict_errors; mod move_errors; mod mutability_errors; mod path_utils; From 8dc945c16912b988a10d48355df3195bff9cdd8f Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 4 May 2019 10:10:37 +0100 Subject: [PATCH 0246/3207] Remove unused parameter in borrowck error reporting --- src/librustc_mir/borrow_check/conflict_errors.rs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs index 19f29f346f96..b00a75bb5696 100644 --- a/src/librustc_mir/borrow_check/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/conflict_errors.rs @@ -1,6 +1,5 @@ use rustc::hir; use rustc::hir::def_id::DefId; -use rustc::middle::region::ScopeTree; use rustc::mir::{ self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory, Local, LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, PlaceProjection, @@ -689,7 +688,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); let drop_span = place_span.1; - let scope_tree = self.infcx.tcx.region_scope_tree(self.mir_def_id); let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All) .last() .unwrap(); @@ -791,7 +789,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { (Some(name), explanation) => self.report_local_value_does_not_live_long_enough( location, &name, - &scope_tree, &borrow, drop_span, borrow_spans, @@ -799,7 +796,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ), (None, explanation) => self.report_temporary_value_does_not_live_long_enough( location, - &scope_tree, &borrow, drop_span, borrow_spans, @@ -815,7 +811,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { &mut self, location: Location, name: &str, - scope_tree: &'tcx ScopeTree, borrow: &BorrowData<'tcx>, drop_span: Span, borrow_spans: UseSpans, @@ -823,9 +818,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ) -> DiagnosticBuilder<'cx> { debug!( "report_local_value_does_not_live_long_enough(\ - {:?}, {:?}, {:?}, {:?}, {:?}, {:?}\ + {:?}, {:?}, {:?}, {:?}, {:?}\ )", - location, name, scope_tree, borrow, drop_span, borrow_spans + location, name, borrow, drop_span, borrow_spans ); let borrow_span = borrow_spans.var_or_use(); @@ -1007,7 +1002,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { fn report_temporary_value_does_not_live_long_enough( &mut self, location: Location, - scope_tree: &'tcx ScopeTree, borrow: &BorrowData<'tcx>, drop_span: Span, borrow_spans: UseSpans, @@ -1016,9 +1010,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ) -> DiagnosticBuilder<'cx> { debug!( "report_temporary_value_does_not_live_long_enough(\ - {:?}, {:?}, {:?}, {:?}, {:?}\ + {:?}, {:?}, {:?}, {:?}\ )", - location, scope_tree, borrow, drop_span, proper_span + location, borrow, drop_span, proper_span ); if let BorrowExplanation::MustBeValidFor { From beea4f5e4a95126ab5837c76eea06f9fcd15fb45 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 21 May 2019 13:32:53 -0700 Subject: [PATCH 0247/3207] Execute everything! --- .azure-pipelines/try.yml | 498 +++++++++++++++++++-------------------- 1 file changed, 249 insertions(+), 249 deletions(-) diff --git a/.azure-pipelines/try.yml b/.azure-pipelines/try.yml index 135fec5f8327..5c76d2053345 100644 --- a/.azure-pipelines/try.yml +++ b/.azure-pipelines/try.yml @@ -18,131 +18,131 @@ jobs: - template: steps/run.yml strategy: matrix: - # x86_64-gnu-llvm-6.0: - # IMAGE: x86_64-gnu-llvm-6.0 - # RUST_BACKTRACE: 1 + x86_64-gnu-llvm-6.0: + IMAGE: x86_64-gnu-llvm-6.0 + RUST_BACKTRACE: 1 dist-x86_64-linux: IMAGE: dist-x86_64-linux DEPLOY: 1 - # dist-x86_64-linux-alt: - # IMAGE: dist-x86_64-linux - # DEPLOY_ALT: 1 + dist-x86_64-linux-alt: + IMAGE: dist-x86_64-linux + DEPLOY_ALT: 1 - # arm-android: - # IMAGE: arm-android - # - # armhf-gnu: - # IMAGE: armhf-gnu - # - # dist-various-1: - # IMAGE: dist-various-1 - # DEPLOY: 1 - # - # dist-various-2: - # IMAGE: dist-various-2 - # DEPLOY: 1 - # - # dist-aarch64-linux: - # IMAGE: dist-aarch64-linux - # DEPLOY: 1 - # - # dist-android: - # IMAGE: dist-android - # DEPLOY: 1 - # - # dist-arm-linux: - # IMAGE: dist-arm-linux - # DEPLOY: 1 - # - # dist-armhf-linux: - # IMAGE: dist-armhf-linux - # DEPLOY: 1 - # - # dist-armv7-linux: - # IMAGE: dist-armv7-linux - # DEPLOY: 1 - # - # dist-i586-gnu-i586-i686-musl: - # IMAGE: dist-i586-gnu-i586-i686-musl - # DEPLOY: 1 - # - # dist-i686-freebsd: - # IMAGE: dist-i686-freebsd - # DEPLOY: 1 - # - # dist-i686-linux: - # IMAGE: dist-i686-linux - # DEPLOY: 1 - # - # dist-mips-linux: - # IMAGE: dist-mips-linux - # DEPLOY: 1 - # - # dist-mips64-linux: - # IMAGE: dist-mips64-linux - # DEPLOY: 1 - # - # dist-mips64el-linux: - # IMAGE: dist-mips64el-linux - # DEPLOY: 1 - # - # dist-mipsel-linux: - # IMAGE: dist-mipsel-linux - # DEPLOY: 1 - # - # dist-powerpc-linux: - # IMAGE: dist-powerpc-linux - # DEPLOY: 1 - # - # dist-powerpc64-linux: - # IMAGE: dist-powerpc64-linux - # DEPLOY: 1 - # - # dist-powerpc64le-linux: - # IMAGE: dist-powerpc64le-linux - # DEPLOY: 1 - # - # dist-s390x-linux: - # IMAGE: dist-s390x-linux - # DEPLOY: 1 - # - # dist-x86_64-freebsd: - # IMAGE: dist-x86_64-freebsd - # DEPLOY: 1 - # - # dist-x86_64-musl: - # IMAGE: dist-x86_64-musl - # DEPLOY: 1 - # - # dist-x86_64-netbsd: - # IMAGE: dist-x86_64-netbsd - # DEPLOY: 1 - # - # asmjs: - # IMAGE: asmjs - # i686-gnu: - # IMAGE: i686-gnu - # i686-gnu-nopt: - # IMAGE: i686-gnu-nopt - # test-various: - # IMAGE: test-various + arm-android: + IMAGE: arm-android + + armhf-gnu: + IMAGE: armhf-gnu + + dist-various-1: + IMAGE: dist-various-1 + DEPLOY: 1 + + dist-various-2: + IMAGE: dist-various-2 + DEPLOY: 1 + + dist-aarch64-linux: + IMAGE: dist-aarch64-linux + DEPLOY: 1 + + dist-android: + IMAGE: dist-android + DEPLOY: 1 + + dist-arm-linux: + IMAGE: dist-arm-linux + DEPLOY: 1 + + dist-armhf-linux: + IMAGE: dist-armhf-linux + DEPLOY: 1 + + dist-armv7-linux: + IMAGE: dist-armv7-linux + DEPLOY: 1 + + dist-i586-gnu-i586-i686-musl: + IMAGE: dist-i586-gnu-i586-i686-musl + DEPLOY: 1 + + dist-i686-freebsd: + IMAGE: dist-i686-freebsd + DEPLOY: 1 + + dist-i686-linux: + IMAGE: dist-i686-linux + DEPLOY: 1 + + dist-mips-linux: + IMAGE: dist-mips-linux + DEPLOY: 1 + + dist-mips64-linux: + IMAGE: dist-mips64-linux + DEPLOY: 1 + + dist-mips64el-linux: + IMAGE: dist-mips64el-linux + DEPLOY: 1 + + dist-mipsel-linux: + IMAGE: dist-mipsel-linux + DEPLOY: 1 + + dist-powerpc-linux: + IMAGE: dist-powerpc-linux + DEPLOY: 1 + + dist-powerpc64-linux: + IMAGE: dist-powerpc64-linux + DEPLOY: 1 + + dist-powerpc64le-linux: + IMAGE: dist-powerpc64le-linux + DEPLOY: 1 + + dist-s390x-linux: + IMAGE: dist-s390x-linux + DEPLOY: 1 + + dist-x86_64-freebsd: + IMAGE: dist-x86_64-freebsd + DEPLOY: 1 + + dist-x86_64-musl: + IMAGE: dist-x86_64-musl + DEPLOY: 1 + + dist-x86_64-netbsd: + IMAGE: dist-x86_64-netbsd + DEPLOY: 1 + + asmjs: + IMAGE: asmjs + i686-gnu: + IMAGE: i686-gnu + i686-gnu-nopt: + IMAGE: i686-gnu-nopt + test-various: + IMAGE: test-various x86_64-gnu: IMAGE: x86_64-gnu - # x86_64-gnu-full-bootstrap: - # IMAGE: x86_64-gnu-full-bootstrap - # x86_64-gnu-aux: - # IMAGE: x86_64-gnu-aux - # x86_64-gnu-tools: - # IMAGE: x86_64-gnu-tools - # x86_64-gnu-debug: - # IMAGE: x86_64-gnu-debug - # x86_64-gnu-nopt: - # IMAGE: x86_64-gnu-nopt - # x86_64-gnu-distcheck: - # IMAGE: x86_64-gnu-distcheck - # mingw-check: - # IMAGE: mingw-check + x86_64-gnu-full-bootstrap: + IMAGE: x86_64-gnu-full-bootstrap + x86_64-gnu-aux: + IMAGE: x86_64-gnu-aux + x86_64-gnu-tools: + IMAGE: x86_64-gnu-tools + x86_64-gnu-debug: + IMAGE: x86_64-gnu-debug + x86_64-gnu-nopt: + IMAGE: x86_64-gnu-nopt + x86_64-gnu-distcheck: + IMAGE: x86_64-gnu-distcheck + mingw-check: + IMAGE: mingw-check - job: macOS timeoutInMinutes: 600 @@ -177,33 +177,33 @@ jobs: NO_DEBUG_ASSERTIONS: 1 DIST_REQUIRE_ALL_TOOLS: 1 - # dist-x86_64-apple-alt: - # RUST_CHECK_TARGET: dist - # RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --enable-lldb --set rust.jemalloc - # DEPLOY_ALT: 1 - # RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - # MACOSX_DEPLOYMENT_TARGET: 10.7 - # NO_LLVM_ASSERTIONS: 1 - # NO_DEBUG_ASSERTIONS: 1 - # - # i686-apple: - # RUST_CHECK_TARGET: check - # RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --set rust.jemalloc - # RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - # MACOSX_DEPLOYMENT_TARGET: 10.8 - # MACOSX_STD_DEPLOYMENT_TARGET: 10.7 - # NO_LLVM_ASSERTIONS: 1 - # NO_DEBUG_ASSERTIONS: 1 - # - # dist-i686-apple: - # RUST_CHECK_TARGET: dist - # RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb --set rust.jemalloc - # DEPLOY: 1 - # RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - # MACOSX_DEPLOYMENT_TARGET: 10.7 - # NO_LLVM_ASSERTIONS: 1 - # NO_DEBUG_ASSERTIONS: 1 - # DIST_REQUIRE_ALL_TOOLS: 1 + dist-x86_64-apple-alt: + RUST_CHECK_TARGET: dist + RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --enable-lldb --set rust.jemalloc + DEPLOY_ALT: 1 + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + + i686-apple: + RUST_CHECK_TARGET: check + RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + + dist-i686-apple: + RUST_CHECK_TARGET: dist + RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb --set rust.jemalloc + DEPLOY: 1 + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + DIST_REQUIRE_ALL_TOOLS: 1 - job: Windows timeoutInMinutes: 600 @@ -225,77 +225,77 @@ jobs: MSYS_BITS: 64 RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler SCRIPT: make ci-subset-2 - # i686-msvc-1: - # MSYS_BITS: 32 - # RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc - # SCRIPT: make ci-subset-1 - # i686-msvc-2: - # MSYS_BITS: 32 - # RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc - # SCRIPT: make ci-subset-2 - # # MSVC aux tests - # x86_64-msvc-aux: - # MSYS_BITS: 64 - # RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1 - # RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc - # x86_64-msvc-cargo: - # MSYS_BITS: 64 - # SCRIPT: python x.py test src/tools/cargotest src/tools/cargo - # RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc - # VCVARS_BAT: vcvars64.bat - # # MSVC tools tests - # x86_64-msvc-tools: - # MSYS_BITS: 64 - # SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows - # RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri + i686-msvc-1: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc + SCRIPT: make ci-subset-1 + i686-msvc-2: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc + SCRIPT: make ci-subset-2 + # MSVC aux tests + x86_64-msvc-aux: + MSYS_BITS: 64 + RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + x86_64-msvc-cargo: + MSYS_BITS: 64 + SCRIPT: python x.py test src/tools/cargotest src/tools/cargo + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + VCVARS_BAT: vcvars64.bat + # MSVC tools tests + x86_64-msvc-tools: + MSYS_BITS: 64 + SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri + + # 32/64-bit MinGW builds. # - # # 32/64-bit MinGW builds. - # # - # # We are using MinGW with posix threads since LLVM does not compile with - # # the win32 threads version due to missing support for C++'s std::thread. - # # - # # Instead of relying on the MinGW version installed on appveryor we download - # # and install one ourselves so we won't be surprised by changes to appveyor's - # # build image. - # # - # # Finally, note that the downloads below are all in the `rust-lang-ci` S3 - # # bucket, but they cleraly didn't originate there! The downloads originally - # # came from the mingw-w64 SourceForge download site. Unfortunately - # # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. - # i686-mingw-1: - # MSYS_BITS: 32 - # RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - # SCRIPT: make ci-subset-1 - # MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - # MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z - # MINGW_DIR: mingw32 - # # FIXME(#59637) - # NO_DEBUG_ASSERTIONS: 1 - # NO_LLVM_ASSERTIONS: 1 - # i686-mingw-2: - # MSYS_BITS: 32 - # RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - # SCRIPT: make ci-subset-2 - # MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - # MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z - # MINGW_DIR: mingw32 - # x86_64-mingw-1: - # MSYS_BITS: 64 - # SCRIPT: make ci-subset-1 - # RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu - # MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - # MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z - # MINGW_DIR: mingw64 - # # FIXME(#59637) - # NO_DEBUG_ASSERTIONS: 1 - # NO_LLVM_ASSERTIONS: 1 - # x86_64-mingw-2: - # MSYS_BITS: 64 - # SCRIPT: make ci-subset-2 - # RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu - # MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - # MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z - # MINGW_DIR: mingw64 + # We are using MinGW with posix threads since LLVM does not compile with + # the win32 threads version due to missing support for C++'s std::thread. + # + # Instead of relying on the MinGW version installed on appveryor we download + # and install one ourselves so we won't be surprised by changes to appveyor's + # build image. + # + # Finally, note that the downloads below are all in the `rust-lang-ci` S3 + # bucket, but they cleraly didn't originate there! The downloads originally + # came from the mingw-w64 SourceForge download site. Unfortunately + # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. + i686-mingw-1: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + SCRIPT: make ci-subset-1 + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z + MINGW_DIR: mingw32 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + i686-mingw-2: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + SCRIPT: make ci-subset-2 + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z + MINGW_DIR: mingw32 + x86_64-mingw-1: + MSYS_BITS: 64 + SCRIPT: make ci-subset-1 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z + MINGW_DIR: mingw64 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + x86_64-mingw-2: + MSYS_BITS: 64 + SCRIPT: make ci-subset-2 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z + MINGW_DIR: mingw64 # 32/64 bit MSVC and GNU deployment dist-x86_64-msvc: @@ -307,37 +307,37 @@ jobs: SCRIPT: python x.py dist DIST_REQUIRE_ALL_TOOLS: 1 DEPLOY: 1 - # dist-i686-msvc: - # RUST_CONFIGURE_ARGS: > - # --build=i686-pc-windows-msvc - # --target=i586-pc-windows-msvc - # --enable-full-tools - # --enable-profiler - # SCRIPT: python x.py dist - # DIST_REQUIRE_ALL_TOOLS: 1 - # DEPLOY: 1 - # dist-i686-mingw: - # MSYS_BITS: 32 - # RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools - # SCRIPT: python x.py dist - # MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - # MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z - # MINGW_DIR: mingw32 - # DIST_REQUIRE_ALL_TOOLS: 1 - # DEPLOY: 1 - # dist-x86_64-mingw: - # MSYS_BITS: 64 - # SCRIPT: python x.py dist - # RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools - # MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - # MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z - # MINGW_DIR: mingw64 - # DIST_REQUIRE_ALL_TOOLS: 1 - # DEPLOY: 1 - # - # # "alternate" deployment, see .travis.yml for more info - # dist-x86_64-msvc-alt: - # MSYS_BITS: 64 - # RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler - # SCRIPT: python x.py dist - # DEPLOY_ALT: 1 + dist-i686-msvc: + RUST_CONFIGURE_ARGS: > + --build=i686-pc-windows-msvc + --target=i586-pc-windows-msvc + --enable-full-tools + --enable-profiler + SCRIPT: python x.py dist + DIST_REQUIRE_ALL_TOOLS: 1 + DEPLOY: 1 + dist-i686-mingw: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools + SCRIPT: python x.py dist + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z + MINGW_DIR: mingw32 + DIST_REQUIRE_ALL_TOOLS: 1 + DEPLOY: 1 + dist-x86_64-mingw: + MSYS_BITS: 64 + SCRIPT: python x.py dist + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z + MINGW_DIR: mingw64 + DIST_REQUIRE_ALL_TOOLS: 1 + DEPLOY: 1 + + # "alternate" deployment, see .travis.yml for more info + dist-x86_64-msvc-alt: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler + SCRIPT: python x.py dist + DEPLOY_ALT: 1 From 6c3862594210cc0a5e60fbad32d3aab7a4fb512c Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Tue, 21 May 2019 12:38:46 -0700 Subject: [PATCH 0248/3207] Make -Zemit-artifact-notifications also emit the artifact type This is easier for tooling to handle than trying to reverse-engineer it from the filename extension. --- src/librustc_codegen_ssa/back/link.rs | 2 +- src/librustc_errors/emitter.rs | 2 +- src/librustc_errors/lib.rs | 4 ++-- src/librustc_interface/passes.rs | 3 ++- src/libsyntax/json.rs | 6 ++++-- src/test/ui/emit-artifact-notifications.nll.stderr | 2 +- src/test/ui/emit-artifact-notifications.stderr | 2 +- 7 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index d5a56f6a09e0..c1ec2071789e 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -96,7 +96,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(sess: &'a Session, } } if sess.opts.debugging_opts.emit_artifact_notifications { - sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename); + sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename, "link"); } } diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 59cbd65f05c6..b56162deaf1c 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -56,7 +56,7 @@ pub trait Emitter { /// Emit a notification that an artifact has been output. /// This is currently only supported for the JSON format, /// other formats can, and will, simply ignore it. - fn emit_artifact_notification(&mut self, _path: &Path) {} + fn emit_artifact_notification(&mut self, _path: &Path, _artifact_type: &str) {} /// Checks if should show explanations about "rustc --explain" fn should_show_explain(&self) -> bool { diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 3aa87fad0717..2dcf7be2aa8b 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -769,8 +769,8 @@ impl Handler { } } - pub fn emit_artifact_notification(&self, path: &Path) { - self.emitter.borrow_mut().emit_artifact_notification(path); + pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) { + self.emitter.borrow_mut().emit_artifact_notification(path, artifact_type); } } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index c5ac8860ccd9..f17554b1fbdc 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -1052,7 +1052,8 @@ fn encode_and_write_metadata<'tcx>( tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e)); } if tcx.sess.opts.debugging_opts.emit_artifact_notifications { - tcx.sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename); + tcx.sess.parse_sess.span_diagnostic + .emit_artifact_notification(&out_filename, "metadata"); } } diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index 2dd2ecb74930..767ab74355e6 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -92,8 +92,8 @@ impl Emitter for JsonEmitter { } } - fn emit_artifact_notification(&mut self, path: &Path) { - let data = ArtifactNotification { artifact: path }; + fn emit_artifact_notification(&mut self, path: &Path, artifact_type: &str) { + let data = ArtifactNotification { artifact: path, emit: artifact_type }; let result = if self.pretty { writeln!(&mut self.dst, "{}", as_pretty_json(&data)) } else { @@ -185,6 +185,8 @@ struct DiagnosticCode { struct ArtifactNotification<'a> { /// The path of the artifact. artifact: &'a Path, + /// What kind of artifact we're emitting. + emit: &'a str, } impl Diagnostic { diff --git a/src/test/ui/emit-artifact-notifications.nll.stderr b/src/test/ui/emit-artifact-notifications.nll.stderr index 347d9aeac230..5547631a4b02 100644 --- a/src/test/ui/emit-artifact-notifications.nll.stderr +++ b/src/test/ui/emit-artifact-notifications.nll.stderr @@ -1 +1 @@ -{"artifact":"$TEST_BUILD_DIR/emit-artifact-notifications.nll/libemit_artifact_notifications.rmeta"} +{"artifact":"$TEST_BUILD_DIR/emit-artifact-notifications.nll/libemit_artifact_notifications.rmeta","emit":"metadata"} diff --git a/src/test/ui/emit-artifact-notifications.stderr b/src/test/ui/emit-artifact-notifications.stderr index 56c977181ff5..260d41b8f15c 100644 --- a/src/test/ui/emit-artifact-notifications.stderr +++ b/src/test/ui/emit-artifact-notifications.stderr @@ -1 +1 @@ -{"artifact":"$TEST_BUILD_DIR/emit-artifact-notifications/libemit_artifact_notifications.rmeta"} +{"artifact":"$TEST_BUILD_DIR/emit-artifact-notifications/libemit_artifact_notifications.rmeta","emit":"metadata"} From 78965f49c8f730327240f59ed0eae4e007f0a0ea Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 21 May 2019 15:14:20 -0700 Subject: [PATCH 0249/3207] Use xcode 9.3 on all osx builders --- .azure-pipelines/steps/run.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.azure-pipelines/steps/run.yml b/.azure-pipelines/steps/run.yml index 22ffa1010e49..3d07df4d936e 100644 --- a/.azure-pipelines/steps/run.yml +++ b/.azure-pipelines/steps/run.yml @@ -35,11 +35,14 @@ steps: displayName: Install build dependencies (OSX) condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin'), eq(variables['RUST_CHECK_TARGET'],'dist')) +# Switch to XCode 9.3 on OSX since it seems to be the last version that supports +# i686-apple-darwin. We'll eventually want to upgrade this and it will probably +# force us to drop i686-apple-darwin, but let's keep the wheels turning for now. - bash: | set -e sudo xcode-select --switch /Applications/Xcode_9.3.app displayName: Switch to Xcode 9.3 (OSX) - condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin'), eq(variables['RUST_CHECK_TARGET'],'dist')) + condition: and(succeeded(), eq(variables['Agent.OS'], 'Darwin')) - template: install-windows-build-deps.yml From e764f475ca7fffd6167ea991afc7d1b2b3f642dc Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 21 May 2019 15:34:56 -0700 Subject: [PATCH 0250/3207] Disable solaris target since toolchain no longer builds --- src/ci/docker/dist-various-2/Dockerfile | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/ci/docker/dist-various-2/Dockerfile b/src/ci/docker/dist-various-2/Dockerfile index 1d6a0269c5b5..04db5e9c0572 100644 --- a/src/ci/docker/dist-various-2/Dockerfile +++ b/src/ci/docker/dist-various-2/Dockerfile @@ -32,9 +32,10 @@ COPY dist-various-2/build-cloudabi-toolchain.sh /tmp/ RUN /tmp/build-cloudabi-toolchain.sh x86_64-unknown-cloudabi COPY dist-various-2/build-fuchsia-toolchain.sh /tmp/ RUN /tmp/build-fuchsia-toolchain.sh -COPY dist-various-2/build-solaris-toolchain.sh /tmp/ -RUN /tmp/build-solaris-toolchain.sh x86_64 amd64 solaris-i386 -RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc +# FIXME(#61022) - reenable solaris +# COPY dist-various-2/build-solaris-toolchain.sh /tmp/ +# RUN /tmp/build-solaris-toolchain.sh x86_64 amd64 solaris-i386 +# RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc COPY dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh /tmp/ # We pass the commit id of the port of LLVM's libunwind to the build script. # Any update to the commit id here, should cause the container image to be re-built from this point on. @@ -73,10 +74,11 @@ ENV CARGO_TARGET_AARCH64_FUCHSIA_RUSTFLAGS \ ENV TARGETS=x86_64-fuchsia ENV TARGETS=$TARGETS,aarch64-fuchsia -ENV TARGETS=$TARGETS,sparcv9-sun-solaris ENV TARGETS=$TARGETS,wasm32-unknown-unknown ENV TARGETS=$TARGETS,wasm32-unknown-wasi -ENV TARGETS=$TARGETS,x86_64-sun-solaris +# FIXME(#61022) - reenable solaris +# ENV TARGETS=$TARGETS,sparcv9-sun-solaris +# ENV TARGETS=$TARGETS,x86_64-sun-solaris ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32 ENV TARGETS=$TARGETS,x86_64-unknown-cloudabi ENV TARGETS=$TARGETS,x86_64-fortanix-unknown-sgx From e0ed2a3f60f3e477c372ec0197e0cd676ada36b6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 21 May 2019 15:55:26 -0700 Subject: [PATCH 0251/3207] Correct the upload_dir in script --- .azure-pipelines/steps/run.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure-pipelines/steps/run.yml b/.azure-pipelines/steps/run.yml index 3d07df4d936e..f7ee490b1fdc 100644 --- a/.azure-pipelines/steps/run.yml +++ b/.azure-pipelines/steps/run.yml @@ -118,7 +118,7 @@ steps: set -e if [ "$AGENT_OS" = "Linux" ]; then rm -rf obj/build/dist/doc - upload_dir=obj/build/dist deploy/$BUILD_SOURCEVERSION + upload_dir=obj/build/dist else rm -rf build/dist/doc upload_dir=build/dist From e5418f61deb65a2d5a2bd48320e05d9cf689cff6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 21 May 2019 15:57:47 -0700 Subject: [PATCH 0252/3207] Update webrender we're testing The one locked here has a dependency on an old enough `cmake` crate that it's not detecting visual studio correctly. Let's update webrender which updates `cmake` which should be able to detect Visual Studio correctly. --- src/tools/cargotest/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs index 3126b44f0d61..14035eedbb44 100644 --- a/src/tools/cargotest/main.rs +++ b/src/tools/cargotest/main.rs @@ -61,7 +61,7 @@ const TEST_REPOS: &'static [Test] = &[ Test { name: "webrender", repo: "https://github.com/servo/webrender", - sha: "57250b2b8fa63934f80e5376a29f7dcb3f759ad6", + sha: "cdadd068f4c7218bd983d856981d561e605270ab", lock: None, packages: &[], }, From fb52aeafc97f4927e7dcc178a81bc005c3dc0015 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 22 May 2019 01:09:58 +0300 Subject: [PATCH 0253/3207] tests: Centralize proc macros commonly used for testing --- src/test/ui/custom-derive/auxiliary/plugin.rs | 28 ----- src/test/ui/custom-derive/derive-in-mod.rs | 13 --- .../helper-attr-blocked-by-import-ambig.rs | 12 -- ...helper-attr-blocked-by-import-ambig.stderr | 21 ---- .../helper-attr-blocked-by-import.rs | 28 ----- src/test/ui/custom-derive/issue-36935.rs | 12 -- src/test/ui/custom-derive/issue-36935.stderr | 10 -- .../proc-macro/attribute-order-restricted.rs | 10 +- .../attribute-order-restricted.stderr | 4 +- .../ui/proc-macro/attribute-with-error.rs | 17 ++- .../ui/proc-macro/attribute-with-error.stderr | 8 +- .../proc-macro/auxiliary/attr_proc_macro.rs | 13 --- .../auxiliary/attribute-with-error.rs | 13 --- .../proc-macro/auxiliary/bang_proc_macro.rs | 13 --- .../ui/proc-macro/auxiliary/derive-a-b.rs | 17 --- src/test/ui/proc-macro/auxiliary/derive-a.rs | 13 --- .../auxiliary/derive-helper-shadowed-2.rs | 2 +- .../auxiliary/derive-helper-shadowed.rs | 12 -- .../auxiliary/derive-helper-shadowing.rs | 17 --- .../ui/proc-macro/auxiliary/derive-panic.rs | 13 --- .../auxiliary/dollar-crate-external.rs | 6 +- .../ui/proc-macro/auxiliary/dollar-crate.rs | 35 ------ .../ui/proc-macro/auxiliary/issue-41211.rs | 12 -- .../ui/proc-macro/auxiliary/issue-53481.rs | 13 --- .../ui/proc-macro/auxiliary/macro-brackets.rs | 12 -- .../proc-macro/auxiliary/nested-item-spans.rs | 13 --- .../proc-macro/auxiliary/proc-macro-gates.rs | 18 --- .../proc-macro/auxiliary/span-preservation.rs | 13 --- .../ui/proc-macro/auxiliary/test-macros.rs | 104 +++++++++++++++-- .../ui/proc-macro/derive-helper-shadowed.rs | 12 +- .../ui/proc-macro/derive-helper-shadowing.rs | 20 ++-- .../proc-macro/derive-helper-shadowing.stderr | 34 +++--- src/test/ui/proc-macro/derive-in-mod.rs | 13 +++ src/test/ui/proc-macro/derive-still-gated.rs | 8 +- .../ui/proc-macro/derive-still-gated.stderr | 8 +- .../ui/proc-macro/dollar-crate-issue-57089.rs | 9 +- .../dollar-crate-issue-57089.stdout | 9 +- src/test/ui/proc-macro/dollar-crate.rs | 13 +-- src/test/ui/proc-macro/dollar-crate.stderr | 4 +- src/test/ui/proc-macro/dollar-crate.stdout | 28 +++-- .../helper-attr-blocked-by-import-ambig.rs | 11 ++ ...helper-attr-blocked-by-import-ambig.stderr | 21 ++++ .../helper-attr-blocked-by-import.rs | 28 +++++ src/test/ui/proc-macro/import.rs | 11 +- src/test/ui/proc-macro/import.stderr | 8 +- src/test/ui/proc-macro/issue-36935.rs | 12 ++ src/test/ui/proc-macro/issue-36935.stderr | 10 ++ src/test/ui/proc-macro/issue-37788.rs | 4 +- src/test/ui/proc-macro/issue-41211.rs | 10 +- src/test/ui/proc-macro/issue-41211.stderr | 10 +- src/test/ui/proc-macro/issue-53481.rs | 14 +-- src/test/ui/proc-macro/load-panic.rs | 7 +- src/test/ui/proc-macro/load-panic.stderr | 8 +- src/test/ui/proc-macro/macro-brackets.rs | 8 +- src/test/ui/proc-macro/macro-use-attr.rs | 7 +- src/test/ui/proc-macro/macro-use-bang.rs | 6 +- src/test/ui/proc-macro/macros-in-extern.rs | 9 +- .../ui/proc-macro/macros-in-extern.stderr | 18 +-- src/test/ui/proc-macro/nested-item-spans.rs | 11 +- .../ui/proc-macro/nested-item-spans.stderr | 4 +- src/test/ui/proc-macro/no-macro-use-attr.rs | 4 +- .../ui/proc-macro/no-macro-use-attr.stderr | 4 +- src/test/ui/proc-macro/proc-macro-gates.rs | 43 +++---- .../ui/proc-macro/proc-macro-gates.stderr | 108 +++++++++--------- src/test/ui/proc-macro/proc-macro-gates2.rs | 11 +- .../ui/proc-macro/proc-macro-gates2.stderr | 16 +-- src/test/ui/proc-macro/resolve-error.rs | 10 +- src/test/ui/proc-macro/resolve-error.stderr | 16 +-- src/test/ui/proc-macro/shadow.rs | 6 +- src/test/ui/proc-macro/shadow.stderr | 12 +- src/test/ui/proc-macro/span-preservation.rs | 17 ++- .../ui/proc-macro/span-preservation.stderr | 10 +- 72 files changed, 480 insertions(+), 654 deletions(-) delete mode 100644 src/test/ui/custom-derive/auxiliary/plugin.rs delete mode 100644 src/test/ui/custom-derive/derive-in-mod.rs delete mode 100644 src/test/ui/custom-derive/helper-attr-blocked-by-import-ambig.rs delete mode 100644 src/test/ui/custom-derive/helper-attr-blocked-by-import-ambig.stderr delete mode 100644 src/test/ui/custom-derive/helper-attr-blocked-by-import.rs delete mode 100644 src/test/ui/custom-derive/issue-36935.rs delete mode 100644 src/test/ui/custom-derive/issue-36935.stderr delete mode 100644 src/test/ui/proc-macro/auxiliary/attr_proc_macro.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/attribute-with-error.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/bang_proc_macro.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/derive-a-b.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/derive-a.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/derive-helper-shadowed.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/derive-helper-shadowing.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/derive-panic.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/dollar-crate.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/issue-41211.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/issue-53481.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/macro-brackets.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/nested-item-spans.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/proc-macro-gates.rs delete mode 100644 src/test/ui/proc-macro/auxiliary/span-preservation.rs create mode 100644 src/test/ui/proc-macro/derive-in-mod.rs create mode 100644 src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs create mode 100644 src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr create mode 100644 src/test/ui/proc-macro/helper-attr-blocked-by-import.rs create mode 100644 src/test/ui/proc-macro/issue-36935.rs create mode 100644 src/test/ui/proc-macro/issue-36935.stderr diff --git a/src/test/ui/custom-derive/auxiliary/plugin.rs b/src/test/ui/custom-derive/auxiliary/plugin.rs deleted file mode 100644 index 5e500de607c1..000000000000 --- a/src/test/ui/custom-derive/auxiliary/plugin.rs +++ /dev/null @@ -1,28 +0,0 @@ -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] - -extern crate proc_macro; - -use proc_macro::TokenStream; - -#[proc_macro_derive(Foo)] -pub fn derive_foo(input: TokenStream) -> TokenStream { - input -} - -#[proc_macro_derive(Bar)] -pub fn derive_bar(input: TokenStream) -> TokenStream { - panic!("lolnope"); -} - -#[proc_macro_derive(WithHelper, attributes(helper))] -pub fn with_helper(input: TokenStream) -> TokenStream { - TokenStream::new() -} - -#[proc_macro_attribute] -pub fn helper(_: TokenStream, input: TokenStream) -> TokenStream { - input -} diff --git a/src/test/ui/custom-derive/derive-in-mod.rs b/src/test/ui/custom-derive/derive-in-mod.rs deleted file mode 100644 index 8478ff1a6ae6..000000000000 --- a/src/test/ui/custom-derive/derive-in-mod.rs +++ /dev/null @@ -1,13 +0,0 @@ -// compile-pass -// aux-build:plugin.rs - -extern crate plugin; - -mod inner { - use plugin::WithHelper; - - #[derive(WithHelper)] - struct S; -} - -fn main() {} diff --git a/src/test/ui/custom-derive/helper-attr-blocked-by-import-ambig.rs b/src/test/ui/custom-derive/helper-attr-blocked-by-import-ambig.rs deleted file mode 100644 index ba072ba3568b..000000000000 --- a/src/test/ui/custom-derive/helper-attr-blocked-by-import-ambig.rs +++ /dev/null @@ -1,12 +0,0 @@ -// aux-build:plugin.rs - -#[macro_use(WithHelper)] -extern crate plugin; - -use plugin::helper; - -#[derive(WithHelper)] -#[helper] //~ ERROR `helper` is ambiguous -struct S; - -fn main() {} diff --git a/src/test/ui/custom-derive/helper-attr-blocked-by-import-ambig.stderr b/src/test/ui/custom-derive/helper-attr-blocked-by-import-ambig.stderr deleted file mode 100644 index e83c291c9bfe..000000000000 --- a/src/test/ui/custom-derive/helper-attr-blocked-by-import-ambig.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0659]: `helper` is ambiguous (derive helper attribute vs any other name) - --> $DIR/helper-attr-blocked-by-import-ambig.rs:9:3 - | -LL | #[helper] - | ^^^^^^ ambiguous name - | -note: `helper` could refer to the derive helper attribute defined here - --> $DIR/helper-attr-blocked-by-import-ambig.rs:8:10 - | -LL | #[derive(WithHelper)] - | ^^^^^^^^^^ -note: `helper` could also refer to the attribute macro imported here - --> $DIR/helper-attr-blocked-by-import-ambig.rs:6:5 - | -LL | use plugin::helper; - | ^^^^^^^^^^^^^^ - = help: use `crate::helper` to refer to this attribute macro unambiguously - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/custom-derive/helper-attr-blocked-by-import.rs b/src/test/ui/custom-derive/helper-attr-blocked-by-import.rs deleted file mode 100644 index abbf014f5533..000000000000 --- a/src/test/ui/custom-derive/helper-attr-blocked-by-import.rs +++ /dev/null @@ -1,28 +0,0 @@ -// compile-pass -// aux-build:plugin.rs - -#[macro_use(WithHelper)] -extern crate plugin; - -use self::one::*; -use self::two::*; - -mod helper {} - -mod one { - use helper; - - #[derive(WithHelper)] - #[helper] - struct One; -} - -mod two { - use helper; - - #[derive(WithHelper)] - #[helper] - struct Two; -} - -fn main() {} diff --git a/src/test/ui/custom-derive/issue-36935.rs b/src/test/ui/custom-derive/issue-36935.rs deleted file mode 100644 index 7a5d19f771f3..000000000000 --- a/src/test/ui/custom-derive/issue-36935.rs +++ /dev/null @@ -1,12 +0,0 @@ -// aux-build:plugin.rs - - -#[macro_use] extern crate plugin; - -#[derive(Foo, Bar)] //~ ERROR proc-macro derive panicked -struct Baz { - a: i32, - b: i32, -} - -fn main() {} diff --git a/src/test/ui/custom-derive/issue-36935.stderr b/src/test/ui/custom-derive/issue-36935.stderr deleted file mode 100644 index 2875bc5fce99..000000000000 --- a/src/test/ui/custom-derive/issue-36935.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: proc-macro derive panicked - --> $DIR/issue-36935.rs:6:15 - | -LL | #[derive(Foo, Bar)] - | ^^^ - | - = help: message: lolnope - -error: aborting due to previous error - diff --git a/src/test/ui/proc-macro/attribute-order-restricted.rs b/src/test/ui/proc-macro/attribute-order-restricted.rs index 7b1eecd15586..a3d4d23450ca 100644 --- a/src/test/ui/proc-macro/attribute-order-restricted.rs +++ b/src/test/ui/proc-macro/attribute-order-restricted.rs @@ -1,14 +1,14 @@ -// aux-build:attr_proc_macro.rs +// aux-build:test-macros.rs -extern crate attr_proc_macro; -use attr_proc_macro::*; +#[macro_use] +extern crate test_macros; -#[attr_proc_macro] // OK +#[identity_attr] // OK #[derive(Clone)] struct Before; #[derive(Clone)] -#[attr_proc_macro] //~ ERROR macro attributes must be placed before `#[derive]` +#[identity_attr] //~ ERROR macro attributes must be placed before `#[derive]` struct After; fn main() {} diff --git a/src/test/ui/proc-macro/attribute-order-restricted.stderr b/src/test/ui/proc-macro/attribute-order-restricted.stderr index 39db45cf569a..9ca8a443e40f 100644 --- a/src/test/ui/proc-macro/attribute-order-restricted.stderr +++ b/src/test/ui/proc-macro/attribute-order-restricted.stderr @@ -1,8 +1,8 @@ error: macro attributes must be placed before `#[derive]` --> $DIR/attribute-order-restricted.rs:11:1 | -LL | #[attr_proc_macro] - | ^^^^^^^^^^^^^^^^^^ +LL | #[identity_attr] + | ^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/proc-macro/attribute-with-error.rs b/src/test/ui/proc-macro/attribute-with-error.rs index 2cced40830a7..aaa6c07dddbb 100644 --- a/src/test/ui/proc-macro/attribute-with-error.rs +++ b/src/test/ui/proc-macro/attribute-with-error.rs @@ -1,12 +1,11 @@ -// aux-build:attribute-with-error.rs +// aux-build:test-macros.rs #![feature(custom_inner_attributes)] -extern crate attribute_with_error; +#[macro_use] +extern crate test_macros; -use attribute_with_error::foo; - -#[foo] +#[recollect_attr] fn test1() { let a: i32 = "foo"; //~^ ERROR: mismatched types @@ -15,13 +14,13 @@ fn test1() { } fn test2() { - #![foo] + #![recollect_attr] // FIXME: should have a type error here and assert it works but it doesn't } trait A { - // FIXME: should have a #[foo] attribute here and assert that it works + // FIXME: should have a #[recollect_attr] attribute here and assert that it works fn foo(&self) { let a: i32 = "foo"; //~^ ERROR: mismatched types @@ -31,13 +30,13 @@ trait A { struct B; impl A for B { - #[foo] + #[recollect_attr] fn foo(&self) { let a: i32 = "foo"; //~^ ERROR: mismatched types } } -#[foo] +#[recollect_attr] fn main() { } diff --git a/src/test/ui/proc-macro/attribute-with-error.stderr b/src/test/ui/proc-macro/attribute-with-error.stderr index c5970ab6baaf..937d47ff0897 100644 --- a/src/test/ui/proc-macro/attribute-with-error.stderr +++ b/src/test/ui/proc-macro/attribute-with-error.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/attribute-with-error.rs:11:18 + --> $DIR/attribute-with-error.rs:10:18 | LL | let a: i32 = "foo"; | ^^^^^ expected i32, found reference @@ -8,7 +8,7 @@ LL | let a: i32 = "foo"; found type `&'static str` error[E0308]: mismatched types - --> $DIR/attribute-with-error.rs:13:18 + --> $DIR/attribute-with-error.rs:12:18 | LL | let b: i32 = "f'oo"; | ^^^^^^ expected i32, found reference @@ -17,7 +17,7 @@ LL | let b: i32 = "f'oo"; found type `&'static str` error[E0308]: mismatched types - --> $DIR/attribute-with-error.rs:26:22 + --> $DIR/attribute-with-error.rs:25:22 | LL | let a: i32 = "foo"; | ^^^^^ expected i32, found reference @@ -26,7 +26,7 @@ LL | let a: i32 = "foo"; found type `&'static str` error[E0308]: mismatched types - --> $DIR/attribute-with-error.rs:36:22 + --> $DIR/attribute-with-error.rs:35:22 | LL | let a: i32 = "foo"; | ^^^^^ expected i32, found reference diff --git a/src/test/ui/proc-macro/auxiliary/attr_proc_macro.rs b/src/test/ui/proc-macro/auxiliary/attr_proc_macro.rs deleted file mode 100644 index b1f54be6bac4..000000000000 --- a/src/test/ui/proc-macro/auxiliary/attr_proc_macro.rs +++ /dev/null @@ -1,13 +0,0 @@ -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] - -extern crate proc_macro; - -use proc_macro::TokenStream; - -#[proc_macro_attribute] -pub fn attr_proc_macro(_: TokenStream, input: TokenStream) -> TokenStream { - input -} diff --git a/src/test/ui/proc-macro/auxiliary/attribute-with-error.rs b/src/test/ui/proc-macro/auxiliary/attribute-with-error.rs deleted file mode 100644 index c073be003101..000000000000 --- a/src/test/ui/proc-macro/auxiliary/attribute-with-error.rs +++ /dev/null @@ -1,13 +0,0 @@ -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] - -extern crate proc_macro; - -use proc_macro::TokenStream; - -#[proc_macro_attribute] -pub fn foo(_attr: TokenStream, input: TokenStream) -> TokenStream { - input.into_iter().collect() -} diff --git a/src/test/ui/proc-macro/auxiliary/bang_proc_macro.rs b/src/test/ui/proc-macro/auxiliary/bang_proc_macro.rs deleted file mode 100644 index 16f3b7640290..000000000000 --- a/src/test/ui/proc-macro/auxiliary/bang_proc_macro.rs +++ /dev/null @@ -1,13 +0,0 @@ -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] - -extern crate proc_macro; - -use proc_macro::TokenStream; - -#[proc_macro] -pub fn bang_proc_macro(input: TokenStream) -> TokenStream { - input -} diff --git a/src/test/ui/proc-macro/auxiliary/derive-a-b.rs b/src/test/ui/proc-macro/auxiliary/derive-a-b.rs deleted file mode 100644 index 64d4e0f7b7ae..000000000000 --- a/src/test/ui/proc-macro/auxiliary/derive-a-b.rs +++ /dev/null @@ -1,17 +0,0 @@ -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] - -extern crate proc_macro; -use proc_macro::TokenStream; - -#[proc_macro_derive(A)] -pub fn derive_a(_: TokenStream) -> TokenStream { - "".parse().unwrap() -} - -#[proc_macro_derive(B)] -pub fn derive_b(_: TokenStream) -> TokenStream { - "".parse().unwrap() -} diff --git a/src/test/ui/proc-macro/auxiliary/derive-a.rs b/src/test/ui/proc-macro/auxiliary/derive-a.rs deleted file mode 100644 index c9d94aba9f75..000000000000 --- a/src/test/ui/proc-macro/auxiliary/derive-a.rs +++ /dev/null @@ -1,13 +0,0 @@ -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] - -extern crate proc_macro; - -use proc_macro::TokenStream; - -#[proc_macro_derive(A)] -pub fn derive_a(input: TokenStream) -> TokenStream { - "".parse().unwrap() -} diff --git a/src/test/ui/proc-macro/auxiliary/derive-helper-shadowed-2.rs b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowed-2.rs index 9912a89dafb3..ab532da29922 100644 --- a/src/test/ui/proc-macro/auxiliary/derive-helper-shadowed-2.rs +++ b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowed-2.rs @@ -1,2 +1,2 @@ #[macro_export] -macro_rules! my_attr { () => () } +macro_rules! empty_helper { () => () } diff --git a/src/test/ui/proc-macro/auxiliary/derive-helper-shadowed.rs b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowed.rs deleted file mode 100644 index 5b5243dd60ee..000000000000 --- a/src/test/ui/proc-macro/auxiliary/derive-helper-shadowed.rs +++ /dev/null @@ -1,12 +0,0 @@ -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] - -extern crate proc_macro; -use proc_macro::*; - -#[proc_macro_derive(MyTrait, attributes(my_attr))] -pub fn foo(_: TokenStream) -> TokenStream { - TokenStream::new() -} diff --git a/src/test/ui/proc-macro/auxiliary/derive-helper-shadowing.rs b/src/test/ui/proc-macro/auxiliary/derive-helper-shadowing.rs deleted file mode 100644 index 6e0bdcba9c50..000000000000 --- a/src/test/ui/proc-macro/auxiliary/derive-helper-shadowing.rs +++ /dev/null @@ -1,17 +0,0 @@ -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] - -extern crate proc_macro; -use proc_macro::*; - -#[proc_macro_attribute] -pub fn my_attr(_: TokenStream, input: TokenStream) -> TokenStream { - input -} - -#[proc_macro_derive(MyTrait, attributes(my_attr))] -pub fn derive(input: TokenStream) -> TokenStream { - TokenStream::new() -} diff --git a/src/test/ui/proc-macro/auxiliary/derive-panic.rs b/src/test/ui/proc-macro/auxiliary/derive-panic.rs deleted file mode 100644 index e2afa7affa30..000000000000 --- a/src/test/ui/proc-macro/auxiliary/derive-panic.rs +++ /dev/null @@ -1,13 +0,0 @@ -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] - -extern crate proc_macro; - -use proc_macro::TokenStream; - -#[proc_macro_derive(A)] -pub fn derive_a(_input: TokenStream) -> TokenStream { - panic!("nope!"); -} diff --git a/src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs b/src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs index 8f15a2b975bf..d5d393b5a645 100644 --- a/src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs +++ b/src/test/ui/proc-macro/auxiliary/dollar-crate-external.rs @@ -3,14 +3,14 @@ pub type S = u8; #[macro_export] macro_rules! external { () => { - dollar_crate::m! { + print_bang! { struct M($crate::S); } - #[dollar_crate::a] + #[print_attr] struct A($crate::S); - #[derive(dollar_crate::d)] + #[derive(Print)] struct D($crate::S); }; } diff --git a/src/test/ui/proc-macro/auxiliary/dollar-crate.rs b/src/test/ui/proc-macro/auxiliary/dollar-crate.rs deleted file mode 100644 index c5347d2e81a6..000000000000 --- a/src/test/ui/proc-macro/auxiliary/dollar-crate.rs +++ /dev/null @@ -1,35 +0,0 @@ -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] - -extern crate proc_macro; -use proc_macro::TokenStream; - -#[proc_macro] -pub fn m_empty(input: TokenStream) -> TokenStream { - println!("PROC MACRO INPUT (PRETTY-PRINTED): {}", input); - println!("PROC MACRO INPUT: {:#?}", input); - TokenStream::new() -} - -#[proc_macro] -pub fn m(input: TokenStream) -> TokenStream { - println!("PROC MACRO INPUT (PRETTY-PRINTED): {}", input); - println!("PROC MACRO INPUT: {:#?}", input); - input.into_iter().collect() -} - -#[proc_macro_attribute] -pub fn a(_args: TokenStream, input: TokenStream) -> TokenStream { - println!("ATTRIBUTE INPUT (PRETTY-PRINTED): {}", input); - println!("ATTRIBUTE INPUT: {:#?}", input); - input.into_iter().collect() -} - -#[proc_macro_derive(d)] -pub fn d(input: TokenStream) -> TokenStream { - println!("DERIVE INPUT (PRETTY-PRINTED): {}", input); - println!("DERIVE INPUT: {:#?}", input); - input.into_iter().collect() -} diff --git a/src/test/ui/proc-macro/auxiliary/issue-41211.rs b/src/test/ui/proc-macro/auxiliary/issue-41211.rs deleted file mode 100644 index db946e7f331c..000000000000 --- a/src/test/ui/proc-macro/auxiliary/issue-41211.rs +++ /dev/null @@ -1,12 +0,0 @@ -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] - -extern crate proc_macro; -use proc_macro::TokenStream; - -#[proc_macro_attribute] -pub fn emit_unchanged(_args: TokenStream, input: TokenStream) -> TokenStream { - input -} diff --git a/src/test/ui/proc-macro/auxiliary/issue-53481.rs b/src/test/ui/proc-macro/auxiliary/issue-53481.rs deleted file mode 100644 index d9f290dec7ef..000000000000 --- a/src/test/ui/proc-macro/auxiliary/issue-53481.rs +++ /dev/null @@ -1,13 +0,0 @@ -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] - -extern crate proc_macro; - -use proc_macro::*; - -#[proc_macro_derive(MyTrait, attributes(my_attr))] -pub fn foo(_: TokenStream) -> TokenStream { - TokenStream::new() -} diff --git a/src/test/ui/proc-macro/auxiliary/macro-brackets.rs b/src/test/ui/proc-macro/auxiliary/macro-brackets.rs deleted file mode 100644 index f2c62ab1b5ef..000000000000 --- a/src/test/ui/proc-macro/auxiliary/macro-brackets.rs +++ /dev/null @@ -1,12 +0,0 @@ -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] - -extern crate proc_macro; -use proc_macro::*; - -#[proc_macro_attribute] -pub fn doit(_: TokenStream, input: TokenStream) -> TokenStream { - input.into_iter().collect() -} diff --git a/src/test/ui/proc-macro/auxiliary/nested-item-spans.rs b/src/test/ui/proc-macro/auxiliary/nested-item-spans.rs deleted file mode 100644 index 8f720b4574dd..000000000000 --- a/src/test/ui/proc-macro/auxiliary/nested-item-spans.rs +++ /dev/null @@ -1,13 +0,0 @@ -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] - -extern crate proc_macro; - -use proc_macro::*; - -#[proc_macro_attribute] -pub fn foo(_: TokenStream, item: TokenStream) -> TokenStream { - item.into_iter().collect() -} diff --git a/src/test/ui/proc-macro/auxiliary/proc-macro-gates.rs b/src/test/ui/proc-macro/auxiliary/proc-macro-gates.rs deleted file mode 100644 index c7c7167eca0d..000000000000 --- a/src/test/ui/proc-macro/auxiliary/proc-macro-gates.rs +++ /dev/null @@ -1,18 +0,0 @@ -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] - -extern crate proc_macro; - -use proc_macro::*; - -#[proc_macro] -pub fn m(a: TokenStream) -> TokenStream { - a -} - -#[proc_macro_attribute] -pub fn a(_a: TokenStream, b: TokenStream) -> TokenStream { - b -} diff --git a/src/test/ui/proc-macro/auxiliary/span-preservation.rs b/src/test/ui/proc-macro/auxiliary/span-preservation.rs deleted file mode 100644 index 33c7968104b7..000000000000 --- a/src/test/ui/proc-macro/auxiliary/span-preservation.rs +++ /dev/null @@ -1,13 +0,0 @@ -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] - -extern crate proc_macro; - -use proc_macro::TokenStream; - -#[proc_macro_attribute] -pub fn foo(_: TokenStream, input: TokenStream) -> TokenStream { - input.into_iter().collect() -} diff --git a/src/test/ui/proc-macro/auxiliary/test-macros.rs b/src/test/ui/proc-macro/auxiliary/test-macros.rs index 15fe3804f9b4..27efa44f9803 100644 --- a/src/test/ui/proc-macro/auxiliary/test-macros.rs +++ b/src/test/ui/proc-macro/auxiliary/test-macros.rs @@ -1,26 +1,112 @@ // force-host // no-prefer-dynamic +// Proc macros commonly used by tests. +// `panic`/`print` -> `panic_bang`/`print_bang` to avoid conflicts with standard macros. + #![crate_type = "proc-macro"] extern crate proc_macro; - use proc_macro::TokenStream; +// Macro that return empty token stream. + +#[proc_macro] +pub fn empty(_: TokenStream) -> TokenStream { + TokenStream::new() +} + #[proc_macro_attribute] -pub fn nop_attr(_attr: TokenStream, input: TokenStream) -> TokenStream { - assert!(_attr.to_string().is_empty()); +pub fn empty_attr(_: TokenStream, _: TokenStream) -> TokenStream { + TokenStream::new() +} + +#[proc_macro_derive(Empty, attributes(empty_helper))] +pub fn empty_derive(_: TokenStream) -> TokenStream { + TokenStream::new() +} + +// Macro that panics. + +#[proc_macro] +pub fn panic_bang(_: TokenStream) -> TokenStream { + panic!("panic-bang"); +} + +#[proc_macro_attribute] +pub fn panic_attr(_: TokenStream, _: TokenStream) -> TokenStream { + panic!("panic-attr"); +} + +#[proc_macro_derive(Panic, attributes(panic_helper))] +pub fn panic_derive(_: TokenStream) -> TokenStream { + panic!("panic-derive"); +} + +// Macros that return the input stream. + +#[proc_macro] +pub fn identity(input: TokenStream) -> TokenStream { input } #[proc_macro_attribute] -pub fn no_output(_attr: TokenStream, _input: TokenStream) -> TokenStream { - assert!(_attr.to_string().is_empty()); - assert!(!_input.to_string().is_empty()); - "".parse().unwrap() +pub fn identity_attr(_: TokenStream, input: TokenStream) -> TokenStream { + input +} + +#[proc_macro_derive(Identity, attributes(identity_helper))] +pub fn identity_derive(input: TokenStream) -> TokenStream { + input +} + +// Macros that iterate and re-collect the input stream. + +#[proc_macro] +pub fn recollect(input: TokenStream) -> TokenStream { + input.into_iter().collect() +} + +#[proc_macro_attribute] +pub fn recollect_attr(_: TokenStream, input: TokenStream) -> TokenStream { + input.into_iter().collect() +} + +#[proc_macro_derive(Recollect, attributes(recollect_helper))] +pub fn recollect_derive(input: TokenStream) -> TokenStream { + input.into_iter().collect() +} + +// Macros that print their input in the original and re-collected forms (if they differ). + +fn print_helper(input: TokenStream, kind: &str) -> TokenStream { + let input_display = format!("{}", input); + let input_debug = format!("{:#?}", input); + let recollected = input.into_iter().collect(); + let recollected_display = format!("{}", recollected); + let recollected_debug = format!("{:#?}", recollected); + println!("PRINT-{} INPUT (DISPLAY): {}", kind, input_display); + if recollected_display != input_display { + println!("PRINT-{} RE-COLLECTED (DISPLAY): {}", kind, recollected_display); + } + println!("PRINT-{} INPUT (DEBUG): {}", kind, input_debug); + if recollected_debug != input_debug { + println!("PRINT-{} RE-COLLECTED (DEBUG): {}", kind, recollected_debug); + } + recollected } #[proc_macro] -pub fn emit_input(input: TokenStream) -> TokenStream { - input +pub fn print_bang(input: TokenStream) -> TokenStream { + print_helper(input, "BANG") +} + +#[proc_macro_attribute] +pub fn print_attr(_: TokenStream, input: TokenStream) -> TokenStream { + print_helper(input, "ATTR") +} + +#[proc_macro_derive(Print, attributes(print_helper))] +pub fn print_derive(input: TokenStream) -> TokenStream { + print_helper(input, "DERIVE") } diff --git a/src/test/ui/proc-macro/derive-helper-shadowed.rs b/src/test/ui/proc-macro/derive-helper-shadowed.rs index 792b54b3b945..0388e647b58a 100644 --- a/src/test/ui/proc-macro/derive-helper-shadowed.rs +++ b/src/test/ui/proc-macro/derive-helper-shadowed.rs @@ -1,16 +1,16 @@ // compile-pass -// aux-build:derive-helper-shadowed.rs +// aux-build:test-macros.rs // aux-build:derive-helper-shadowed-2.rs #[macro_use] -extern crate derive_helper_shadowed; -#[macro_use(my_attr)] +extern crate test_macros; +#[macro_use(empty_helper)] extern crate derive_helper_shadowed_2; -macro_rules! my_attr { () => () } +macro_rules! empty_helper { () => () } -#[derive(MyTrait)] -#[my_attr] // OK +#[derive(Empty)] +#[empty_helper] // OK struct S; fn main() {} diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.rs b/src/test/ui/proc-macro/derive-helper-shadowing.rs index f6fe9f9fd8b3..cdc0d6da9469 100644 --- a/src/test/ui/proc-macro/derive-helper-shadowing.rs +++ b/src/test/ui/proc-macro/derive-helper-shadowing.rs @@ -1,23 +1,25 @@ -// aux-build:derive-helper-shadowing.rs +// aux-build:test-macros.rs -extern crate derive_helper_shadowing; -use derive_helper_shadowing::*; +#[macro_use] +extern crate test_macros; -#[my_attr] //~ ERROR `my_attr` is ambiguous -#[derive(MyTrait)] +use test_macros::empty_attr as empty_helper; + +#[empty_helper] //~ ERROR `empty_helper` is ambiguous +#[derive(Empty)] struct S { // FIXME No ambiguity, attributes in non-macro positions are not resolved properly - #[my_attr] + #[empty_helper] field: [u8; { // FIXME No ambiguity, derive helpers are not put into scope for non-attributes - use my_attr; + use empty_helper; // FIXME No ambiguity, derive helpers are not put into scope for inner items - #[my_attr] + #[empty_helper] struct U; mod inner { - #[my_attr] //~ ERROR attribute `my_attr` is currently unknown + #[empty_helper] //~ ERROR attribute `empty_helper` is currently unknown struct V; } diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.stderr b/src/test/ui/proc-macro/derive-helper-shadowing.stderr index fb86cabf939c..ed6d30516562 100644 --- a/src/test/ui/proc-macro/derive-helper-shadowing.stderr +++ b/src/test/ui/proc-macro/derive-helper-shadowing.stderr @@ -1,29 +1,29 @@ -error[E0658]: The attribute `my_attr` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/derive-helper-shadowing.rs:20:15 +error[E0658]: The attribute `empty_helper` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/derive-helper-shadowing.rs:22:15 | -LL | #[my_attr] - | ^^^^^^^ +LL | #[empty_helper] + | ^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/29642 = help: add #![feature(custom_attribute)] to the crate attributes to enable -error[E0659]: `my_attr` is ambiguous (derive helper attribute vs any other name) - --> $DIR/derive-helper-shadowing.rs:6:3 +error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name) + --> $DIR/derive-helper-shadowing.rs:8:3 | -LL | #[my_attr] - | ^^^^^^^ ambiguous name +LL | #[empty_helper] + | ^^^^^^^^^^^^ ambiguous name | -note: `my_attr` could refer to the derive helper attribute defined here - --> $DIR/derive-helper-shadowing.rs:7:10 +note: `empty_helper` could refer to the derive helper attribute defined here + --> $DIR/derive-helper-shadowing.rs:9:10 | -LL | #[derive(MyTrait)] - | ^^^^^^^ -note: `my_attr` could also refer to the attribute macro imported here - --> $DIR/derive-helper-shadowing.rs:4:5 +LL | #[derive(Empty)] + | ^^^^^ +note: `empty_helper` could also refer to the attribute macro imported here + --> $DIR/derive-helper-shadowing.rs:6:5 | -LL | use derive_helper_shadowing::*; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: use `crate::my_attr` to refer to this attribute macro unambiguously +LL | use test_macros::empty_attr as empty_helper; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `crate::empty_helper` to refer to this attribute macro unambiguously error: aborting due to 2 previous errors diff --git a/src/test/ui/proc-macro/derive-in-mod.rs b/src/test/ui/proc-macro/derive-in-mod.rs new file mode 100644 index 000000000000..e6b91324f95d --- /dev/null +++ b/src/test/ui/proc-macro/derive-in-mod.rs @@ -0,0 +1,13 @@ +// compile-pass +// aux-build:test-macros.rs + +extern crate test_macros; + +mod inner { + use test_macros::Empty; + + #[derive(Empty)] + struct S; +} + +fn main() {} diff --git a/src/test/ui/proc-macro/derive-still-gated.rs b/src/test/ui/proc-macro/derive-still-gated.rs index 526eff39891a..d895d26f2676 100644 --- a/src/test/ui/proc-macro/derive-still-gated.rs +++ b/src/test/ui/proc-macro/derive-still-gated.rs @@ -1,11 +1,9 @@ -// aux-build:derive-a.rs - -#![allow(warnings)] +// aux-build:test-macros.rs #[macro_use] -extern crate derive_a; +extern crate test_macros; -#[derive_A] //~ ERROR attribute `derive_A` is currently unknown +#[derive_Empty] //~ ERROR attribute `derive_Empty` is currently unknown struct A; fn main() {} diff --git a/src/test/ui/proc-macro/derive-still-gated.stderr b/src/test/ui/proc-macro/derive-still-gated.stderr index d235343ff161..f299b5abdbc6 100644 --- a/src/test/ui/proc-macro/derive-still-gated.stderr +++ b/src/test/ui/proc-macro/derive-still-gated.stderr @@ -1,8 +1,8 @@ -error[E0658]: The attribute `derive_A` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/derive-still-gated.rs:8:3 +error[E0658]: The attribute `derive_Empty` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/derive-still-gated.rs:6:3 | -LL | #[derive_A] - | ^^^^^^^^ help: a built-in attribute with a similar name exists: `derive` +LL | #[derive_Empty] + | ^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/29642 = help: add #![feature(custom_attribute)] to the crate attributes to enable diff --git a/src/test/ui/proc-macro/dollar-crate-issue-57089.rs b/src/test/ui/proc-macro/dollar-crate-issue-57089.rs index 2d54c07ff953..2615db3e119f 100644 --- a/src/test/ui/proc-macro/dollar-crate-issue-57089.rs +++ b/src/test/ui/proc-macro/dollar-crate-issue-57089.rs @@ -1,22 +1,23 @@ // compile-pass // edition:2018 -// aux-build:dollar-crate.rs +// aux-build:test-macros.rs // Anonymize unstable non-dummy spans while still showing dummy spans `0..0`. // normalize-stdout-test "bytes\([^0]\w*\.\.(\w+)\)" -> "bytes(LO..$1)" // normalize-stdout-test "bytes\((\w+)\.\.[^0]\w*\)" -> "bytes($1..HI)" -extern crate dollar_crate; +#[macro_use] +extern crate test_macros; type S = u8; macro_rules! m { () => { - dollar_crate::m_empty! { + print_bang! { struct M($crate::S); } - #[dollar_crate::a] + #[print_attr] struct A($crate::S); }; } diff --git a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout index 618380d7f0be..0611fcb13f26 100644 --- a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout +++ b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout @@ -1,5 +1,5 @@ -PROC MACRO INPUT (PRETTY-PRINTED): struct M ( $crate :: S ) ; -PROC MACRO INPUT: TokenStream [ +PRINT-BANG INPUT (DISPLAY): struct M ( $crate :: S ) ; +PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "struct", span: #2 bytes(LO..HI), @@ -38,8 +38,9 @@ PROC MACRO INPUT: TokenStream [ span: #2 bytes(LO..HI), }, ] -ATTRIBUTE INPUT (PRETTY-PRINTED): struct A(crate::S); -ATTRIBUTE INPUT: TokenStream [ +PRINT-ATTR INPUT (DISPLAY): struct A(crate::S); +PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ( $crate :: S ) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", span: #2 bytes(LO..HI), diff --git a/src/test/ui/proc-macro/dollar-crate.rs b/src/test/ui/proc-macro/dollar-crate.rs index 1460e9a3b2d5..aadd87ffaf20 100644 --- a/src/test/ui/proc-macro/dollar-crate.rs +++ b/src/test/ui/proc-macro/dollar-crate.rs @@ -1,29 +1,28 @@ // edition:2018 -// aux-build:dollar-crate.rs +// aux-build:test-macros.rs // aux-build:dollar-crate-external.rs // Anonymize unstable non-dummy spans while still showing dummy spans `0..0`. // normalize-stdout-test "bytes\([^0]\w*\.\.(\w+)\)" -> "bytes(LO..$1)" // normalize-stdout-test "bytes\((\w+)\.\.[^0]\w*\)" -> "bytes($1..HI)" -extern crate dollar_crate; +#[macro_use] +extern crate test_macros; extern crate dollar_crate_external; type S = u8; mod local { - use crate::dollar_crate; - macro_rules! local { () => { - dollar_crate::m! { + print_bang! { struct M($crate::S); } - #[dollar_crate::a] + #[print_attr] struct A($crate::S); - #[derive(dollar_crate::d)] + #[derive(Print)] struct D($crate::S); //~ ERROR the name `D` is defined multiple times }; } diff --git a/src/test/ui/proc-macro/dollar-crate.stderr b/src/test/ui/proc-macro/dollar-crate.stderr index d1b836e7f6f2..5d78a8e19872 100644 --- a/src/test/ui/proc-macro/dollar-crate.stderr +++ b/src/test/ui/proc-macro/dollar-crate.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `D` is defined multiple times - --> $DIR/dollar-crate.rs:27:13 + --> $DIR/dollar-crate.rs:26:13 | LL | struct D($crate::S); | ^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL | local!(); = note: `D` must be defined only once in the type namespace of this module error[E0428]: the name `D` is defined multiple times - --> $DIR/dollar-crate.rs:37:5 + --> $DIR/dollar-crate.rs:36:5 | LL | dollar_crate_external::external!(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/proc-macro/dollar-crate.stdout b/src/test/ui/proc-macro/dollar-crate.stdout index 454da5394305..3c88ee99842a 100644 --- a/src/test/ui/proc-macro/dollar-crate.stdout +++ b/src/test/ui/proc-macro/dollar-crate.stdout @@ -1,5 +1,5 @@ -PROC MACRO INPUT (PRETTY-PRINTED): struct M ( $crate :: S ) ; -PROC MACRO INPUT: TokenStream [ +PRINT-BANG INPUT (DISPLAY): struct M ( $crate :: S ) ; +PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "struct", span: #2 bytes(LO..HI), @@ -38,8 +38,9 @@ PROC MACRO INPUT: TokenStream [ span: #2 bytes(LO..HI), }, ] -ATTRIBUTE INPUT (PRETTY-PRINTED): struct A(crate::S); -ATTRIBUTE INPUT: TokenStream [ +PRINT-ATTR INPUT (DISPLAY): struct A(crate::S); +PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ( $crate :: S ) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", span: #2 bytes(LO..HI), @@ -78,8 +79,9 @@ ATTRIBUTE INPUT: TokenStream [ span: #2 bytes(LO..HI), }, ] -DERIVE INPUT (PRETTY-PRINTED): struct D(crate::S); -DERIVE INPUT: TokenStream [ +PRINT-DERIVE INPUT (DISPLAY): struct D(crate::S); +PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ( $crate :: S ) ; +PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", span: #2 bytes(LO..HI), @@ -118,8 +120,8 @@ DERIVE INPUT: TokenStream [ span: #2 bytes(LO..HI), }, ] -PROC MACRO INPUT (PRETTY-PRINTED): struct M ( $crate :: S ) ; -PROC MACRO INPUT: TokenStream [ +PRINT-BANG INPUT (DISPLAY): struct M ( $crate :: S ) ; +PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "struct", span: #10 bytes(LO..HI), @@ -158,8 +160,9 @@ PROC MACRO INPUT: TokenStream [ span: #10 bytes(LO..HI), }, ] -ATTRIBUTE INPUT (PRETTY-PRINTED): struct A(::dollar_crate_external::S); -ATTRIBUTE INPUT: TokenStream [ +PRINT-ATTR INPUT (DISPLAY): struct A(::dollar_crate_external::S); +PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ( $crate :: S ) ; +PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", span: #10 bytes(LO..HI), @@ -198,8 +201,9 @@ ATTRIBUTE INPUT: TokenStream [ span: #10 bytes(LO..HI), }, ] -DERIVE INPUT (PRETTY-PRINTED): struct D(::dollar_crate_external::S); -DERIVE INPUT: TokenStream [ +PRINT-DERIVE INPUT (DISPLAY): struct D(::dollar_crate_external::S); +PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ( $crate :: S ) ; +PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", span: #10 bytes(LO..HI), diff --git a/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs b/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs new file mode 100644 index 000000000000..3a1c56efce8c --- /dev/null +++ b/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.rs @@ -0,0 +1,11 @@ +// aux-build:test-macros.rs + +#[macro_use(Empty)] +extern crate test_macros; +use test_macros::empty_attr as empty_helper; + +#[derive(Empty)] +#[empty_helper] //~ ERROR `empty_helper` is ambiguous +struct S; + +fn main() {} diff --git a/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr b/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr new file mode 100644 index 000000000000..012fb105b128 --- /dev/null +++ b/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr @@ -0,0 +1,21 @@ +error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name) + --> $DIR/helper-attr-blocked-by-import-ambig.rs:8:3 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ ambiguous name + | +note: `empty_helper` could refer to the derive helper attribute defined here + --> $DIR/helper-attr-blocked-by-import-ambig.rs:7:10 + | +LL | #[derive(Empty)] + | ^^^^^ +note: `empty_helper` could also refer to the attribute macro imported here + --> $DIR/helper-attr-blocked-by-import-ambig.rs:5:5 + | +LL | use test_macros::empty_attr as empty_helper; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: use `crate::empty_helper` to refer to this attribute macro unambiguously + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/proc-macro/helper-attr-blocked-by-import.rs b/src/test/ui/proc-macro/helper-attr-blocked-by-import.rs new file mode 100644 index 000000000000..6d3e5ec198d8 --- /dev/null +++ b/src/test/ui/proc-macro/helper-attr-blocked-by-import.rs @@ -0,0 +1,28 @@ +// compile-pass +// aux-build:test-macros.rs + +#[macro_use(Empty)] +extern crate test_macros; + +use self::one::*; +use self::two::*; + +mod empty_helper {} + +mod one { + use empty_helper; + + #[derive(Empty)] + #[empty_helper] + struct One; +} + +mod two { + use empty_helper; + + #[derive(Empty)] + #[empty_helper] + struct Two; +} + +fn main() {} diff --git a/src/test/ui/proc-macro/import.rs b/src/test/ui/proc-macro/import.rs index 8fbccdf1aed1..d1b1ff350695 100644 --- a/src/test/ui/proc-macro/import.rs +++ b/src/test/ui/proc-macro/import.rs @@ -1,11 +1,8 @@ -// aux-build:derive-a.rs +// aux-build:test-macros.rs -#![allow(warnings)] +extern crate test_macros; -#[macro_use] -extern crate derive_a; - -use derive_a::derive_a; -//~^ ERROR: unresolved import `derive_a::derive_a` +use test_macros::empty_derive; +//~^ ERROR: unresolved import `test_macros::empty_derive` fn main() {} diff --git a/src/test/ui/proc-macro/import.stderr b/src/test/ui/proc-macro/import.stderr index 813a8ac26046..aae621193ab9 100644 --- a/src/test/ui/proc-macro/import.stderr +++ b/src/test/ui/proc-macro/import.stderr @@ -1,8 +1,8 @@ -error[E0432]: unresolved import `derive_a::derive_a` - --> $DIR/import.rs:8:5 +error[E0432]: unresolved import `test_macros::empty_derive` + --> $DIR/import.rs:5:5 | -LL | use derive_a::derive_a; - | ^^^^^^^^^^^^^^^^^^ no `derive_a` in the root +LL | use test_macros::empty_derive; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ no `empty_derive` in the root error: aborting due to previous error diff --git a/src/test/ui/proc-macro/issue-36935.rs b/src/test/ui/proc-macro/issue-36935.rs new file mode 100644 index 000000000000..f809592d5f44 --- /dev/null +++ b/src/test/ui/proc-macro/issue-36935.rs @@ -0,0 +1,12 @@ +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +#[derive(Identity, Panic)] //~ ERROR proc-macro derive panicked +struct Baz { + a: i32, + b: i32, +} + +fn main() {} diff --git a/src/test/ui/proc-macro/issue-36935.stderr b/src/test/ui/proc-macro/issue-36935.stderr new file mode 100644 index 000000000000..da4366eb668d --- /dev/null +++ b/src/test/ui/proc-macro/issue-36935.stderr @@ -0,0 +1,10 @@ +error: proc-macro derive panicked + --> $DIR/issue-36935.rs:6:20 + | +LL | #[derive(Identity, Panic)] + | ^^^^^ + | + = help: message: panic-derive + +error: aborting due to previous error + diff --git a/src/test/ui/proc-macro/issue-37788.rs b/src/test/ui/proc-macro/issue-37788.rs index 75fcd24d85f6..73b1f0d58c83 100644 --- a/src/test/ui/proc-macro/issue-37788.rs +++ b/src/test/ui/proc-macro/issue-37788.rs @@ -1,7 +1,7 @@ -// aux-build:derive-a-b.rs +// aux-build:test-macros.rs #[macro_use] -extern crate derive_a_b; +extern crate test_macros; fn main() { // Test that constructing the `visible_parent_map` (in `cstore_impl.rs`) does not ICE. diff --git a/src/test/ui/proc-macro/issue-41211.rs b/src/test/ui/proc-macro/issue-41211.rs index 0b082f4818f1..ee9246e1c9b5 100644 --- a/src/test/ui/proc-macro/issue-41211.rs +++ b/src/test/ui/proc-macro/issue-41211.rs @@ -1,14 +1,14 @@ -// aux-build:issue-41211.rs +// aux-build:test-macros.rs // FIXME: https://github.com/rust-lang/rust/issues/41430 // This is a temporary regression test for the ICE reported in #41211 #![feature(custom_inner_attributes)] -#![emit_unchanged] -//~^ ERROR attribute `emit_unchanged` is currently unknown to the compiler +#![identity_attr] +//~^ ERROR attribute `identity_attr` is currently unknown to the compiler //~| ERROR inconsistent resolution for a macro: first custom attribute, then attribute macro -extern crate issue_41211; -use issue_41211::emit_unchanged; +extern crate test_macros; +use test_macros::identity_attr; fn main() {} diff --git a/src/test/ui/proc-macro/issue-41211.stderr b/src/test/ui/proc-macro/issue-41211.stderr index dfb2f6f63d84..1de6b293ecfb 100644 --- a/src/test/ui/proc-macro/issue-41211.stderr +++ b/src/test/ui/proc-macro/issue-41211.stderr @@ -1,8 +1,8 @@ -error[E0658]: The attribute `emit_unchanged` is currently unknown to the compiler and may have meaning added to it in the future +error[E0658]: The attribute `identity_attr` is currently unknown to the compiler and may have meaning added to it in the future --> $DIR/issue-41211.rs:8:4 | -LL | #![emit_unchanged] - | ^^^^^^^^^^^^^^ +LL | #![identity_attr] + | ^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/29642 = help: add #![feature(custom_attribute)] to the crate attributes to enable @@ -10,8 +10,8 @@ LL | #![emit_unchanged] error: inconsistent resolution for a macro: first custom attribute, then attribute macro --> $DIR/issue-41211.rs:8:4 | -LL | #![emit_unchanged] - | ^^^^^^^^^^^^^^ +LL | #![identity_attr] + | ^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/proc-macro/issue-53481.rs b/src/test/ui/proc-macro/issue-53481.rs index 479fd1db630a..2fbde5fedb95 100644 --- a/src/test/ui/proc-macro/issue-53481.rs +++ b/src/test/ui/proc-macro/issue-53481.rs @@ -1,21 +1,21 @@ // compile-pass -// aux-build:issue-53481.rs +// aux-build:test-macros.rs #[macro_use] -extern crate issue_53481; +extern crate test_macros; mod m1 { - use m2::MyTrait; + use m2::Empty; - #[derive(MyTrait)] + #[derive(Empty)] struct A {} } mod m2 { - pub type MyTrait = u8; + pub type Empty = u8; - #[derive(MyTrait)] - #[my_attr] + #[derive(Empty)] + #[empty_helper] struct B {} } diff --git a/src/test/ui/proc-macro/load-panic.rs b/src/test/ui/proc-macro/load-panic.rs index fa279c559fbf..2e9a311d882b 100644 --- a/src/test/ui/proc-macro/load-panic.rs +++ b/src/test/ui/proc-macro/load-panic.rs @@ -1,10 +1,9 @@ -// aux-build:derive-panic.rs -// compile-flags:--error-format human +// aux-build:test-macros.rs #[macro_use] -extern crate derive_panic; +extern crate test_macros; -#[derive(A)] +#[derive(Panic)] //~^ ERROR: proc-macro derive panicked struct Foo; diff --git a/src/test/ui/proc-macro/load-panic.stderr b/src/test/ui/proc-macro/load-panic.stderr index b448c804bff5..40cc4ee0e3d3 100644 --- a/src/test/ui/proc-macro/load-panic.stderr +++ b/src/test/ui/proc-macro/load-panic.stderr @@ -1,10 +1,10 @@ error: proc-macro derive panicked - --> $DIR/load-panic.rs:7:10 + --> $DIR/load-panic.rs:6:10 | -LL | #[derive(A)] - | ^ +LL | #[derive(Panic)] + | ^^^^^ | - = help: message: nope! + = help: message: panic-derive error: aborting due to previous error diff --git a/src/test/ui/proc-macro/macro-brackets.rs b/src/test/ui/proc-macro/macro-brackets.rs index c46abf03654c..aa0046f45822 100644 --- a/src/test/ui/proc-macro/macro-brackets.rs +++ b/src/test/ui/proc-macro/macro-brackets.rs @@ -1,13 +1,13 @@ -// aux-build:macro-brackets.rs +// aux-build:test-macros.rs -extern crate macro_brackets as bar; -use bar::doit; +#[macro_use] +extern crate test_macros; macro_rules! id { ($($t:tt)*) => ($($t)*) } -#[doit] +#[identity_attr] id![static X: u32 = 'a';]; //~ ERROR: mismatched types diff --git a/src/test/ui/proc-macro/macro-use-attr.rs b/src/test/ui/proc-macro/macro-use-attr.rs index 13db0725a388..d1b1430fb5d0 100644 --- a/src/test/ui/proc-macro/macro-use-attr.rs +++ b/src/test/ui/proc-macro/macro-use-attr.rs @@ -1,9 +1,10 @@ // compile-pass -// aux-build:attr_proc_macro.rs +// aux-build:test-macros.rs -#[macro_use] extern crate attr_proc_macro; +#[macro_use] +extern crate test_macros; -#[attr_proc_macro] +#[identity_attr] struct Foo; fn main() { diff --git a/src/test/ui/proc-macro/macro-use-bang.rs b/src/test/ui/proc-macro/macro-use-bang.rs index 4bf3bcd6f3aa..d39c42267fb9 100644 --- a/src/test/ui/proc-macro/macro-use-bang.rs +++ b/src/test/ui/proc-macro/macro-use-bang.rs @@ -1,11 +1,11 @@ // compile-pass -// aux-build:bang_proc_macro.rs +// aux-build:test-macros.rs #![feature(proc_macro_hygiene)] #[macro_use] -extern crate bang_proc_macro; +extern crate test_macros; fn main() { - bang_proc_macro!(println!("Hello, world!")); + identity!(println!("Hello, world!")); } diff --git a/src/test/ui/proc-macro/macros-in-extern.rs b/src/test/ui/proc-macro/macros-in-extern.rs index 5c5603b6c06b..0477b5c48ecc 100644 --- a/src/test/ui/proc-macro/macros-in-extern.rs +++ b/src/test/ui/proc-macro/macros-in-extern.rs @@ -1,10 +1,9 @@ // aux-build:test-macros.rs // ignore-wasm32 +#[macro_use] extern crate test_macros; -use test_macros::{nop_attr, no_output, emit_input}; - fn main() { assert_eq!(unsafe { rust_get_test_int() }, 0isize); assert_eq!(unsafe { rust_dbg_extern_identity_u32(0xDEADBEEF) }, 0xDEADBEEF); @@ -12,14 +11,14 @@ fn main() { #[link(name = "rust_test_helpers", kind = "static")] extern { - #[no_output] + #[empty_attr] //~^ ERROR macro invocations in `extern {}` blocks are experimental fn some_definitely_unknown_symbol_which_should_be_removed(); - #[nop_attr] + #[identity_attr] //~^ ERROR macro invocations in `extern {}` blocks are experimental fn rust_get_test_int() -> isize; - emit_input!(fn rust_dbg_extern_identity_u32(arg: u32) -> u32;); + identity!(fn rust_dbg_extern_identity_u32(arg: u32) -> u32;); //~^ ERROR macro invocations in `extern {}` blocks are experimental } diff --git a/src/test/ui/proc-macro/macros-in-extern.stderr b/src/test/ui/proc-macro/macros-in-extern.stderr index 61571650f2f0..592c91553aa8 100644 --- a/src/test/ui/proc-macro/macros-in-extern.stderr +++ b/src/test/ui/proc-macro/macros-in-extern.stderr @@ -1,26 +1,26 @@ error[E0658]: macro invocations in `extern {}` blocks are experimental - --> $DIR/macros-in-extern.rs:15:5 + --> $DIR/macros-in-extern.rs:14:5 | -LL | #[no_output] - | ^^^^^^^^^^^^ +LL | #[empty_attr] + | ^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/49476 = help: add #![feature(macros_in_extern)] to the crate attributes to enable error[E0658]: macro invocations in `extern {}` blocks are experimental - --> $DIR/macros-in-extern.rs:19:5 + --> $DIR/macros-in-extern.rs:18:5 | -LL | #[nop_attr] - | ^^^^^^^^^^^ +LL | #[identity_attr] + | ^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/49476 = help: add #![feature(macros_in_extern)] to the crate attributes to enable error[E0658]: macro invocations in `extern {}` blocks are experimental - --> $DIR/macros-in-extern.rs:23:5 + --> $DIR/macros-in-extern.rs:22:5 | -LL | emit_input!(fn rust_dbg_extern_identity_u32(arg: u32) -> u32;); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | identity!(fn rust_dbg_extern_identity_u32(arg: u32) -> u32;); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/49476 = help: add #![feature(macros_in_extern)] to the crate attributes to enable diff --git a/src/test/ui/proc-macro/nested-item-spans.rs b/src/test/ui/proc-macro/nested-item-spans.rs index e365b74b3be8..63da170d0bbb 100644 --- a/src/test/ui/proc-macro/nested-item-spans.rs +++ b/src/test/ui/proc-macro/nested-item-spans.rs @@ -1,10 +1,9 @@ -// aux-build:nested-item-spans.rs +// aux-build:test-macros.rs -extern crate nested_item_spans; +#[macro_use] +extern crate test_macros; -use nested_item_spans::foo; - -#[foo] +#[recollect_attr] fn another() { fn bar() { let x: u32 = "x"; //~ ERROR: mismatched types @@ -14,7 +13,7 @@ fn another() { } fn main() { - #[foo] + #[recollect_attr] fn bar() { let x: u32 = "x"; //~ ERROR: mismatched types } diff --git a/src/test/ui/proc-macro/nested-item-spans.stderr b/src/test/ui/proc-macro/nested-item-spans.stderr index 011a91d44629..bef80311f38e 100644 --- a/src/test/ui/proc-macro/nested-item-spans.stderr +++ b/src/test/ui/proc-macro/nested-item-spans.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/nested-item-spans.rs:10:22 + --> $DIR/nested-item-spans.rs:9:22 | LL | let x: u32 = "x"; | ^^^ expected u32, found reference @@ -8,7 +8,7 @@ LL | let x: u32 = "x"; found type `&'static str` error[E0308]: mismatched types - --> $DIR/nested-item-spans.rs:19:22 + --> $DIR/nested-item-spans.rs:18:22 | LL | let x: u32 = "x"; | ^^^ expected u32, found reference diff --git a/src/test/ui/proc-macro/no-macro-use-attr.rs b/src/test/ui/proc-macro/no-macro-use-attr.rs index 62a501ded100..15ab431fe754 100644 --- a/src/test/ui/proc-macro/no-macro-use-attr.rs +++ b/src/test/ui/proc-macro/no-macro-use-attr.rs @@ -1,9 +1,9 @@ -// aux-build:derive-a.rs +// aux-build:test-macros.rs #![feature(rustc_attrs)] #![warn(unused_extern_crates)] -extern crate derive_a; +extern crate test_macros; //~^ WARN unused extern crate #[rustc_error] diff --git a/src/test/ui/proc-macro/no-macro-use-attr.stderr b/src/test/ui/proc-macro/no-macro-use-attr.stderr index 4b2fce7f6e4c..87487bcc7d66 100644 --- a/src/test/ui/proc-macro/no-macro-use-attr.stderr +++ b/src/test/ui/proc-macro/no-macro-use-attr.stderr @@ -1,8 +1,8 @@ warning: unused extern crate --> $DIR/no-macro-use-attr.rs:6:1 | -LL | extern crate derive_a; - | ^^^^^^^^^^^^^^^^^^^^^^ help: remove it +LL | extern crate test_macros; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove it | note: lint level defined here --> $DIR/no-macro-use-attr.rs:4:9 diff --git a/src/test/ui/proc-macro/proc-macro-gates.rs b/src/test/ui/proc-macro/proc-macro-gates.rs index af6bfa08aaa9..678dc83b753b 100644 --- a/src/test/ui/proc-macro/proc-macro-gates.rs +++ b/src/test/ui/proc-macro/proc-macro-gates.rs @@ -1,61 +1,62 @@ -// aux-build:proc-macro-gates.rs +// aux-build:test-macros.rs // gate-test-proc_macro_hygiene #![feature(stmt_expr_attributes)] -extern crate proc_macro_gates as foo; - -use foo::*; +#[macro_use] +extern crate test_macros; fn _test_inner() { - #![a] //~ ERROR: non-builtin inner attributes are unstable + #![empty_attr] //~ ERROR: non-builtin inner attributes are unstable } -#[a] //~ ERROR: custom attributes cannot be applied to modules +#[empty_attr] //~ ERROR: custom attributes cannot be applied to modules mod _test2 {} mod _test2_inner { - #![a] //~ ERROR: custom attributes cannot be applied to modules + #![empty_attr] //~ ERROR: custom attributes cannot be applied to modules //~| ERROR: non-builtin inner attributes are unstable } -#[a = "y"] //~ ERROR: must only be followed by a delimiter token +#[empty_attr = "y"] //~ ERROR: must only be followed by a delimiter token fn _test3() {} fn attrs() { // Statement, item - #[a] // OK + #[empty_attr] // OK struct S; // Statement, macro - #[a] //~ ERROR: custom attributes cannot be applied to statements + #[empty_attr] //~ ERROR: custom attributes cannot be applied to statements println!(); // Statement, semi - #[a] //~ ERROR: custom attributes cannot be applied to statements + #[empty_attr] //~ ERROR: custom attributes cannot be applied to statements S; // Statement, local - #[a] //~ ERROR: custom attributes cannot be applied to statements + #[empty_attr] //~ ERROR: custom attributes cannot be applied to statements let _x = 2; // Expr - let _x = #[a] 2; //~ ERROR: custom attributes cannot be applied to expressions + let _x = #[identity_attr] 2; //~ ERROR: custom attributes cannot be applied to expressions // Opt expr - let _x = [#[a] 2]; //~ ERROR: custom attributes cannot be applied to expressions + let _x = [#[identity_attr] 2]; //~ ERROR: custom attributes cannot be applied to expressions // Expr macro - let _x = #[a] println!(); //~ ERROR: custom attributes cannot be applied to expressions + let _x = #[identity_attr] println!(); + //~^ ERROR: custom attributes cannot be applied to expressions } fn main() { - let _x: m!(u32) = 3; //~ ERROR: procedural macros cannot be expanded to types - if let m!(Some(_x)) = Some(3) {} //~ ERROR: procedural macros cannot be expanded to patterns + let _x: identity!(u32) = 3; //~ ERROR: procedural macros cannot be expanded to types + if let identity!(Some(_x)) = Some(3) {} + //~^ ERROR: procedural macros cannot be expanded to patterns - m!(struct S;); //~ ERROR: procedural macros cannot be expanded to statements - m!(let _x = 3;); //~ ERROR: procedural macros cannot be expanded to statements + empty!(struct S;); //~ ERROR: procedural macros cannot be expanded to statements + empty!(let _x = 3;); //~ ERROR: procedural macros cannot be expanded to statements - let _x = m!(3); //~ ERROR: procedural macros cannot be expanded to expressions - let _x = [m!(3)]; //~ ERROR: procedural macros cannot be expanded to expressions + let _x = identity!(3); //~ ERROR: procedural macros cannot be expanded to expressions + let _x = [empty!(3)]; //~ ERROR: procedural macros cannot be expanded to expressions } diff --git a/src/test/ui/proc-macro/proc-macro-gates.stderr b/src/test/ui/proc-macro/proc-macro-gates.stderr index 1bb864b52ea7..f53ad222a036 100644 --- a/src/test/ui/proc-macro/proc-macro-gates.stderr +++ b/src/test/ui/proc-macro/proc-macro-gates.stderr @@ -1,95 +1,95 @@ error[E0658]: non-builtin inner attributes are unstable - --> $DIR/proc-macro-gates.rs:11:5 + --> $DIR/proc-macro-gates.rs:10:5 | -LL | #![a] - | ^^^^^ +LL | #![empty_attr] + | ^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/54726 = help: add #![feature(custom_inner_attributes)] to the crate attributes to enable error[E0658]: non-builtin inner attributes are unstable - --> $DIR/proc-macro-gates.rs:18:5 + --> $DIR/proc-macro-gates.rs:17:5 | -LL | #![a] - | ^^^^^ +LL | #![empty_attr] + | ^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/54726 = help: add #![feature(custom_inner_attributes)] to the crate attributes to enable error[E0658]: custom attributes cannot be applied to modules - --> $DIR/proc-macro-gates.rs:14:1 + --> $DIR/proc-macro-gates.rs:13:1 | -LL | #[a] - | ^^^^ +LL | #[empty_attr] + | ^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/54727 = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable error[E0658]: custom attributes cannot be applied to modules - --> $DIR/proc-macro-gates.rs:18:5 + --> $DIR/proc-macro-gates.rs:17:5 | -LL | #![a] - | ^^^^^ +LL | #![empty_attr] + | ^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/54727 = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable error: custom attribute invocations must be of the form #[foo] or #[foo(..)], the macro name must only be followed by a delimiter token - --> $DIR/proc-macro-gates.rs:22:1 + --> $DIR/proc-macro-gates.rs:21:1 | -LL | #[a = "y"] - | ^^^^^^^^^^ +LL | #[empty_attr = "y"] + | ^^^^^^^^^^^^^^^^^^^ error[E0658]: custom attributes cannot be applied to statements - --> $DIR/proc-macro-gates.rs:31:5 + --> $DIR/proc-macro-gates.rs:30:5 | -LL | #[a] - | ^^^^ +LL | #[empty_attr] + | ^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/54727 = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable error[E0658]: custom attributes cannot be applied to statements - --> $DIR/proc-macro-gates.rs:35:5 + --> $DIR/proc-macro-gates.rs:34:5 | -LL | #[a] - | ^^^^ +LL | #[empty_attr] + | ^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/54727 = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable error[E0658]: custom attributes cannot be applied to statements - --> $DIR/proc-macro-gates.rs:39:5 + --> $DIR/proc-macro-gates.rs:38:5 | -LL | #[a] - | ^^^^ +LL | #[empty_attr] + | ^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/54727 = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable error[E0658]: custom attributes cannot be applied to expressions - --> $DIR/proc-macro-gates.rs:43:14 + --> $DIR/proc-macro-gates.rs:42:14 | -LL | let _x = #[a] 2; - | ^^^^ +LL | let _x = #[identity_attr] 2; + | ^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/54727 = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable error[E0658]: custom attributes cannot be applied to expressions - --> $DIR/proc-macro-gates.rs:46:15 + --> $DIR/proc-macro-gates.rs:45:15 | -LL | let _x = [#[a] 2]; - | ^^^^ +LL | let _x = [#[identity_attr] 2]; + | ^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/54727 = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable error[E0658]: custom attributes cannot be applied to expressions - --> $DIR/proc-macro-gates.rs:49:14 + --> $DIR/proc-macro-gates.rs:48:14 | -LL | let _x = #[a] println!(); - | ^^^^ +LL | let _x = #[identity_attr] println!(); + | ^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/54727 = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable @@ -97,8 +97,8 @@ LL | let _x = #[a] println!(); error[E0658]: procedural macros cannot be expanded to types --> $DIR/proc-macro-gates.rs:53:13 | -LL | let _x: m!(u32) = 3; - | ^^^^^^^ +LL | let _x: identity!(u32) = 3; + | ^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/54727 = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable @@ -106,17 +106,8 @@ LL | let _x: m!(u32) = 3; error[E0658]: procedural macros cannot be expanded to patterns --> $DIR/proc-macro-gates.rs:54:12 | -LL | if let m!(Some(_x)) = Some(3) {} - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/54727 - = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable - -error[E0658]: procedural macros cannot be expanded to statements - --> $DIR/proc-macro-gates.rs:56:5 - | -LL | m!(struct S;); - | ^^^^^^^^^^^^^^ +LL | if let identity!(Some(_x)) = Some(3) {} + | ^^^^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/54727 = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable @@ -124,26 +115,35 @@ LL | m!(struct S;); error[E0658]: procedural macros cannot be expanded to statements --> $DIR/proc-macro-gates.rs:57:5 | -LL | m!(let _x = 3;); - | ^^^^^^^^^^^^^^^^ +LL | empty!(struct S;); + | ^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/54727 + = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable + +error[E0658]: procedural macros cannot be expanded to statements + --> $DIR/proc-macro-gates.rs:58:5 + | +LL | empty!(let _x = 3;); + | ^^^^^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/54727 = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable error[E0658]: procedural macros cannot be expanded to expressions - --> $DIR/proc-macro-gates.rs:59:14 + --> $DIR/proc-macro-gates.rs:60:14 | -LL | let _x = m!(3); - | ^^^^^ +LL | let _x = identity!(3); + | ^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/54727 = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable error[E0658]: procedural macros cannot be expanded to expressions - --> $DIR/proc-macro-gates.rs:60:15 + --> $DIR/proc-macro-gates.rs:61:15 | -LL | let _x = [m!(3)]; - | ^^^^^ +LL | let _x = [empty!(3)]; + | ^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/54727 = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable diff --git a/src/test/ui/proc-macro/proc-macro-gates2.rs b/src/test/ui/proc-macro/proc-macro-gates2.rs index 46b543a397cc..35d7fc8042a3 100644 --- a/src/test/ui/proc-macro/proc-macro-gates2.rs +++ b/src/test/ui/proc-macro/proc-macro-gates2.rs @@ -1,21 +1,20 @@ -// aux-build:proc-macro-gates.rs +// aux-build:test-macros.rs #![feature(stmt_expr_attributes)] -extern crate proc_macro_gates as foo; - -use foo::*; +#[macro_use] +extern crate test_macros; // NB. these errors aren't the best errors right now, but they're definitely // intended to be errors. Somehow using a custom attribute in these positions // should either require a feature gate or not be allowed on stable. -fn _test6<#[a] T>() {} +fn _test6<#[empty_attr] T>() {} //~^ ERROR: unknown to the compiler fn _test7() { match 1 { - #[a] //~ ERROR: unknown to the compiler + #[empty_attr] //~ ERROR: unknown to the compiler 0 => {} _ => {} } diff --git a/src/test/ui/proc-macro/proc-macro-gates2.stderr b/src/test/ui/proc-macro/proc-macro-gates2.stderr index 0e8236f460f8..8eeca99ab398 100644 --- a/src/test/ui/proc-macro/proc-macro-gates2.stderr +++ b/src/test/ui/proc-macro/proc-macro-gates2.stderr @@ -1,17 +1,17 @@ -error[E0658]: The attribute `a` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/proc-macro-gates2.rs:13:11 +error[E0658]: The attribute `empty_attr` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-gates2.rs:12:11 | -LL | fn _test6<#[a] T>() {} - | ^^^^ +LL | fn _test6<#[empty_attr] T>() {} + | ^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/29642 = help: add #![feature(custom_attribute)] to the crate attributes to enable -error[E0658]: The attribute `a` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/proc-macro-gates2.rs:18:9 +error[E0658]: The attribute `empty_attr` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/proc-macro-gates2.rs:17:9 | -LL | #[a] - | ^^^^ +LL | #[empty_attr] + | ^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/29642 = help: add #![feature(custom_attribute)] to the crate attributes to enable diff --git a/src/test/ui/proc-macro/resolve-error.rs b/src/test/ui/proc-macro/resolve-error.rs index bb242f302496..82607136f0b6 100644 --- a/src/test/ui/proc-macro/resolve-error.rs +++ b/src/test/ui/proc-macro/resolve-error.rs @@ -1,7 +1,6 @@ // aux-build:derive-foo.rs // aux-build:derive-clona.rs -// aux-build:attr_proc_macro.rs -// aux-build:bang_proc_macro.rs +// aux-build:test-macros.rs #![feature(custom_attribute)] @@ -9,11 +8,10 @@ extern crate derive_foo; #[macro_use] extern crate derive_clona; -extern crate attr_proc_macro; -extern crate bang_proc_macro; +extern crate test_macros; -use attr_proc_macro::attr_proc_macro; -use bang_proc_macro::bang_proc_macro; +use test_macros::empty as bang_proc_macro; +use test_macros::empty_attr as attr_proc_macro; macro_rules! FooWithLongNam { () => {} diff --git a/src/test/ui/proc-macro/resolve-error.stderr b/src/test/ui/proc-macro/resolve-error.stderr index cf7de578c7d4..705ef6006a04 100644 --- a/src/test/ui/proc-macro/resolve-error.stderr +++ b/src/test/ui/proc-macro/resolve-error.stderr @@ -1,47 +1,47 @@ error: cannot find derive macro `FooWithLongNan` in this scope - --> $DIR/resolve-error.rs:26:10 + --> $DIR/resolve-error.rs:24:10 | LL | #[derive(FooWithLongNan)] | ^^^^^^^^^^^^^^ help: try: `FooWithLongName` error: cannot find derive macro `Dlone` in this scope - --> $DIR/resolve-error.rs:36:10 + --> $DIR/resolve-error.rs:34:10 | LL | #[derive(Dlone)] | ^^^^^ help: try: `Clone` error: cannot find derive macro `Dlona` in this scope - --> $DIR/resolve-error.rs:40:10 + --> $DIR/resolve-error.rs:38:10 | LL | #[derive(Dlona)] | ^^^^^ help: try: `Clona` error: cannot find derive macro `attr_proc_macra` in this scope - --> $DIR/resolve-error.rs:44:10 + --> $DIR/resolve-error.rs:42:10 | LL | #[derive(attr_proc_macra)] | ^^^^^^^^^^^^^^^ error: cannot find macro `FooWithLongNama!` in this scope - --> $DIR/resolve-error.rs:49:5 + --> $DIR/resolve-error.rs:47:5 | LL | FooWithLongNama!(); | ^^^^^^^^^^^^^^^ help: you could try the macro: `FooWithLongNam` error: cannot find macro `attr_proc_macra!` in this scope - --> $DIR/resolve-error.rs:52:5 + --> $DIR/resolve-error.rs:50:5 | LL | attr_proc_macra!(); | ^^^^^^^^^^^^^^^ help: you could try the macro: `attr_proc_mac` error: cannot find macro `Dlona!` in this scope - --> $DIR/resolve-error.rs:55:5 + --> $DIR/resolve-error.rs:53:5 | LL | Dlona!(); | ^^^^^ error: cannot find macro `bang_proc_macrp!` in this scope - --> $DIR/resolve-error.rs:58:5 + --> $DIR/resolve-error.rs:56:5 | LL | bang_proc_macrp!(); | ^^^^^^^^^^^^^^^ help: you could try the macro: `bang_proc_macro` diff --git a/src/test/ui/proc-macro/shadow.rs b/src/test/ui/proc-macro/shadow.rs index 9c49bae28a3b..61959594c798 100644 --- a/src/test/ui/proc-macro/shadow.rs +++ b/src/test/ui/proc-macro/shadow.rs @@ -1,8 +1,8 @@ -// aux-build:derive-a.rs +// aux-build:test-macros.rs #[macro_use] -extern crate derive_a; +extern crate test_macros; #[macro_use] -extern crate derive_a; //~ ERROR the name `derive_a` is defined multiple times +extern crate test_macros; //~ ERROR the name `test_macros` is defined multiple times fn main() {} diff --git a/src/test/ui/proc-macro/shadow.stderr b/src/test/ui/proc-macro/shadow.stderr index 08057e163496..e7d95cc83581 100644 --- a/src/test/ui/proc-macro/shadow.stderr +++ b/src/test/ui/proc-macro/shadow.stderr @@ -1,13 +1,13 @@ -error[E0259]: the name `derive_a` is defined multiple times +error[E0259]: the name `test_macros` is defined multiple times --> $DIR/shadow.rs:6:1 | -LL | extern crate derive_a; - | ---------------------- previous import of the extern crate `derive_a` here +LL | extern crate test_macros; + | ------------------------- previous import of the extern crate `test_macros` here LL | #[macro_use] -LL | extern crate derive_a; - | ^^^^^^^^^^^^^^^^^^^^^^ `derive_a` reimported here +LL | extern crate test_macros; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `test_macros` reimported here | - = note: `derive_a` must be defined only once in the type namespace of this module + = note: `test_macros` must be defined only once in the type namespace of this module error: aborting due to previous error diff --git a/src/test/ui/proc-macro/span-preservation.rs b/src/test/ui/proc-macro/span-preservation.rs index 64f675ecc1c4..0a82d28e9e54 100644 --- a/src/test/ui/proc-macro/span-preservation.rs +++ b/src/test/ui/proc-macro/span-preservation.rs @@ -1,19 +1,18 @@ //~ ERROR mismatched types -// aux-build:span-preservation.rs +// aux-build:test-macros.rs // For each of these, we should get the appropriate type mismatch error message, // and the function should be echoed. -extern crate span_preservation as foo; +#[macro_use] +extern crate test_macros; -use foo::foo; - -#[foo] +#[recollect_attr] fn a() { let x: usize = "hello";;;;; //~ ERROR mismatched types } -#[foo] +#[recollect_attr] fn b(x: Option) -> usize { match x { Some(x) => { return x }, //~ ERROR mismatched types @@ -21,7 +20,7 @@ fn b(x: Option) -> usize { } } -#[foo] +#[recollect_attr] fn c() { struct Foo { a: usize @@ -39,12 +38,12 @@ fn c() { // FIXME: This doesn't work at the moment. See the one below. The pretty-printer // injects a "C" between `extern` and `fn` which causes a "probably_eq" // `TokenStream` mismatch. The lack of `"C"` should be preserved in the AST. -#[foo] +#[recollect_attr] extern fn bar() { 0 } -#[foo] +#[recollect_attr] extern "C" fn baz() { 0 //~ ERROR mismatched types } diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr index 1cc7706ce3a4..cf03deee7e44 100644 --- a/src/test/ui/proc-macro/span-preservation.stderr +++ b/src/test/ui/proc-macro/span-preservation.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types found type `{integer}` error[E0308]: mismatched types - --> $DIR/span-preservation.rs:13:20 + --> $DIR/span-preservation.rs:12:20 | LL | let x: usize = "hello";;;;; | ^^^^^^^ expected usize, found reference @@ -13,7 +13,7 @@ LL | let x: usize = "hello";;;;; found type `&'static str` error[E0308]: mismatched types - --> $DIR/span-preservation.rs:19:29 + --> $DIR/span-preservation.rs:18:29 | LL | fn b(x: Option) -> usize { | ----- expected `usize` because of return type @@ -22,13 +22,13 @@ LL | Some(x) => { return x }, | ^ expected usize, found isize error[E0308]: mismatched types - --> $DIR/span-preservation.rs:35:22 + --> $DIR/span-preservation.rs:34:22 | LL | let x = Foo { a: 10isize }; | ^^^^^^^ expected usize, found isize error[E0560]: struct `c::Foo` has no field named `b` - --> $DIR/span-preservation.rs:36:26 + --> $DIR/span-preservation.rs:35:26 | LL | let y = Foo { a: 10, b: 10isize }; | ^ `c::Foo` does not have this field @@ -36,7 +36,7 @@ LL | let y = Foo { a: 10, b: 10isize }; = note: available fields are: `a` error[E0308]: mismatched types - --> $DIR/span-preservation.rs:49:5 + --> $DIR/span-preservation.rs:48:5 | LL | extern "C" fn baz() { | - possibly return type missing here? From e641fb47c472e767074a773c6a88cbc9873e63e0 Mon Sep 17 00:00:00 2001 From: Brent Kerby Date: Tue, 21 May 2019 21:52:21 -0600 Subject: [PATCH 0254/3207] Simplify RefCell minimum_spanning_tree example --- src/libcore/cell.rs | 48 ++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index fcfd80d92660..9672cf4ffed3 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -67,16 +67,26 @@ //! mutability: //! //! ``` +//! use std::cell::{RefCell, RefMut}; //! use std::collections::HashMap; -//! use std::cell::RefCell; //! use std::rc::Rc; //! //! fn main() { //! let shared_map: Rc> = Rc::new(RefCell::new(HashMap::new())); -//! shared_map.borrow_mut().insert("africa", 92388); -//! shared_map.borrow_mut().insert("kyoto", 11837); -//! shared_map.borrow_mut().insert("piccadilly", 11826); -//! shared_map.borrow_mut().insert("marbles", 38); +//! // Create a new block to limit the scope of the dynamic borrow +//! { +//! let mut map: RefMut<_> = shared_map.borrow_mut(); +//! map.insert("africa", 92388); +//! map.insert("kyoto", 11837); +//! map.insert("piccadilly", 11826); +//! map.insert("marbles", 38); +//! } +//! +//! // Note that if we had not let the previous borrow of the cache fall out +//! // of scope then the subsequent borrow would cause a dynamic thread panic. +//! // This is the major hazard of using `RefCell`. +//! let total: i32 = shared_map.borrow().values().sum(); +//! println!("{}", total); //! } //! ``` //! @@ -102,27 +112,15 @@ //! //! impl Graph { //! fn minimum_spanning_tree(&self) -> Vec<(i32, i32)> { -//! // Create a new scope to contain the lifetime of the -//! // dynamic borrow -//! { -//! // Take a reference to the inside of cache cell -//! let mut cache = self.span_tree_cache.borrow_mut(); -//! if cache.is_some() { -//! return cache.as_ref().unwrap().clone(); -//! } -//! -//! let span_tree = self.calc_span_tree(); -//! *cache = Some(span_tree); -//! } -//! -//! // Recursive call to return the just-cached value. -//! // Note that if we had not let the previous borrow -//! // of the cache fall out of scope then the subsequent -//! // recursive borrow would cause a dynamic thread panic. -//! // This is the major hazard of using `RefCell`. -//! self.minimum_spanning_tree() +//! self.span_tree_cache.borrow_mut() +//! .get_or_insert_with(|| self.calc_span_tree()) +//! .clone() +//! } +//! +//! fn calc_span_tree(&self) -> Vec<(i32, i32)> { +//! // Expensive computation goes here +//! vec![] //! } -//! # fn calc_span_tree(&self) -> Vec<(i32, i32)> { vec![] } //! } //! ``` //! From f47b87279c2d67c7822ad2c36480614e033d6277 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 22 May 2019 01:17:16 +0200 Subject: [PATCH 0255/3207] Migrate from recursion to iterate on qualify consts visitor impl --- src/librustc_mir/transform/qualify_consts.rs | 100 ++++++++++--------- 1 file changed, 51 insertions(+), 49 deletions(-) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 579f75ba5165..c9800b1825cd 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -930,58 +930,60 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { context: PlaceContext, location: Location) { debug!("visit_place: place={:?} context={:?} location={:?}", place, context, location); - self.super_place(place, context, location); - match *place { - Place::Base(PlaceBase::Local(_)) => {} - Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) => { - unreachable!() - } - Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })) => { - if self.tcx - .get_attrs(def_id) - .iter() - .any(|attr| attr.check_name(sym::thread_local)) { + place.iterate(|place_base, place_projections| { + match place_base { + PlaceBase::Local(_) => {} + PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. }) => { + unreachable!() + } + PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. }) => { + if self.tcx + .get_attrs(*def_id) + .iter() + .any(|attr| attr.check_name(sym::thread_local)) { + if self.mode != Mode::Fn { + span_err!(self.tcx.sess, self.span, E0625, + "thread-local statics cannot be \ + accessed at compile-time"); + } + return; + } + + // Only allow statics (not consts) to refer to other statics. + if self.mode == Mode::Static || self.mode == Mode::StaticMut { + if self.mode == Mode::Static && context.is_mutating_use() { + // this is not strictly necessary as miri will also bail out + // For interior mutability we can't really catch this statically as that + // goes through raw pointers and intermediate temporaries, so miri has + // to catch this anyway + self.tcx.sess.span_err( + self.span, + "cannot mutate statics in the initializer of another static", + ); + } + return; + } + unleash_miri!(self); + if self.mode != Mode::Fn { - span_err!(self.tcx.sess, self.span, E0625, - "thread-local statics cannot be \ - accessed at compile-time"); + let mut err = struct_span_err!(self.tcx.sess, self.span, E0013, + "{}s cannot refer to statics, use \ + a constant instead", self.mode); + if self.tcx.sess.teach(&err.get_code().unwrap()) { + err.note( + "Static and const variables can refer to other const variables. \ + But a const variable cannot refer to a static variable." + ); + err.help( + "To fix this, the value can be extracted as a const and then used." + ); + } + err.emit() } - return; - } - - // Only allow statics (not consts) to refer to other statics. - if self.mode == Mode::Static || self.mode == Mode::StaticMut { - if self.mode == Mode::Static && context.is_mutating_use() { - // this is not strictly necessary as miri will also bail out - // For interior mutability we can't really catch this statically as that - // goes through raw pointers and intermediate temporaries, so miri has - // to catch this anyway - self.tcx.sess.span_err( - self.span, - "cannot mutate statics in the initializer of another static", - ); - } - return; - } - unleash_miri!(self); - - if self.mode != Mode::Fn { - let mut err = struct_span_err!(self.tcx.sess, self.span, E0013, - "{}s cannot refer to statics, use \ - a constant instead", self.mode); - if self.tcx.sess.teach(&err.get_code().unwrap()) { - err.note( - "Static and const variables can refer to other const variables. But a \ - const variable cannot refer to a static variable." - ); - err.help( - "To fix this, the value can be extracted as a const and then used." - ); - } - err.emit() } } - Place::Projection(ref proj) => { + + for proj in place_projections { match proj.elem { ProjectionElem::Deref => { if context.is_mutating_use() { @@ -1041,7 +1043,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { } } } - } + }); } fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) { From c99090761c71b7c1c59ce889df5f1b4f78376538 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 Apr 2019 10:22:02 +0300 Subject: [PATCH 0256/3207] rustc_metadata: parametrize schema::CrateRoot by 'tcx. --- src/librustc_metadata/creader.rs | 6 +++--- src/librustc_metadata/cstore.rs | 6 +++++- src/librustc_metadata/cstore_impl.rs | 7 +------ src/librustc_metadata/decoder.rs | 11 ++++------- src/librustc_metadata/encoder.rs | 17 ++++++----------- src/librustc_metadata/index.rs | 17 ++++++++++------- src/librustc_metadata/index_builder.rs | 4 ++-- src/librustc_metadata/lib.rs | 1 + src/librustc_metadata/schema.rs | 13 ++++--------- 9 files changed, 36 insertions(+), 46 deletions(-) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 3e00ba3c6200..991bebc647d0 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -162,7 +162,7 @@ impl<'a> CrateLoader<'a> { fn verify_no_symbol_conflicts(&self, span: Span, - root: &CrateRoot) { + root: &CrateRoot<'_>) { // Check for (potential) conflicts with the local crate if self.local_crate_name == root.name && self.sess.local_crate_disambiguator() == root.disambiguator { @@ -476,7 +476,7 @@ impl<'a> CrateLoader<'a> { // Go through the crate metadata and load any crates that it references fn resolve_crate_deps(&mut self, root: &Option, - crate_root: &CrateRoot, + crate_root: &CrateRoot<'_>, metadata: &MetadataBlob, krate: CrateNum, span: Span, @@ -582,7 +582,7 @@ impl<'a> CrateLoader<'a> { /// implemented as dynamic libraries, but we have a possible future where /// custom derive (and other macro-1.1 style features) are implemented via /// executables and custom IPC. - fn load_derive_macros(&mut self, root: &CrateRoot, dylib: Option, span: Span) + fn load_derive_macros(&mut self, root: &CrateRoot<'_>, dylib: Option, span: Span) -> Vec<(ast::Name, Lrc)> { use std::{env, mem}; use crate::dynamic_lib::DynamicLibrary; diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 22a13f37722b..5d8fabc7e69a 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -64,7 +64,11 @@ pub struct CrateMetadata { /// Used for decoding interpret::AllocIds in a cached & thread-safe manner. pub alloc_decoding_state: AllocDecodingState, - pub root: schema::CrateRoot, + // NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this + // lifetime is only used behind `Lazy` / `LazySeq`, and therefore + // acts like an universal (`for<'tcx>`), that is paired up with + // whichever `TyCtxt` is being used to decode those values. + pub root: schema::CrateRoot<'static>, /// For each public item in this crate, we encode a key. When the /// crate is loaded, we read all the keys and put them in this diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 2070a38b7b85..49f93c4014dc 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -246,12 +246,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, used_crate_source => { Lrc::new(cdata.source.clone()) } - exported_symbols => { - let cnum = cdata.cnum; - assert!(cnum != LOCAL_CRATE); - - Arc::new(cdata.exported_symbols(tcx)) - } + exported_symbols => { Arc::new(cdata.exported_symbols(tcx)) } } pub fn provide<'tcx>(providers: &mut Providers<'tcx>) { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index d2ba82b5a1c9..cf21e9bd9201 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -365,7 +365,7 @@ for DecodeContext<'a, 'tcx> { implement_ty_decoder!( DecodeContext<'a, 'tcx> ); -impl<'a, 'tcx> MetadataBlob { +impl<'tcx> MetadataBlob { pub fn is_compatible(&self) -> bool { self.raw_bytes().starts_with(METADATA_HEADER) } @@ -374,7 +374,7 @@ impl<'a, 'tcx> MetadataBlob { Lazy::with_position(METADATA_HEADER.len() + 4).decode(self) } - pub fn get_root(&self) -> CrateRoot { + pub fn get_root(&self) -> CrateRoot<'tcx> { let slice = self.raw_bytes(); let offset = METADATA_HEADER.len(); let pos = (((slice[offset + 0] as u32) << 24) | ((slice[offset + 1] as u32) << 16) | @@ -444,7 +444,7 @@ impl<'tcx> EntryKind<'tcx> { /// |- proc macro #0 (DefIndex 1:N) /// |- proc macro #1 (DefIndex 1:N+1) /// \- ... -crate fn proc_macro_def_path_table(crate_root: &CrateRoot, +crate fn proc_macro_def_path_table(crate_root: &CrateRoot<'_>, proc_macros: &[(ast::Name, Lrc)]) -> DefPathTable { @@ -1126,10 +1126,7 @@ impl<'a, 'tcx> CrateMetadata { // link those in so we skip those crates. vec![] } else { - let lazy_seq: LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)> = - LazySeq::with_position_and_length(self.root.exported_symbols.position, - self.root.exported_symbols.len); - lazy_seq.decode((self, tcx)).collect() + self.root.exported_symbols.decode((self, tcx)).collect() } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 7f0993e799f5..4fda3e769e01 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -309,7 +309,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { op(&mut IsolatedEncoder::new(self), data) } - fn encode_info_for_items(&mut self) -> Index { + fn encode_info_for_items(&mut self) -> Index<'tcx> { let krate = self.tcx.hir().krate(); let mut index = IndexBuilder::new(self); let vis = Spanned { span: syntax_pos::DUMMY_SP, node: hir::VisibilityKind::Public }; @@ -371,7 +371,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.lazy_seq_ref(adapted.iter().map(|rc| &**rc)) } - fn encode_crate_root(&mut self) -> Lazy { + fn encode_crate_root(&mut self) -> Lazy> { let mut i = self.position(); let crate_deps = self.tracked(IsolatedEncoder::encode_crate_deps, ()); @@ -1595,13 +1595,13 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { // symbol associated with them (they weren't translated) or if they're an FFI // definition (as that's not defined in this crate). fn encode_exported_symbols(&mut self, - exported_symbols: &[(ExportedSymbol<'_>, SymbolExportLevel)]) - -> EncodedExportedSymbols { + exported_symbols: &[(ExportedSymbol<'tcx>, SymbolExportLevel)]) + -> LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)> { // The metadata symbol name is special. It should not show up in // downstream crates. let metadata_symbol_name = SymbolName::new(&metadata_symbol_name(self.tcx)); - let lazy_seq = self.lazy_seq(exported_symbols + self.lazy_seq(exported_symbols .iter() .filter(|&&(ref exported_symbol, _)| { match *exported_symbol { @@ -1611,12 +1611,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { _ => true, } }) - .cloned()); - - EncodedExportedSymbols { - len: lazy_seq.len, - position: lazy_seq.position, - } + .cloned()) } fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq> { diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index 934e871559c7..dd2f59922ef9 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -2,6 +2,7 @@ use crate::schema::*; use rustc::hir::def_id::{DefId, DefIndex}; use rustc_serialize::opaque::Encoder; +use std::marker::PhantomData; use std::u32; use log::debug; @@ -74,23 +75,25 @@ impl FixedSizeEncoding for u32 { /// `u32::MAX`. Whenever an index is visited, we fill in the /// appropriate spot by calling `record_position`. We should never /// visit the same index twice. -pub struct Index { +pub struct Index<'tcx> { positions: Vec, + _marker: PhantomData<&'tcx ()>, } -impl Index { - pub fn new(max_index: usize) -> Index { +impl Index<'tcx> { + pub fn new(max_index: usize) -> Self { Index { positions: vec![0xff; max_index * 4], + _marker: PhantomData, } } - pub fn record(&mut self, def_id: DefId, entry: Lazy>) { + pub fn record(&mut self, def_id: DefId, entry: Lazy>) { assert!(def_id.is_local()); self.record_index(def_id.index, entry); } - pub fn record_index(&mut self, item: DefIndex, entry: Lazy>) { + pub fn record_index(&mut self, item: DefIndex, entry: Lazy>) { assert!(entry.position < (u32::MAX as usize)); let position = entry.position as u32; let array_index = item.index(); @@ -105,7 +108,7 @@ impl Index { position.write_to_bytes_at(positions, array_index) } - pub fn write_index(&self, buf: &mut Encoder) -> LazySeq { + pub fn write_index(&self, buf: &mut Encoder) -> LazySeq { let pos = buf.position(); // First we write the length of the lower range ... @@ -116,7 +119,7 @@ impl Index { } } -impl<'tcx> LazySeq { +impl LazySeq> { /// Given the metadata, extract out the offset of a particular /// DefIndex (if any). #[inline(never)] diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs index e780693a5a92..ee928968cb42 100644 --- a/src/librustc_metadata/index_builder.rs +++ b/src/librustc_metadata/index_builder.rs @@ -60,7 +60,7 @@ use std::ops::{Deref, DerefMut}; /// Builder that can encode new items, adding them into the index. /// Item encoding cannot be nested. pub struct IndexBuilder<'a, 'b: 'a, 'tcx: 'b> { - items: Index, + items: Index<'tcx>, pub ecx: &'a mut EncodeContext<'b, 'tcx>, } @@ -123,7 +123,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { }) } - pub fn into_items(self) -> Index { + pub fn into_items(self) -> Index<'tcx> { self.items } } diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 4f84ca69b7f1..0faadd23f47a 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -2,6 +2,7 @@ #![feature(box_patterns)] #![feature(drain_filter)] +#![feature(in_band_lifetimes)] #![feature(libc)] #![feature(nll)] #![feature(proc_macro_internals)] diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 504c7da7d6b9..b2f6fd65ed44 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -4,6 +4,7 @@ use rustc::hir; use rustc::hir::def::{self, CtorKind}; use rustc::hir::def_id::{DefIndex, DefId, CrateNum}; use rustc::ich::StableHashingContext; +use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary, ForeignModule}; use rustc::middle::lang_items; use rustc::mir; @@ -174,7 +175,7 @@ pub enum LazyState { } #[derive(RustcEncodable, RustcDecodable)] -pub struct CrateRoot { +pub struct CrateRoot<'tcx> { pub name: Symbol, pub triple: TargetTriple, pub extra_filename: String, @@ -199,10 +200,10 @@ pub struct CrateRoot { pub source_map: LazySeq, pub def_path_table: Lazy, pub impls: LazySeq, - pub exported_symbols: EncodedExportedSymbols, + pub exported_symbols: LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)>, pub interpret_alloc_index: LazySeq, - pub index: LazySeq, + pub index: LazySeq>, pub compiler_builtins: bool, pub needs_allocator: bool, @@ -577,9 +578,3 @@ impl_stable_hash_for!(struct GeneratorData<'tcx> { layout }); // Tags used for encoding Spans: pub const TAG_VALID_SPAN: u8 = 0; pub const TAG_INVALID_SPAN: u8 = 1; - -#[derive(RustcEncodable, RustcDecodable)] -pub struct EncodedExportedSymbols { - pub position: usize, - pub len: usize, -} From 7327768a75621df3f4cec4229a0812eceb7c5adb Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 22 May 2019 12:16:48 +0300 Subject: [PATCH 0257/3207] rustc_metadata: rip out unused incremental infrastructure. --- src/librustc_metadata/decoder.rs | 2 +- src/librustc_metadata/encoder.rs | 274 ++++++++++------------ src/librustc_metadata/index_builder.rs | 224 ------------------ src/librustc_metadata/isolated_encoder.rs | 48 ---- src/librustc_metadata/lib.rs | 2 - src/librustc_metadata/schema.rs | 198 +--------------- 6 files changed, 125 insertions(+), 623 deletions(-) delete mode 100644 src/librustc_metadata/index_builder.rs delete mode 100644 src/librustc_metadata/isolated_encoder.rs diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index cf21e9bd9201..a89cfe42eaaf 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -475,7 +475,7 @@ impl<'a, 'tcx> CrateMetadata { fn maybe_entry(&self, item_id: DefIndex) -> Option>> { assert!(!self.is_proc_macro(item_id)); - self.root.index.lookup(self.blob.raw_bytes(), item_id) + self.root.entries_index.lookup(self.blob.raw_bytes(), item_id) } fn entry(&self, item_id: DefIndex) -> Entry<'tcx> { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 4fda3e769e01..6711e54053a1 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1,6 +1,4 @@ use crate::index::Index; -use crate::index_builder::{FromId, IndexBuilder, Untracked}; -use crate::isolated_encoder::IsolatedEncoder; use crate::schema::*; use rustc::middle::cstore::{LinkagePreference, NativeLibrary, @@ -46,6 +44,8 @@ pub struct EncodeContext<'a, 'tcx: 'a> { opaque: opaque::Encoder, pub tcx: TyCtxt<'a, 'tcx, 'tcx>, + entries_index: Index<'tcx>, + lazy_state: LazyState, type_shorthands: FxHashMap, usize>, predicate_shorthands: FxHashMap, usize>, @@ -300,28 +300,34 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }) } - // Encodes something that corresponds to a single DepNode::GlobalMetaData - // and registers the Fingerprint in the `metadata_hashes` map. - pub fn tracked<'x, DATA, R>(&'x mut self, - op: fn(&mut IsolatedEncoder<'x, 'a, 'tcx>, DATA) -> R, - data: DATA) - -> R { - op(&mut IsolatedEncoder::new(self), data) + /// Emit the data for a `DefId` to the metadata. The function to + /// emit the data is `op`, and it will be given `data` as + /// arguments. This `record` function will call `op` to generate + /// the `Entry` (which may point to other encoded information) + /// and will then record the `Lazy` for use in the index. + // FIXME(eddyb) remove this. + pub fn record(&mut self, + id: DefId, + op: impl FnOnce(&mut Self, DATA) -> Entry<'tcx>, + data: DATA) + { + assert!(id.is_local()); + + let entry = op(self, data); + let entry = self.lazy(&entry); + self.entries_index.record(id, entry); } - fn encode_info_for_items(&mut self) -> Index<'tcx> { + fn encode_info_for_items(&mut self) { let krate = self.tcx.hir().krate(); - let mut index = IndexBuilder::new(self); let vis = Spanned { span: syntax_pos::DUMMY_SP, node: hir::VisibilityKind::Public }; - index.record(DefId::local(CRATE_DEF_INDEX), - IsolatedEncoder::encode_info_for_mod, - FromId(hir::CRATE_HIR_ID, (&krate.module, &krate.attrs, &vis))); - let mut visitor = EncodeVisitor { index }; - krate.visit_all_item_likes(&mut visitor.as_deep_visitor()); + self.record(DefId::local(CRATE_DEF_INDEX), + EncodeContext::encode_info_for_mod, + (hir::CRATE_HIR_ID, &krate.module, &krate.attrs, &vis)); + krate.visit_all_item_likes(&mut self.as_deep_visitor()); for macro_def in &krate.exported_macros { - visitor.visit_macro_def(macro_def); + self.visit_macro_def(macro_def); } - visitor.index.into_items() } fn encode_def_path_table(&mut self) -> Lazy { @@ -374,35 +380,27 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_crate_root(&mut self) -> Lazy> { let mut i = self.position(); - let crate_deps = self.tracked(IsolatedEncoder::encode_crate_deps, ()); - let dylib_dependency_formats = self.tracked( - IsolatedEncoder::encode_dylib_dependency_formats, - ()); + let crate_deps = self.encode_crate_deps(); + let dylib_dependency_formats = self.encode_dylib_dependency_formats(); let dep_bytes = self.position() - i; // Encode the lib features. i = self.position(); - let lib_features = self.tracked(IsolatedEncoder::encode_lib_features, ()); + let lib_features = self.encode_lib_features(); let lib_feature_bytes = self.position() - i; // Encode the language items. i = self.position(); - let lang_items = self.tracked(IsolatedEncoder::encode_lang_items, ()); - let lang_items_missing = self.tracked( - IsolatedEncoder::encode_lang_items_missing, - ()); + let lang_items = self.encode_lang_items(); + let lang_items_missing = self.encode_lang_items_missing(); let lang_item_bytes = self.position() - i; // Encode the native libraries used i = self.position(); - let native_libraries = self.tracked( - IsolatedEncoder::encode_native_libraries, - ()); + let native_libraries = self.encode_native_libraries(); let native_lib_bytes = self.position() - i; - let foreign_modules = self.tracked( - IsolatedEncoder::encode_foreign_modules, - ()); + let foreign_modules = self.encode_foreign_modules(); // Encode source_map i = self.position(); @@ -416,22 +414,20 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Encode the def IDs of impls, for coherence checking. i = self.position(); - let impls = self.tracked(IsolatedEncoder::encode_impls, ()); + let impls = self.encode_impls(); let impl_bytes = self.position() - i; // Encode exported symbols info. i = self.position(); let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE); - let exported_symbols = self.tracked( - IsolatedEncoder::encode_exported_symbols, - &exported_symbols); + let exported_symbols = self.encode_exported_symbols(&exported_symbols); let exported_symbols_bytes = self.position() - i; let tcx = self.tcx; // Encode the items. i = self.position(); - let items = self.encode_info_for_items(); + self.encode_info_for_items(); let item_bytes = self.position() - i; // Encode the allocation index @@ -462,10 +458,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.lazy_seq(interpret_alloc_index) }; - // Index the items i = self.position(); - let index = items.write_index(&mut self.opaque); - let index_bytes = self.position() - i; + let entries_index = self.entries_index.write_index(&mut self.opaque); + let entries_index_bytes = self.position() - i; let attrs = tcx.hir().krate_attrs(); let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro); @@ -516,7 +511,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { impls, exported_symbols, interpret_alloc_index, - index, + entries_index, }); let total_bytes = self.position(); @@ -539,7 +534,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { println!(" exp. symbols bytes: {}", exported_symbols_bytes); println!(" def-path table bytes: {}", def_path_table_bytes); println!(" item bytes: {}", item_bytes); - println!(" index bytes: {}", index_bytes); + println!(" entries index bytes: {}", entries_index_bytes); println!(" zero bytes: {}", zero_bytes); println!(" total bytes: {}", total_bytes); } @@ -548,40 +543,29 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } -// These are methods for encoding various things. They are meant to be used with -// IndexBuilder::record() and EncodeContext::tracked(). They actually -// would not have to be methods of IsolatedEncoder (free standing functions -// taking IsolatedEncoder as first argument would be just fine) but by making -// them methods we don't have to repeat the lengthy `<'a, 'b: 'a, 'tcx: 'b>` -// clause again and again. -impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { +impl EncodeContext<'_, 'tcx> { fn encode_variances_of(&mut self, def_id: DefId) -> LazySeq { - debug!("IsolatedEncoder::encode_variances_of({:?})", def_id); + debug!("EncodeContext::encode_variances_of({:?})", def_id); let tcx = self.tcx; - self.lazy_seq_from_slice(&tcx.variances_of(def_id)) + self.lazy_seq_ref(&tcx.variances_of(def_id)[..]) } fn encode_item_type(&mut self, def_id: DefId) -> Lazy> { let tcx = self.tcx; let ty = tcx.type_of(def_id); - debug!("IsolatedEncoder::encode_item_type({:?}) => {:?}", def_id, ty); + debug!("EncodeContext::encode_item_type({:?}) => {:?}", def_id, ty); self.lazy(&ty) } - /// Encode data for the given variant of the given ADT. The - /// index of the variant is untracked: this is ok because we - /// will have to lookup the adt-def by its id, and that gives us - /// the right to access any information in the adt-def (including, - /// e.g., the length of the various vectors). fn encode_enum_variant_info( &mut self, - (enum_did, Untracked(index)): (DefId, Untracked), + (enum_did, index): (DefId, VariantIdx), ) -> Entry<'tcx> { let tcx = self.tcx; let def = tcx.adt_def(enum_did); let variant = &def.variants[index]; let def_id = variant.def_id; - debug!("IsolatedEncoder::encode_enum_variant_info({:?})", def_id); + debug!("EncodeContext::encode_enum_variant_info({:?})", def_id); let data = VariantData { ctor_kind: variant.ctor_kind, @@ -625,17 +609,15 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } } - /// Encode the constructor for the given variant of the given ADT. See - /// `encode_enum_variant_info` for an explanation about why the index is untracked. fn encode_enum_variant_ctor( &mut self, - (enum_did, Untracked(index)): (DefId, Untracked), + (enum_did, index): (DefId, VariantIdx), ) -> Entry<'tcx> { let tcx = self.tcx; let def = tcx.adt_def(enum_did); let variant = &def.variants[index]; let def_id = variant.ctor_def_id.unwrap(); - debug!("IsolatedEncoder::encode_enum_variant_ctor({:?})", def_id); + debug!("EncodeContext::encode_enum_variant_ctor({:?})", def_id); let data = VariantData { ctor_kind: variant.ctor_kind, @@ -681,18 +663,17 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } } - fn encode_info_for_mod(&mut self, - FromId(id, (md, attrs, vis)): FromId<(&hir::Mod, - &[ast::Attribute], - &hir::Visibility)>) - -> Entry<'tcx> { + fn encode_info_for_mod( + &mut self, + (id, md, attrs, vis): (hir::HirId, &hir::Mod, &[ast::Attribute], &hir::Visibility), + ) -> Entry<'tcx> { let tcx = self.tcx; let def_id = tcx.hir().local_def_id_from_hir_id(id); - debug!("IsolatedEncoder::encode_info_for_mod({:?})", def_id); + debug!("EncodeContext::encode_info_for_mod({:?})", def_id); let data = ModData { reexports: match tcx.module_exports(def_id) { - Some(ref exports) => self.lazy_seq_from_slice(exports.as_slice()), + Some(ref exports) => self.lazy_seq_ref(&exports[..]), _ => LazySeq::empty(), }, }; @@ -719,23 +700,16 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } } - /// Encode data for the given field of the given variant of the - /// given ADT. The indices of the variant/field are untracked: - /// this is ok because we will have to lookup the adt-def by its - /// id, and that gives us the right to access any information in - /// the adt-def (including, e.g., the length of the various - /// vectors). - fn encode_field(&mut self, - (adt_def_id, Untracked((variant_index, field_index))): (DefId, - Untracked<(VariantIdx, - usize)>)) - -> Entry<'tcx> { + fn encode_field( + &mut self, + (adt_def_id, variant_index, field_index): (DefId, VariantIdx, usize), + ) -> Entry<'tcx> { let tcx = self.tcx; let variant = &tcx.adt_def(adt_def_id).variants[variant_index]; let field = &variant.fields[field_index]; let def_id = field.did; - debug!("IsolatedEncoder::encode_field({:?})", def_id); + debug!("EncodeContext::encode_field({:?})", def_id); let variant_id = tcx.hir().as_local_hir_id(variant.def_id).unwrap(); let variant_data = tcx.hir().expect_variant_data(variant_id); @@ -761,7 +735,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<'tcx> { - debug!("IsolatedEncoder::encode_struct_ctor({:?})", def_id); + debug!("EncodeContext::encode_struct_ctor({:?})", def_id); let tcx = self.tcx; let adt_def = tcx.adt_def(adt_def_id); let variant = adt_def.non_enum_variant(); @@ -821,25 +795,25 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } fn encode_generics(&mut self, def_id: DefId) -> Lazy { - debug!("IsolatedEncoder::encode_generics({:?})", def_id); + debug!("EncodeContext::encode_generics({:?})", def_id); let tcx = self.tcx; self.lazy(tcx.generics_of(def_id)) } fn encode_predicates(&mut self, def_id: DefId) -> Lazy> { - debug!("IsolatedEncoder::encode_predicates({:?})", def_id); + debug!("EncodeContext::encode_predicates({:?})", def_id); let tcx = self.tcx; self.lazy(&tcx.predicates_of(def_id)) } fn encode_predicates_defined_on(&mut self, def_id: DefId) -> Lazy> { - debug!("IsolatedEncoder::encode_predicates_defined_on({:?})", def_id); + debug!("EncodeContext::encode_predicates_defined_on({:?})", def_id); let tcx = self.tcx; self.lazy(&tcx.predicates_defined_on(def_id)) } fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> { - debug!("IsolatedEncoder::encode_info_for_trait_item({:?})", def_id); + debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id); let tcx = self.tcx; let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); @@ -949,7 +923,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> { - debug!("IsolatedEncoder::encode_info_for_impl_item({:?})", def_id); + debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id); let tcx = self.tcx; let hir_id = self.tcx.hir().as_local_hir_id(def_id).unwrap(); @@ -1064,7 +1038,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { // Encodes the inherent implementations of a structure, enumeration, or trait. fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq { - debug!("IsolatedEncoder::encode_inherent_implementations({:?})", def_id); + debug!("EncodeContext::encode_inherent_implementations({:?})", def_id); let implementations = self.tcx.inherent_impls(def_id); if implementations.is_empty() { LazySeq::empty() @@ -1077,12 +1051,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } fn encode_stability(&mut self, def_id: DefId) -> Option> { - debug!("IsolatedEncoder::encode_stability({:?})", def_id); + debug!("EncodeContext::encode_stability({:?})", def_id); self.tcx.lookup_stability(def_id).map(|stab| self.lazy(stab)) } fn encode_deprecation(&mut self, def_id: DefId) -> Option> { - debug!("IsolatedEncoder::encode_deprecation({:?})", def_id); + debug!("EncodeContext::encode_deprecation({:?})", def_id); self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(&depr)) } @@ -1096,7 +1070,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> Entry<'tcx> { let tcx = self.tcx; - debug!("IsolatedEncoder::encode_info_for_item({:?})", def_id); + debug!("EncodeContext::encode_info_for_item({:?})", def_id); let kind = match item.node { hir::ItemKind::Static(_, hir::MutMutable, _) => EntryKind::MutStatic, @@ -1118,7 +1092,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { EntryKind::Fn(self.lazy(&data)) } hir::ItemKind::Mod(ref m) => { - return self.encode_info_for_mod(FromId(item.hir_id, (m, &item.attrs, &item.vis))); + return self.encode_info_for_mod((item.hir_id, m, &item.attrs, &item.vis)); } hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod, hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm, @@ -1391,9 +1365,9 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { fn encode_info_for_ty_param( &mut self, - (def_id, Untracked(encode_type)): (DefId, Untracked), + (def_id, encode_type): (DefId, bool), ) -> Entry<'tcx> { - debug!("IsolatedEncoder::encode_info_for_ty_param({:?})", def_id); + debug!("EncodeContext::encode_info_for_ty_param({:?})", def_id); self.encode_info_for_generic_param(def_id, EntryKind::TypeParam, encode_type) } @@ -1401,12 +1375,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { &mut self, def_id: DefId, ) -> Entry<'tcx> { - debug!("IsolatedEncoder::encode_info_for_const_param({:?})", def_id); + debug!("EncodeContext::encode_info_for_const_param({:?})", def_id); self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true) } fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> { - debug!("IsolatedEncoder::encode_info_for_closure({:?})", def_id); + debug!("EncodeContext::encode_info_for_closure({:?})", def_id); let tcx = self.tcx; let tables = self.tcx.typeck_tables_of(def_id); @@ -1450,7 +1424,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } fn encode_info_for_anon_const(&mut self, def_id: DefId) -> Entry<'tcx> { - debug!("IsolatedEncoder::encode_info_for_anon_const({:?})", def_id); + debug!("EncodeContext::encode_info_for_anon_const({:?})", def_id); let tcx = self.tcx; let id = tcx.hir().as_local_hir_id(def_id).unwrap(); let body_id = tcx.hir().body_owned_by(id); @@ -1478,23 +1452,20 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq { - // NOTE: This must use lazy_seq_from_slice(), not lazy_seq() because - // we rely on the HashStable specialization for [Attribute] - // to properly filter things out. - self.lazy_seq_from_slice(attrs) + self.lazy_seq_ref(attrs) } - fn encode_native_libraries(&mut self, _: ()) -> LazySeq { + fn encode_native_libraries(&mut self) -> LazySeq { let used_libraries = self.tcx.native_libraries(LOCAL_CRATE); self.lazy_seq(used_libraries.iter().cloned()) } - fn encode_foreign_modules(&mut self, _: ()) -> LazySeq { + fn encode_foreign_modules(&mut self) -> LazySeq { let foreign_modules = self.tcx.foreign_modules(LOCAL_CRATE); self.lazy_seq(foreign_modules.iter().cloned()) } - fn encode_crate_deps(&mut self, _: ()) -> LazySeq { + fn encode_crate_deps(&mut self) -> LazySeq { let crates = self.tcx.crates(); let mut deps = crates @@ -1528,13 +1499,13 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { self.lazy_seq_ref(deps.iter().map(|&(_, ref dep)| dep)) } - fn encode_lib_features(&mut self, _: ()) -> LazySeq<(ast::Name, Option)> { + fn encode_lib_features(&mut self) -> LazySeq<(ast::Name, Option)> { let tcx = self.tcx; let lib_features = tcx.lib_features(); self.lazy_seq(lib_features.to_vec()) } - fn encode_lang_items(&mut self, _: ()) -> LazySeq<(DefIndex, usize)> { + fn encode_lang_items(&mut self) -> LazySeq<(DefIndex, usize)> { let tcx = self.tcx; let lang_items = tcx.lang_items(); let lang_items = lang_items.items().iter(); @@ -1548,14 +1519,14 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { })) } - fn encode_lang_items_missing(&mut self, _: ()) -> LazySeq { + fn encode_lang_items_missing(&mut self) -> LazySeq { let tcx = self.tcx; self.lazy_seq_ref(&tcx.lang_items().missing) } /// Encodes an index, mapping each trait to its (local) implementations. - fn encode_impls(&mut self, _: ()) -> LazySeq { - debug!("IsolatedEncoder::encode_impls()"); + fn encode_impls(&mut self) -> LazySeq { + debug!("EncodeContext::encode_impls()"); let tcx = self.tcx; let mut visitor = ImplVisitor { tcx, @@ -1580,12 +1551,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { TraitImpls { trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index), - impls: self.lazy_seq_from_slice(&impls[..]), + impls: self.lazy_seq_ref(&impls), } }) .collect(); - self.lazy_seq_from_slice(&all_impls[..]) + self.lazy_seq_ref(&all_impls) } // Encodes all symbols exported from this crate into the metadata. @@ -1614,7 +1585,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { .cloned()) } - fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq> { + fn encode_dylib_dependency_formats(&mut self) -> LazySeq> { match self.tcx.sess.dependency_formats.borrow().get(&config::CrateType::Dylib) { Some(arr) => { self.lazy_seq(arr.iter().map(|slot| { @@ -1636,7 +1607,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { -> Entry<'tcx> { let tcx = self.tcx; - debug!("IsolatedEncoder::encode_info_for_foreign_item({:?})", def_id); + debug!("EncodeContext::encode_info_for_foreign_item({:?})", def_id); let kind = match nitem.node { hir::ForeignItemKind::Fn(_, ref names, _) => { @@ -1676,33 +1647,29 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } } -struct EncodeVisitor<'a, 'b: 'a, 'tcx: 'b> { - index: IndexBuilder<'a, 'b, 'tcx>, -} - -impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { +impl Visitor<'tcx> for EncodeContext<'_, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.index.tcx.hir()) + NestedVisitorMap::OnlyBodies(&self.tcx.hir()) } fn visit_expr(&mut self, ex: &'tcx hir::Expr) { intravisit::walk_expr(self, ex); - self.index.encode_info_for_expr(ex); + self.encode_info_for_expr(ex); } fn visit_item(&mut self, item: &'tcx hir::Item) { intravisit::walk_item(self, item); - let def_id = self.index.tcx.hir().local_def_id_from_hir_id(item.hir_id); + let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id); match item.node { hir::ItemKind::ExternCrate(_) | - hir::ItemKind::Use(..) => (), // ignore these - _ => self.index.record(def_id, IsolatedEncoder::encode_info_for_item, (def_id, item)), + hir::ItemKind::Use(..) => {} // ignore these + _ => self.record(def_id, EncodeContext::encode_info_for_item, (def_id, item)), } - self.index.encode_addl_info_for_item(item); + self.encode_addl_info_for_item(item); } fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) { intravisit::walk_foreign_item(self, ni); - let def_id = self.index.tcx.hir().local_def_id_from_hir_id(ni.hir_id); - self.index.record(def_id, - IsolatedEncoder::encode_info_for_foreign_item, + let def_id = self.tcx.hir().local_def_id_from_hir_id(ni.hir_id); + self.record(def_id, + EncodeContext::encode_info_for_foreign_item, (def_id, ni)); } fn visit_variant(&mut self, @@ -1712,32 +1679,32 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { intravisit::walk_variant(self, v, g, id); if let Some(ref discr) = v.node.disr_expr { - let def_id = self.index.tcx.hir().local_def_id_from_hir_id(discr.hir_id); - self.index.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id); + let def_id = self.tcx.hir().local_def_id_from_hir_id(discr.hir_id); + self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id); } } fn visit_generics(&mut self, generics: &'tcx hir::Generics) { intravisit::walk_generics(self, generics); - self.index.encode_info_for_generics(generics); + self.encode_info_for_generics(generics); } fn visit_ty(&mut self, ty: &'tcx hir::Ty) { intravisit::walk_ty(self, ty); - self.index.encode_info_for_ty(ty); + self.encode_info_for_ty(ty); } fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) { - let def_id = self.index.tcx.hir().local_def_id_from_hir_id(macro_def.hir_id); - self.index.record(def_id, IsolatedEncoder::encode_info_for_macro_def, macro_def); + let def_id = self.tcx.hir().local_def_id_from_hir_id(macro_def.hir_id); + self.record(def_id, EncodeContext::encode_info_for_macro_def, macro_def); } } -impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { +impl EncodeContext<'_, 'tcx> { fn encode_fields(&mut self, adt_def_id: DefId) { let def = self.tcx.adt_def(adt_def_id); for (variant_index, variant) in def.variants.iter_enumerated() { for (field_index, field) in variant.fields.iter().enumerate() { self.record(field.did, - IsolatedEncoder::encode_field, - (adt_def_id, Untracked((variant_index, field_index)))); + EncodeContext::encode_field, + (adt_def_id, variant_index, field_index)); } } } @@ -1750,12 +1717,12 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { GenericParamKind::Type { ref default, .. } => { self.record( def_id, - IsolatedEncoder::encode_info_for_ty_param, - (def_id, Untracked(default.is_some())), + EncodeContext::encode_info_for_ty_param, + (def_id, default.is_some()), ); } GenericParamKind::Const { .. } => { - self.record(def_id, IsolatedEncoder::encode_info_for_const_param, def_id); + self.record(def_id, EncodeContext::encode_info_for_const_param, def_id); } } } @@ -1765,7 +1732,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { match ty.node { hir::TyKind::Array(_, ref length) => { let def_id = self.tcx.hir().local_def_id_from_hir_id(length.hir_id); - self.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id); + self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id); } _ => {} } @@ -1775,7 +1742,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { match expr.node { hir::ExprKind::Closure(..) => { let def_id = self.tcx.hir().local_def_id_from_hir_id(expr.hir_id); - self.record(def_id, IsolatedEncoder::encode_info_for_closure, def_id); + self.record(def_id, EncodeContext::encode_info_for_closure, def_id); } _ => {} } @@ -1807,13 +1774,13 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { let def = self.tcx.adt_def(def_id); for (i, variant) in def.variants.iter_enumerated() { self.record(variant.def_id, - IsolatedEncoder::encode_enum_variant_info, - (def_id, Untracked(i))); + EncodeContext::encode_enum_variant_info, + (def_id, i)); if let Some(ctor_def_id) = variant.ctor_def_id { self.record(ctor_def_id, - IsolatedEncoder::encode_enum_variant_ctor, - (def_id, Untracked(i))); + EncodeContext::encode_enum_variant_ctor, + (def_id, i)); } } } @@ -1824,7 +1791,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { if let Some(ctor_hir_id) = struct_def.ctor_hir_id() { let ctor_def_id = self.tcx.hir().local_def_id_from_hir_id(ctor_hir_id); self.record(ctor_def_id, - IsolatedEncoder::encode_struct_ctor, + EncodeContext::encode_struct_ctor, (def_id, ctor_def_id)); } } @@ -1834,14 +1801,14 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { hir::ItemKind::Impl(..) => { for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() { self.record(trait_item_def_id, - IsolatedEncoder::encode_info_for_impl_item, + EncodeContext::encode_info_for_impl_item, trait_item_def_id); } } hir::ItemKind::Trait(..) => { for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() { self.record(item_def_id, - IsolatedEncoder::encode_info_for_trait_item, + EncodeContext::encode_info_for_trait_item, item_def_id); } } @@ -1906,10 +1873,13 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) // Will be filled with the root position after encoding everything. encoder.emit_raw_bytes(&[0, 0, 0, 0]); - let (root, mut result) = { + // Since encoding metadata is not in a query, and nothing is cached, + // there's no need to do dep-graph tracking for any of it. + let (root, mut result) = tcx.dep_graph.with_ignore(move || { let mut ecx = EncodeContext { opaque: encoder, tcx, + entries_index: Index::new(tcx.hir().definitions().def_index_count()), lazy_state: LazyState::NoNode, type_shorthands: Default::default(), predicate_shorthands: Default::default(), @@ -1925,7 +1895,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) // culminating in the `CrateRoot` which points to all of it. let root = ecx.encode_crate_root(); (root, ecx.opaque.into_inner()) - }; + }); // Encode the root position. let header = METADATA_HEADER.len(); diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs deleted file mode 100644 index ee928968cb42..000000000000 --- a/src/librustc_metadata/index_builder.rs +++ /dev/null @@ -1,224 +0,0 @@ -//! Builder types for generating the "item data" section of the -//! metadata. This section winds up looking like this: -//! -//! ``` -//! // big list of item-like things... -//! // ...for most `DefId`s, there is an entry. -//! -//! -//! ``` -//! -//! As we generate this listing, we collect the offset of each -//! `data_item` entry and store it in an index. Then, when we load the -//! metadata, we can skip right to the metadata for a particular item. -//! -//! In addition to the offset, we need to track the data that was used -//! to generate the contents of each `data_item`. This is so that we -//! can figure out which HIR nodes contributed to that data for -//! incremental compilation purposes. -//! -//! The `IndexBuilder` facilitates both of these. It is created -//! with an `EncodingContext` (`ecx`), which it encapsulates. -//! It has one main method, `record()`. You invoke `record` -//! like so to create a new `data_item` element in the list: -//! -//! ``` -//! index.record(some_def_id, callback_fn, data) -//! ``` -//! -//! What record will do is to (a) record the current offset, (b) emit -//! the `common::data_item` tag, and then call `callback_fn` with the -//! given data as well as the `EncodingContext`. Once `callback_fn` -//! returns, the `common::data_item` tag will be closed. -//! -//! `EncodingContext` does not offer the `record` method, so that we -//! can ensure that `common::data_item` elements are never nested. -//! -//! In addition, while the `callback_fn` is executing, we will push a -//! task `MetaData(some_def_id)`, which can then observe the -//! reads/writes that occur in the task. For this reason, the `data` -//! argument that is given to the `callback_fn` must implement the -//! trait `DepGraphRead`, which indicates how to register reads on the -//! data in this new task (note that many types of data, such as -//! `DefId`, do not currently require any reads to be registered, -//! since they are not derived from a HIR node). This is also why we -//! give a callback fn, rather than taking a closure: it allows us to -//! easily control precisely what data is given to that fn. - -use crate::encoder::EncodeContext; -use crate::index::Index; -use crate::schema::*; -use crate::isolated_encoder::IsolatedEncoder; - -use rustc::hir; -use rustc::hir::def_id::DefId; -use rustc::ty::TyCtxt; -use syntax::ast; - -use std::ops::{Deref, DerefMut}; - -/// Builder that can encode new items, adding them into the index. -/// Item encoding cannot be nested. -pub struct IndexBuilder<'a, 'b: 'a, 'tcx: 'b> { - items: Index<'tcx>, - pub ecx: &'a mut EncodeContext<'b, 'tcx>, -} - -impl<'a, 'b, 'tcx> Deref for IndexBuilder<'a, 'b, 'tcx> { - type Target = EncodeContext<'b, 'tcx>; - fn deref(&self) -> &Self::Target { - self.ecx - } -} - -impl<'a, 'b, 'tcx> DerefMut for IndexBuilder<'a, 'b, 'tcx> { - fn deref_mut(&mut self) -> &mut Self::Target { - self.ecx - } -} - -impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { - pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self { - IndexBuilder { - items: Index::new(ecx.tcx.hir().definitions().def_index_count()), - ecx, - } - } - - /// Emit the data for a `DefId` to the metadata. The function to - /// emit the data is `op`, and it will be given `data` as - /// arguments. This `record` function will call `op` to generate - /// the `Entry` (which may point to other encoded information) - /// and will then record the `Lazy` for use in the index. - /// - /// In addition, it will setup a dep-graph task to track what data - /// `op` accesses to generate the metadata, which is later used by - /// incremental compilation to compute a hash for the metadata and - /// track changes. - /// - /// The reason that `op` is a function pointer, and not a closure, - /// is that we want to be able to completely track all data it has - /// access to, so that we can be sure that `DATA: DepGraphRead` - /// holds, and that it is therefore not gaining "secret" access to - /// bits of HIR or other state that would not be trackd by the - /// content system. - pub fn record<'x, DATA>(&'x mut self, - id: DefId, - op: fn(&mut IsolatedEncoder<'x, 'b, 'tcx>, DATA) -> Entry<'tcx>, - data: DATA) - where DATA: DepGraphRead - { - assert!(id.is_local()); - - // We don't track this since we are explicitly computing the incr. comp. - // hashes anyway. In theory we could do some tracking here and use it to - // avoid rehashing things (and instead cache the hashes) but it's - // unclear whether that would be a win since hashing is cheap enough. - self.ecx.tcx.dep_graph.with_ignore(move || { - let mut entry_builder = IsolatedEncoder::new(self.ecx); - let entry = op(&mut entry_builder, data); - let entry = entry_builder.lazy(&entry); - - self.items.record(id, entry); - }) - } - - pub fn into_items(self) -> Index<'tcx> { - self.items - } -} - -/// Trait used for data that can be passed from outside a dep-graph -/// task. The data must either be of some safe type, such as a -/// `DefId` index, or implement the `read` method so that it can add -/// a read of whatever dep-graph nodes are appropriate. -pub trait DepGraphRead { - fn read(&self, tcx: TyCtxt<'_, '_, '_>); -} - -impl DepGraphRead for DefId { - fn read(&self, _tcx: TyCtxt<'_, '_, '_>) {} -} - -impl DepGraphRead for ast::NodeId { - fn read(&self, _tcx: TyCtxt<'_, '_, '_>) {} -} - -impl DepGraphRead for Option - where T: DepGraphRead -{ - fn read(&self, tcx: TyCtxt<'_, '_, '_>) { - match *self { - Some(ref v) => v.read(tcx), - None => (), - } - } -} - -impl DepGraphRead for [T] - where T: DepGraphRead -{ - fn read(&self, tcx: TyCtxt<'_, '_, '_>) { - for i in self { - i.read(tcx); - } - } -} - -macro_rules! read_tuple { - ($($name:ident),*) => { - impl<$($name),*> DepGraphRead for ($($name),*) - where $($name: DepGraphRead),* - { - #[allow(non_snake_case)] - fn read(&self, tcx: TyCtxt<'_, '_, '_>) { - let &($(ref $name),*) = self; - $($name.read(tcx);)* - } - } - } -} -read_tuple!(A, B); -read_tuple!(A, B, C); - -macro_rules! read_hir { - ($t:ty) => { - impl<'tcx> DepGraphRead for &'tcx $t { - fn read(&self, tcx: TyCtxt<'_, '_, '_>) { - tcx.hir().read(self.hir_id); - } - } - } -} -read_hir!(hir::Item); -read_hir!(hir::ImplItem); -read_hir!(hir::TraitItem); -read_hir!(hir::ForeignItem); -read_hir!(hir::MacroDef); - -/// Leaks access to a value of type T without any tracking. This is -/// suitable for ambiguous types like `usize`, which *could* represent -/// tracked data (e.g., if you read it out of a HIR node) or might not -/// (e.g., if it's an index). Adding in an `Untracked` is an -/// assertion, essentially, that the data does not need to be tracked -/// (or that read edges will be added by some other way). -/// -/// A good idea is to add to each use of `Untracked` an explanation of -/// why this value is ok. -pub struct Untracked(pub T); - -impl DepGraphRead for Untracked { - fn read(&self, _tcx: TyCtxt<'_, '_, '_>) {} -} - -/// Newtype that can be used to package up misc data extracted from a -/// HIR node that doesn't carry its own ID. This will allow an -/// arbitrary `T` to be passed in, but register a read on the given -/// `NodeId`. -pub struct FromId(pub hir::HirId, pub T); - -impl DepGraphRead for FromId { - fn read(&self, tcx: TyCtxt<'_, '_, '_>) { - tcx.hir().read(self.0); - } -} diff --git a/src/librustc_metadata/isolated_encoder.rs b/src/librustc_metadata/isolated_encoder.rs deleted file mode 100644 index e879a73e650b..000000000000 --- a/src/librustc_metadata/isolated_encoder.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::encoder::EncodeContext; -use crate::schema::{Lazy, LazySeq}; -use rustc::ty::TyCtxt; -use rustc_serialize::Encodable; - -/// The IsolatedEncoder provides facilities to write to crate metadata while -/// making sure that anything going through it is also feed into an ICH hasher. -pub struct IsolatedEncoder<'a, 'b: 'a, 'tcx: 'b> { - pub tcx: TyCtxt<'b, 'tcx, 'tcx>, - ecx: &'a mut EncodeContext<'b, 'tcx>, -} - -impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { - - pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self { - let tcx = ecx.tcx; - IsolatedEncoder { - tcx, - ecx, - } - } - - pub fn lazy(&mut self, value: &T) -> Lazy - where T: Encodable - { - self.ecx.lazy(value) - } - - pub fn lazy_seq(&mut self, iter: I) -> LazySeq - where I: IntoIterator, - T: Encodable - { - self.ecx.lazy_seq(iter) - } - - pub fn lazy_seq_ref<'x, I, T>(&mut self, iter: I) -> LazySeq - where I: IntoIterator, - T: 'x + Encodable - { - self.ecx.lazy_seq_ref(iter) - } - - pub fn lazy_seq_from_slice(&mut self, slice: &[T]) -> LazySeq - where T: Encodable - { - self.ecx.lazy_seq_ref(slice.iter()) - } -} diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 0faadd23f47a..e0b92341575c 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -29,12 +29,10 @@ extern crate rustc_data_structures; mod error_codes; -mod index_builder; mod index; mod encoder; mod decoder; mod cstore_impl; -mod isolated_encoder; mod schema; mod native_libs; mod link_args; diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index b2f6fd65ed44..0ad325154071 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -2,8 +2,7 @@ use crate::index; use rustc::hir; use rustc::hir::def::{self, CtorKind}; -use rustc::hir::def_id::{DefIndex, DefId, CrateNum}; -use rustc::ich::StableHashingContext; +use rustc::hir::def_id::{DefIndex, DefId}; use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary, ForeignModule}; use rustc::middle::lang_items; @@ -20,10 +19,6 @@ use syntax::symbol::Symbol; use syntax_pos::{self, Span}; use std::marker::PhantomData; -use std::mem; - -use rustc_data_structures::stable_hasher::{StableHasher, HashStable, - StableHasherResult}; pub fn rustc_version() -> String { format!("rustc {}", @@ -92,15 +87,6 @@ impl Clone for Lazy { impl serialize::UseSpecializedEncodable for Lazy {} impl serialize::UseSpecializedDecodable for Lazy {} -impl HashStable for Lazy { - fn hash_stable(&self, - _: &mut CTX, - _: &mut StableHasher) { - // There's nothing to do. Whatever got encoded within this Lazy<> - // wrapper has already been hashed. - } -} - /// A sequence of type T referred to by its absolute position /// in the metadata and length, and which can be decoded lazily. /// The sequence is a single node for the purposes of `Lazy`. @@ -149,15 +135,6 @@ impl Clone for LazySeq { impl serialize::UseSpecializedEncodable for LazySeq {} impl serialize::UseSpecializedDecodable for LazySeq {} -impl HashStable for LazySeq { - fn hash_stable(&self, - _: &mut CTX, - _: &mut StableHasher) { - // There's nothing to do. Whatever got encoded within this Lazy<> - // wrapper has already been hashed. - } -} - /// Encoding / decoding state for `Lazy` and `LazySeq`. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum LazyState { @@ -203,7 +180,7 @@ pub struct CrateRoot<'tcx> { pub exported_symbols: LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)>, pub interpret_alloc_index: LazySeq, - pub index: LazySeq>, + pub entries_index: LazySeq>, pub compiler_builtins: bool, pub needs_allocator: bool, @@ -222,36 +199,12 @@ pub struct CrateDep { pub extra_filename: String, } -impl_stable_hash_for!(struct CrateDep { - name, - hash, - kind, - extra_filename -}); - #[derive(RustcEncodable, RustcDecodable)] pub struct TraitImpls { pub trait_id: (u32, DefIndex), pub impls: LazySeq, } -impl<'a, 'gcx> HashStable> for TraitImpls { - fn hash_stable(&self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher) { - let TraitImpls { - trait_id: (krate, def_index), - ref impls, - } = *self; - - DefId { - krate: CrateNum::from_u32(krate), - index: def_index - }.hash_stable(hcx, hasher); - impls.hash_stable(hcx, hasher); - } -} - #[derive(RustcEncodable, RustcDecodable)] pub struct Entry<'tcx> { pub kind: EntryKind<'tcx>, @@ -272,23 +225,6 @@ pub struct Entry<'tcx> { pub mir: Option>>, } -impl_stable_hash_for!(struct Entry<'tcx> { - kind, - visibility, - span, - attributes, - children, - stability, - deprecation, - ty, - inherent_impls, - variances, - generics, - predicates, - predicates_defined_on, - mir -}); - #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] pub enum EntryKind<'tcx> { Const(ConstQualif, Lazy), @@ -323,82 +259,6 @@ pub enum EntryKind<'tcx> { TraitAlias(Lazy>), } -impl<'a, 'gcx> HashStable> for EntryKind<'gcx> { - fn hash_stable(&self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher) { - mem::discriminant(self).hash_stable(hcx, hasher); - match *self { - EntryKind::ImmStatic | - EntryKind::MutStatic | - EntryKind::ForeignImmStatic | - EntryKind::ForeignMutStatic | - EntryKind::ForeignMod | - EntryKind::GlobalAsm | - EntryKind::ForeignType | - EntryKind::Field | - EntryKind::Existential | - EntryKind::Type | - EntryKind::TypeParam | - EntryKind::ConstParam => { - // Nothing else to hash here. - } - EntryKind::Const(qualif, ref const_data) => { - qualif.hash_stable(hcx, hasher); - const_data.hash_stable(hcx, hasher); - } - EntryKind::Enum(ref repr_options) => { - repr_options.hash_stable(hcx, hasher); - } - EntryKind::Variant(ref variant_data) => { - variant_data.hash_stable(hcx, hasher); - } - EntryKind::Struct(ref variant_data, ref repr_options) | - EntryKind::Union(ref variant_data, ref repr_options) => { - variant_data.hash_stable(hcx, hasher); - repr_options.hash_stable(hcx, hasher); - } - EntryKind::Fn(ref fn_data) | - EntryKind::ForeignFn(ref fn_data) => { - fn_data.hash_stable(hcx, hasher); - } - EntryKind::Mod(ref mod_data) => { - mod_data.hash_stable(hcx, hasher); - } - EntryKind::MacroDef(ref macro_def) => { - macro_def.hash_stable(hcx, hasher); - } - EntryKind::Generator(data) => { - data.hash_stable(hcx, hasher); - } - EntryKind::Closure(closure_data) => { - closure_data.hash_stable(hcx, hasher); - } - EntryKind::Trait(ref trait_data) => { - trait_data.hash_stable(hcx, hasher); - } - EntryKind::TraitAlias(ref trait_alias_data) => { - trait_alias_data.hash_stable(hcx, hasher); - } - EntryKind::Impl(ref impl_data) => { - impl_data.hash_stable(hcx, hasher); - } - EntryKind::Method(ref method_data) => { - method_data.hash_stable(hcx, hasher); - } - EntryKind::AssociatedExistential(associated_container) | - EntryKind::AssociatedType(associated_container) => { - associated_container.hash_stable(hcx, hasher); - } - EntryKind::AssociatedConst(associated_container, qualif, ref const_data) => { - associated_container.hash_stable(hcx, hasher); - qualif.hash_stable(hcx, hasher); - const_data.hash_stable(hcx, hasher); - } - } - } -} - /// Additional data for EntryKind::Const and EntryKind::AssociatedConst #[derive(Clone, Copy, RustcEncodable, RustcDecodable)] pub struct ConstQualif { @@ -406,37 +266,22 @@ pub struct ConstQualif { pub ast_promotable: bool, } -impl_stable_hash_for!(struct ConstQualif { mir, ast_promotable }); - /// Contains a constant which has been rendered to a String. /// Used by rustdoc. #[derive(RustcEncodable, RustcDecodable)] pub struct RenderedConst(pub String); -impl<'a> HashStable> for RenderedConst { - #[inline] - fn hash_stable(&self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher) { - self.0.hash_stable(hcx, hasher); - } -} - #[derive(RustcEncodable, RustcDecodable)] pub struct ModData { pub reexports: LazySeq>, } -impl_stable_hash_for!(struct ModData { reexports }); - #[derive(RustcEncodable, RustcDecodable)] pub struct MacroDef { pub body: String, pub legacy: bool, } -impl_stable_hash_for!(struct MacroDef { body, legacy }); - #[derive(RustcEncodable, RustcDecodable)] pub struct FnData<'tcx> { pub constness: hir::Constness, @@ -444,8 +289,6 @@ pub struct FnData<'tcx> { pub sig: Lazy>, } -impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig }); - #[derive(RustcEncodable, RustcDecodable)] pub struct VariantData<'tcx> { pub ctor_kind: CtorKind, @@ -457,13 +300,6 @@ pub struct VariantData<'tcx> { pub ctor_sig: Option>>, } -impl_stable_hash_for!(struct VariantData<'tcx> { - ctor_kind, - discr, - ctor, - ctor_sig -}); - #[derive(RustcEncodable, RustcDecodable)] pub struct TraitData<'tcx> { pub unsafety: hir::Unsafety, @@ -473,23 +309,11 @@ pub struct TraitData<'tcx> { pub super_predicates: Lazy>, } -impl_stable_hash_for!(struct TraitData<'tcx> { - unsafety, - paren_sugar, - has_auto_impl, - is_marker, - super_predicates -}); - #[derive(RustcEncodable, RustcDecodable)] pub struct TraitAliasData<'tcx> { pub super_predicates: Lazy>, } -impl_stable_hash_for!(struct TraitAliasData<'tcx> { - super_predicates -}); - #[derive(RustcEncodable, RustcDecodable)] pub struct ImplData<'tcx> { pub polarity: hir::ImplPolarity, @@ -501,14 +325,6 @@ pub struct ImplData<'tcx> { pub trait_ref: Option>>, } -impl_stable_hash_for!(struct ImplData<'tcx> { - polarity, - defaultness, - parent_impl, - coerce_unsized_info, - trait_ref -}); - /// Describes whether the container of an associated item /// is a trait or an impl and whether, in a trait, it has @@ -521,13 +337,6 @@ pub enum AssociatedContainer { ImplFinal, } -impl_stable_hash_for!(enum crate::schema::AssociatedContainer { - TraitRequired, - TraitWithDefault, - ImplDefault, - ImplFinal -}); - impl AssociatedContainer { pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer { match *self { @@ -561,19 +370,16 @@ pub struct MethodData<'tcx> { pub container: AssociatedContainer, pub has_self: bool, } -impl_stable_hash_for!(struct MethodData<'tcx> { fn_data, container, has_self }); #[derive(RustcEncodable, RustcDecodable)] pub struct ClosureData<'tcx> { pub sig: Lazy>, } -impl_stable_hash_for!(struct ClosureData<'tcx> { sig }); #[derive(RustcEncodable, RustcDecodable)] pub struct GeneratorData<'tcx> { pub layout: mir::GeneratorLayout<'tcx>, } -impl_stable_hash_for!(struct GeneratorData<'tcx> { layout }); // Tags used for encoding Spans: pub const TAG_VALID_SPAN: u8 = 0; From 08c91f8bef21095d0eca2f7fed080c9672f1db82 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 22 May 2019 13:12:37 +0200 Subject: [PATCH 0258/3207] Update clippy submodule --- src/tools/clippy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy b/src/tools/clippy index 60a609acaed3..a8eeb7cdb135 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 60a609acaed3bf2b3ec6ab995bccf0f03bc26060 +Subproject commit a8eeb7cdb135da1cd582c6093c1739732727a4a2 From 36ee777cebd865ffd7e8223b4ae4bf533f7b476b Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 22 May 2019 13:28:20 +0200 Subject: [PATCH 0259/3207] remove azure badge from the readme --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 4a130d257770..75d7823490a2 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ -[![Build Status](https://dev.azure.com/rust-lang-azure/rust/_apis/build/status/johnterickson.rust?branchName=master)](https://dev.azure.com/rust-lang-azure/rust/_build/latest?definitionId=6&branchName=master) - # The Rust Programming Language This is the main source code repository for [Rust]. It contains the compiler, From 3fd4b22bce195e5c12e478296c8e0c03de6c8331 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 22 May 2019 05:51:50 +0200 Subject: [PATCH 0260/3207] Make maybe_codegen_consume_direct iterate instead of doing recursion --- src/librustc_codegen_ssa/mir/operand.rs | 76 +++++++++++++------------ 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 3b8e5b449538..3db05b7214d6 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -380,45 +380,47 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ) -> Option> { debug!("maybe_codegen_consume_direct(place={:?})", place); - // watch out for locals that do not have an - // alloca; they are handled somewhat differently - if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place { - match self.locals[index] { - LocalRef::Operand(Some(o)) => { - return Some(o); - } - LocalRef::Operand(None) => { - bug!("use of {:?} before def", place); - } - LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => { - // use path below - } - } - } - - // Moves out of scalar and scalar pair fields are trivial. - if let &mir::Place::Projection(ref proj) = place { - if let Some(o) = self.maybe_codegen_consume_direct(bx, &proj.base) { - match proj.elem { - mir::ProjectionElem::Field(ref f, _) => { - return Some(o.extract_field(bx, f.index())); - } - mir::ProjectionElem::Index(_) | - mir::ProjectionElem::ConstantIndex { .. } => { - // ZSTs don't require any actual memory access. - // FIXME(eddyb) deduplicate this with the identical - // checks in `codegen_consume` and `extract_field`. - let elem = o.layout.field(bx.cx(), 0); - if elem.is_zst() { - return Some(OperandRef::new_zst(bx, elem)); + place.iterate(|place_base, place_projection| { + if let mir::PlaceBase::Local(index) = place_base { + match self.locals[*index] { + LocalRef::Operand(Some(mut o)) => { + // Moves out of scalar and scalar pair fields are trivial. + for proj in place_projection { + match proj.elem { + mir::ProjectionElem::Field(ref f, _) => { + o = o.extract_field(bx, f.index()); + } + mir::ProjectionElem::Index(_) | + mir::ProjectionElem::ConstantIndex { .. } => { + // ZSTs don't require any actual memory access. + // FIXME(eddyb) deduplicate this with the identical + // checks in `codegen_consume` and `extract_field`. + let elem = o.layout.field(bx.cx(), 0); + if elem.is_zst() { + o = OperandRef::new_zst(bx, elem); + } else { + return None; + } + } + _ => return None, + } } - } - _ => {} - } - } - } - None + Some(o) + } + LocalRef::Operand(None) => { + bug!("use of {:?} before def", place); + } + LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => { + // watch out for locals that do not have an + // alloca; they are handled somewhat differently + None + } + } + } else { + None + } + }) } pub fn codegen_consume( From a8ac80b7bcb46d199c196ec0313ca7fd70aee857 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 22 May 2019 07:09:25 -0700 Subject: [PATCH 0261/3207] Final cleanups * Clean up the `install-windows-build-deps.yml` file and add some more comments where appropriate. * Add some comments to `run.yml` * Don't fast path the `rustfmt` submodule, but we'll take care of that later if necessary. --- .../steps/install-windows-build-deps.yml | 57 ++++++++----------- .azure-pipelines/steps/run.yml | 2 + src/ci/init_repo.sh | 1 - 3 files changed, 27 insertions(+), 33 deletions(-) diff --git a/.azure-pipelines/steps/install-windows-build-deps.yml b/.azure-pipelines/steps/install-windows-build-deps.yml index e54f7b6eb672..037c8daa2a80 100644 --- a/.azure-pipelines/steps/install-windows-build-deps.yml +++ b/.azure-pipelines/steps/install-windows-build-deps.yml @@ -1,21 +1,20 @@ steps: -# FIXME: are these still needed? -# - bash: | -# set -x -# git submodule -# export SUBMODULES_EXCLUDES=$(git submodule | grep -Eow 'src/[^ ]+' | sed 's/\(.*\)/--exclude=\1\/\.git/') -# echo "##vso[task.setvariable variable=SUBMODULES_EXCLUDES;]$SUBMODULES_EXCLUDES" - -# FIXME: needs a comment to justify its existence +# We've had issues with the default drive in use running out of space during a +# build, and it looks like the `C:` drive has more space than the default `D:` +# drive. We should probably confirm this with the azure pipelines team at some +# point, but this seems to fix our "disk space full" problems. - script: | - REM echo hack as drive D is too small - IF NOT "%DISABLE_DISK_SPACE_HACK%"=="1" ( - mkdir c:\MORE_SPACE - mklink /J build c:\MORE_SPACE - ) + mkdir c:\MORE_SPACE + mklink /J build c:\MORE_SPACE displayName: "Ensure build happens on C:/ instead of D:/" condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT')) +# Download and install MSYS2, needed primarily for the test suite (run-make) but +# also used by the MinGW toolchain for assembling things. +# +# FIXME: we should probe the default azure image and see if we can use the MSYS2 +# toolchain there. (if there's even one there). For now though this gets the job +# done. - script: | set MSYS_PATH=%CD%\citools\msys64 choco install msys2 --params="/InstallDir:%MSYS_PATH% /NoPath" -y @@ -37,23 +36,11 @@ steps: # If we need to download a custom MinGW, do so here and set the path # appropriately. # -# Note that this *also* means that we're not using what is typically -# /mingw32/bin/python2.7.exe, which is a "correct" python interpreter where -# /usr/bin/python2.7.exe is not. To ensure we use the right interpreter we -# move `C:\Python27` ahead in PATH and then also make sure the `python2.7.exe` -# file exists in there (which it doesn't by default). -- script: | - powershell -Command "iwr -outf %MINGW_ARCHIVE% %MINGW_URL%/%MINGW_ARCHIVE%" - 7z x -y %MINGW_ARCHIVE% > nul - echo ##vso[task.prependpath]%CD%\%MINGW_DIR%\bin - condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), ne(variables['MINGW_URL'],'')) - displayName: Download custom MinGW - -# Here we do a pretty heinous thing which is to mangle the MinGW installation -# we just had above. Currently, as of this writing, we're using MinGW-w64 -# builds of gcc, and that's currently at 6.3.0. We use 6.3.0 as it appears to -# be the first version which contains a fix for #40546, builds randomly -# failing during LLVM due to ar.exe/ranlib.exe failures. +# Here we also do a pretty heinous thing which is to mangle the MinGW +# installation we just downloaded. Currently, as of this writing, we're using +# MinGW-w64 builds of gcc, and that's currently at 6.3.0. We use 6.3.0 as it +# appears to be the first version which contains a fix for #40546, builds +# randomly failing during LLVM due to ar.exe/ranlib.exe failures. # # Unfortunately, though, 6.3.0 *also* is the first version of MinGW-w64 builds # to contain a regression in gdb (#40184). As a result if we were to use the @@ -67,11 +54,13 @@ steps: # Note that we don't literally overwrite the gdb.exe binary because it appears # to just use gdborig.exe, so that's the binary we deal with instead. - script: | - echo ON + powershell -Command "iwr -outf %MINGW_ARCHIVE% %MINGW_URL%/%MINGW_ARCHIVE%" + 7z x -y %MINGW_ARCHIVE% > nul powershell -Command "iwr -outf 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_URL%/2017-04-20-%MSYS_BITS%bit-gdborig.exe" mv 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_DIR%\bin\gdborig.exe + echo ##vso[task.prependpath]%CD%\%MINGW_DIR%\bin condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), ne(variables['MINGW_URL'],'')) - displayName: Override with 6.3.0 gdb with 6.2.0 gdb + displayName: Download custom MinGW # Otherwise pull in the MinGW installed on appveyor - script: | @@ -79,6 +68,10 @@ steps: condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), eq(variables['MINGW_URL'],'')) displayName: Add MinGW to path +# Make sure we use the native python interpreter instead of some msys equivalent +# one way or another. The msys interpreters seem to have weird path conversions +# baked in which break LLVM's build system one way or another, so let's use the +# native version which keeps everything as native as possible. - script: | copy C:\Python27amd64\python.exe C:\Python27amd64\python2.7.exe echo ##vso[task.prependpath]C:\Python27amd64 diff --git a/.azure-pipelines/steps/run.yml b/.azure-pipelines/steps/run.yml index f7ee490b1fdc..47a4c1830851 100644 --- a/.azure-pipelines/steps/run.yml +++ b/.azure-pipelines/steps/run.yml @@ -114,6 +114,8 @@ steps: AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY) displayName: Run build +# If we're a deploy builder, use the `aws` command to publish everything to our +# bucket. - bash: | set -e if [ "$AGENT_OS" = "Linux" ]; then diff --git a/src/ci/init_repo.sh b/src/ci/init_repo.sh index 10215d863be0..3dfd33815761 100755 --- a/src/ci/init_repo.sh +++ b/src/ci/init_repo.sh @@ -47,7 +47,6 @@ function fetch_github_commit_archive { } included="src/llvm-project src/llvm-emscripten src/doc/book src/doc/rust-by-example" -included="${included} src/tools/rustfmt" modules="$(git config --file .gitmodules --get-regexp '\.path$' | cut -d' ' -f2)" modules=($modules) use_git="" From 7fa6e878be86490168c23de7added219e8aa0860 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Tue, 21 May 2019 12:38:04 +0200 Subject: [PATCH 0262/3207] Provide some benchmarks for bitset hybrid union --- src/librustc_data_structures/bit_set.rs | 88 +++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/src/librustc_data_structures/bit_set.rs b/src/librustc_data_structures/bit_set.rs index ec7ff3bd8139..b9842b5b77a8 100644 --- a/src/librustc_data_structures/bit_set.rs +++ b/src/librustc_data_structures/bit_set.rs @@ -5,6 +5,10 @@ use std::iter; use std::marker::PhantomData; use std::mem; use std::slice; +#[cfg(test)] +extern crate test; +#[cfg(test)] +use test::Bencher; pub type Word = u64; pub const WORD_BYTES: usize = mem::size_of::(); @@ -1132,3 +1136,87 @@ fn sparse_matrix_iter() { } assert!(iter.next().is_none()); } + +/// Merge dense hybrid set into empty sparse hybrid set. +#[bench] +fn union_hybrid_sparse_empty_to_dense(b: &mut Bencher) { + let mut pre_dense: HybridBitSet = HybridBitSet::new_empty(256); + for i in 0..10 { + assert!(pre_dense.insert(i)); + } + let pre_sparse: HybridBitSet = HybridBitSet::new_empty(256); + b.iter(|| { + let dense = pre_dense.clone(); + let mut sparse = pre_sparse.clone(); + sparse.union(&dense); + }) +} + +/// Merge dense hybrid set into full hybrid set with same indices. +#[bench] +fn union_hybrid_sparse_full_to_dense(b: &mut Bencher) { + let mut pre_dense: HybridBitSet = HybridBitSet::new_empty(256); + for i in 0..10 { + assert!(pre_dense.insert(i)); + } + let mut pre_sparse: HybridBitSet = HybridBitSet::new_empty(256); + for i in 0..SPARSE_MAX { + assert!(pre_sparse.insert(i)); + } + b.iter(|| { + let dense = pre_dense.clone(); + let mut sparse = pre_sparse.clone(); + sparse.union(&dense); + }) +} + +/// Merge dense hybrid set into full hybrid set with indices over the whole domain. +#[bench] +fn union_hybrid_sparse_domain_to_dense(b: &mut Bencher) { + let mut pre_dense: HybridBitSet = HybridBitSet::new_empty(SPARSE_MAX*64); + for i in 0..10 { + assert!(pre_dense.insert(i)); + } + let mut pre_sparse: HybridBitSet = HybridBitSet::new_empty(SPARSE_MAX*64); + for i in 0..SPARSE_MAX { + assert!(pre_sparse.insert(i*64)); + } + b.iter(|| { + let dense = pre_dense.clone(); + let mut sparse = pre_sparse.clone(); + sparse.union(&dense); + }) +} + +/// Merge dense hybrid set into empty hybrid set where the domain is very small. +#[bench] +fn union_hybrid_sparse_empty_small_domain(b: &mut Bencher) { + let mut pre_dense: HybridBitSet = HybridBitSet::new_empty(SPARSE_MAX); + for i in 0..SPARSE_MAX { + assert!(pre_dense.insert(i)); + } + let pre_sparse: HybridBitSet = HybridBitSet::new_empty(SPARSE_MAX); + b.iter(|| { + let dense = pre_dense.clone(); + let mut sparse = pre_sparse.clone(); + sparse.union(&dense); + }) +} + +/// Merge dense hybrid set into full hybrid set where the domain is very small. +#[bench] +fn union_hybrid_sparse_full_small_domain(b: &mut Bencher) { + let mut pre_dense: HybridBitSet = HybridBitSet::new_empty(SPARSE_MAX); + for i in 0..SPARSE_MAX { + assert!(pre_dense.insert(i)); + } + let mut pre_sparse: HybridBitSet = HybridBitSet::new_empty(SPARSE_MAX); + for i in 0..SPARSE_MAX { + assert!(pre_sparse.insert(i)); + } + b.iter(|| { + let dense = pre_dense.clone(); + let mut sparse = pre_sparse.clone(); + sparse.union(&dense); + }) +} From a31dc8e3b153ac3073f9fb14d8e523a350fe10f2 Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Wed, 22 May 2019 06:49:43 -0700 Subject: [PATCH 0263/3207] Allow null-pointer-optimized enums in FFI if their underlying representation is FFI safe This allows types like Option to be used in FFI without triggering the improper_ctypes lint. This works by changing the is_repr_nullable_ptr function to consider an enum E to be FFI-safe if: - E has no explicit #[repr(...)]. - It only has two variants. - One of those variants is empty (meaning it has no fields). - The other variant has only one field. - That field is one of the following: - &T - &mut T - extern "C" fn - core::num::NonZero* - core::ptr::NonNull - #[repr(transparent)] struct wrapper around one of the types in this list. - The size of E and its field are both known and are both the same size (implying E is participating in the nonnull optimization). --- src/libcore/num/mod.rs | 1 + src/libcore/ptr.rs | 1 + src/librustc_lint/types.rs | 114 +++++++++++------- src/libsyntax/feature_gate.rs | 7 ++ src/libsyntax_pos/symbol.rs | 1 + .../feature-gate-rustc-attrs-1.rs | 1 + .../feature-gate-rustc-attrs-1.stderr | 11 +- src/test/ui/lint/lint-ctypes-enum.rs | 33 ++++- src/test/ui/lint/lint-ctypes-enum.stderr | 42 +++++-- 9 files changed, 159 insertions(+), 52 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 562a7a4b3c71..932c0eaa4c7b 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -50,6 +50,7 @@ assert_eq!(size_of::>(), size_of::<", s #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(1)] + #[cfg_attr(not(stage0), rustc_nonnull_optimization_guaranteed)] pub struct $Ty($Int); } diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 006b1e143eee..4bb4d3ee4666 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2938,6 +2938,7 @@ impl<'a, T: ?Sized> From> for Unique { #[stable(feature = "nonnull", since = "1.25.0")] #[repr(transparent)] #[rustc_layout_scalar_valid_range_start(1)] +#[cfg_attr(not(stage0), rustc_nonnull_optimization_guaranteed)] pub struct NonNull { pointer: *const T, } diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 38b6e2c19793..ac18e131c4a3 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -1,10 +1,11 @@ #![allow(non_snake_case)] use rustc::hir::{ExprKind, Node}; +use crate::hir::def_id::DefId; use rustc::hir::lowering::is_range_literal; use rustc::ty::subst::SubstsRef; use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; -use rustc::ty::layout::{self, IntegerExt, LayoutOf, VariantIdx}; +use rustc::ty::layout::{self, IntegerExt, LayoutOf, VariantIdx, SizeSkeleton}; use rustc::{lint, util}; use rustc_data_structures::indexed_vec::Idx; use util::nodemap::FxHashSet; @@ -14,11 +15,11 @@ use lint::{LintPass, LateLintPass}; use std::cmp; use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64}; -use syntax::{ast, attr}; +use syntax::{ast, attr, source_map}; use syntax::errors::Applicability; +use syntax::symbol::sym; use rustc_target::spec::abi::Abi; use syntax_pos::Span; -use syntax::source_map; use rustc::hir; @@ -522,42 +523,79 @@ enum FfiResult<'tcx> { }, } +fn is_zst<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId, ty: Ty<'tcx>) -> bool { + tcx.layout_of(tcx.param_env(did).and(ty)).map(|layout| layout.is_zst()).unwrap_or(false) +} + +fn ty_is_known_nonnull<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool { + match ty.sty { + ty::FnPtr(_) => true, + ty::Ref(..) => true, + ty::Adt(field_def, substs) if field_def.repr.transparent() && field_def.is_struct() => { + for field in &field_def.non_enum_variant().fields { + let field_ty = tcx.normalize_erasing_regions( + ParamEnv::reveal_all(), + field.ty(tcx, substs), + ); + if is_zst(tcx, field.did, field_ty) { + continue; + } + + let attrs = tcx.get_attrs(field_def.did); + if attrs.iter().any(|a| a.check_name(sym::rustc_nonnull_optimization_guaranteed)) || + ty_is_known_nonnull(tcx, field_ty) { + return true; + } + } + + false + } + _ => false, + } +} + /// Check if this enum can be safely exported based on the /// "nullable pointer optimization". Currently restricted -/// to function pointers and references, but could be -/// expanded to cover NonZero raw pointers and newtypes. +/// to function pointers, references, core::num::NonZero*, +/// core::ptr::NonNull, and #[repr(transparent)] newtypes. /// FIXME: This duplicates code in codegen. fn is_repr_nullable_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def: &'tcx ty::AdtDef, + ty: Ty<'tcx>, + ty_def: &'tcx ty::AdtDef, substs: SubstsRef<'tcx>) -> bool { - if def.variants.len() == 2 { - let data_idx; - - let zero = VariantIdx::new(0); - let one = VariantIdx::new(1); - - if def.variants[zero].fields.is_empty() { - data_idx = one; - } else if def.variants[one].fields.is_empty() { - data_idx = zero; - } else { - return false; - } - - if def.variants[data_idx].fields.len() == 1 { - match def.variants[data_idx].fields[0].ty(tcx, substs).sty { - ty::FnPtr(_) => { - return true; - } - ty::Ref(..) => { - return true; - } - _ => {} - } - } + if ty_def.variants.len() != 2 { + return false; } - false + + let get_variant_fields = |index| &ty_def.variants[VariantIdx::new(index)].fields; + let variant_fields = [get_variant_fields(0), get_variant_fields(1)]; + let fields = if variant_fields[0].is_empty() { + &variant_fields[1] + } else if variant_fields[1].is_empty() { + &variant_fields[0] + } else { + return false; + }; + + if fields.len() != 1 { + return false; + } + + let field_ty = fields[0].ty(tcx, substs); + if !ty_is_known_nonnull(tcx, field_ty) { + return false; + } + + // At this point, the field's type is known to be nonnull and the parent enum is Option-like. + // If the computed size for the field and the enum are different, the nonnull optimization isn't + // being applied (and we've got a problem somewhere). + let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, ParamEnv::reveal_all()).unwrap(); + if !compute_size_skeleton(ty).same_size(compute_size_skeleton(field_ty)) { + bug!("improper_ctypes: Option nonnull optimization not applied?"); + } + + true } impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { @@ -612,14 +650,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ); // repr(transparent) types are allowed to have arbitrary ZSTs, not just // PhantomData -- skip checking all ZST fields - if def.repr.transparent() { - let is_zst = cx - .layout_of(cx.param_env(field.did).and(field_ty)) - .map(|layout| layout.is_zst()) - .unwrap_or(false); - if is_zst { - continue; - } + if def.repr.transparent() && is_zst(cx, field.did, field_ty) { + continue; } let r = self.check_type_for_ffi(cache, field_ty); match r { @@ -682,7 +714,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // discriminant. if !def.repr.c() && def.repr.int.is_none() { // Special-case types like `Option`. - if !is_repr_nullable_ptr(cx, def, substs) { + if !is_repr_nullable_ptr(cx, ty, def, substs) { return FfiUnsafe { ty: ty, reason: "enum has no representation hint", diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 5b1a9bb739ff..b27f5b1495cb 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1134,6 +1134,13 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ is just used to enable niche optimizations in libcore \ and will never be stable", cfg_fn!(rustc_attrs))), + (sym::rustc_nonnull_optimization_guaranteed, Whitelisted, template!(Word), + Gated(Stability::Unstable, + sym::rustc_attrs, + "the `#[rustc_nonnull_optimization_guaranteed]` attribute \ + is just used to enable niche optimizations in libcore \ + and will never be stable", + cfg_fn!(rustc_attrs))), (sym::rustc_regions, Normal, template!(Word), Gated(Stability::Unstable, sym::rustc_attrs, "the `#[rustc_regions]` attribute \ diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 8b07e81e5863..b59244283d73 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -491,6 +491,7 @@ symbols! { rustc_layout_scalar_valid_range_end, rustc_layout_scalar_valid_range_start, rustc_mir, + rustc_nonnull_optimization_guaranteed, rustc_object_lifetime_default, rustc_on_unimplemented, rustc_outlives, diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.rs b/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.rs index f7ff3eb3ac9f..9f5c92349e06 100644 --- a/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.rs +++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.rs @@ -4,5 +4,6 @@ #[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable #[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable +#[rustc_nonnull_optimization_guaranteed] //~ ERROR the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable niche optimizations in libcore and will never be stable fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr b/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr index 882feb87f42e..ed98484e13c4 100644 --- a/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr +++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr @@ -16,6 +16,15 @@ LL | #[rustc_error] = note: for more information, see https://github.com/rust-lang/rust/issues/29642 = help: add #![feature(rustc_attrs)] to the crate attributes to enable -error: aborting due to 2 previous errors +error[E0658]: the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable niche optimizations in libcore and will never be stable + --> $DIR/feature-gate-rustc-attrs-1.rs:7:1 + | +LL | #[rustc_nonnull_optimization_guaranteed] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add #![feature(rustc_attrs)] to the crate attributes to enable + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/lint/lint-ctypes-enum.rs b/src/test/ui/lint/lint-ctypes-enum.rs index f347c2761c32..d3e11d2f7ed6 100644 --- a/src/test/ui/lint/lint-ctypes-enum.rs +++ b/src/test/ui/lint/lint-ctypes-enum.rs @@ -1,6 +1,8 @@ #![deny(improper_ctypes)] #![allow(dead_code)] +use std::num; + enum Z { } enum U { A } enum B { C, D } @@ -15,14 +17,39 @@ enum U8 { A, B, C } #[repr(isize)] enum Isize { A, B, C } +#[repr(transparent)] +struct Transparent(T, std::marker::PhantomData); + +struct Rust(T); + extern { fn zf(x: Z); fn uf(x: U); //~ ERROR enum has no representation hint fn bf(x: B); //~ ERROR enum has no representation hint fn tf(x: T); //~ ERROR enum has no representation hint - fn reprc(x: ReprC); - fn u8(x: U8); - fn isize(x: Isize); + fn repr_c(x: ReprC); + fn repr_u8(x: U8); + fn repr_isize(x: Isize); + fn option_ref(x: Option<&'static u8>); + fn option_fn(x: Option); + fn nonnull(x: Option>); + fn nonzero_u8(x: Option); + fn nonzero_u16(x: Option); + fn nonzero_u32(x: Option); + fn nonzero_u64(x: Option); + fn nonzero_u128(x: Option); + //~^ ERROR 128-bit integers don't currently have a known stable ABI + fn nonzero_usize(x: Option); + fn nonzero_i8(x: Option); + fn nonzero_i16(x: Option); + fn nonzero_i32(x: Option); + fn nonzero_i64(x: Option); + fn nonzero_i128(x: Option); + //~^ ERROR 128-bit integers don't currently have a known stable ABI + fn nonzero_isize(x: Option); + fn repr_transparent(x: Option>); + fn repr_rust(x: Option>); //~ ERROR enum has no representation hint + fn no_result(x: Result<(), num::NonZeroI32>); //~ ERROR enum has no representation hint } pub fn main() { } diff --git a/src/test/ui/lint/lint-ctypes-enum.stderr b/src/test/ui/lint/lint-ctypes-enum.stderr index 92f76cfc38a7..6b807f48aaa8 100644 --- a/src/test/ui/lint/lint-ctypes-enum.stderr +++ b/src/test/ui/lint/lint-ctypes-enum.stderr @@ -1,5 +1,5 @@ error: `extern` block uses type `U` which is not FFI-safe: enum has no representation hint - --> $DIR/lint-ctypes-enum.rs:20:13 + --> $DIR/lint-ctypes-enum.rs:27:13 | LL | fn uf(x: U); | ^ @@ -11,36 +11,64 @@ LL | #![deny(improper_ctypes)] | ^^^^^^^^^^^^^^^ = help: consider adding a #[repr(...)] attribute to this enum note: type defined here - --> $DIR/lint-ctypes-enum.rs:5:1 + --> $DIR/lint-ctypes-enum.rs:7:1 | LL | enum U { A } | ^^^^^^^^^^^^ error: `extern` block uses type `B` which is not FFI-safe: enum has no representation hint - --> $DIR/lint-ctypes-enum.rs:21:13 + --> $DIR/lint-ctypes-enum.rs:28:13 | LL | fn bf(x: B); | ^ | = help: consider adding a #[repr(...)] attribute to this enum note: type defined here - --> $DIR/lint-ctypes-enum.rs:6:1 + --> $DIR/lint-ctypes-enum.rs:8:1 | LL | enum B { C, D } | ^^^^^^^^^^^^^^^ error: `extern` block uses type `T` which is not FFI-safe: enum has no representation hint - --> $DIR/lint-ctypes-enum.rs:22:13 + --> $DIR/lint-ctypes-enum.rs:29:13 | LL | fn tf(x: T); | ^ | = help: consider adding a #[repr(...)] attribute to this enum note: type defined here - --> $DIR/lint-ctypes-enum.rs:7:1 + --> $DIR/lint-ctypes-enum.rs:9:1 | LL | enum T { E, F, G } | ^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: `extern` block uses type `u128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI + --> $DIR/lint-ctypes-enum.rs:40:23 + | +LL | fn nonzero_u128(x: Option); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI + --> $DIR/lint-ctypes-enum.rs:47:23 + | +LL | fn nonzero_i128(x: Option); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `extern` block uses type `std::option::Option>` which is not FFI-safe: enum has no representation hint + --> $DIR/lint-ctypes-enum.rs:51:20 + | +LL | fn repr_rust(x: Option>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a #[repr(...)] attribute to this enum + +error: `extern` block uses type `std::result::Result<(), std::num::NonZeroI32>` which is not FFI-safe: enum has no representation hint + --> $DIR/lint-ctypes-enum.rs:52:20 + | +LL | fn no_result(x: Result<(), num::NonZeroI32>); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a #[repr(...)] attribute to this enum + +error: aborting due to 7 previous errors From e59f0cc0d33f3098a883661227c0c14def403cfd Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 20 May 2019 11:00:34 -0700 Subject: [PATCH 0264/3207] Bump compiler-builtins to 0.1.15 This commit bumps the `compiler-builtins` dependency to 0.1.15 which expects to have the source for `compiler-rt` provided externally if the `c` feature is enabled. This then plumbs through the necessary support in the build system to ensure that if the `llvm-project` directory is checked out and present that we enable the `c` feature of `compiler-builtins` and compile in all the C intrinsics. --- Cargo.lock | 34 +++++++++++++++---------------- src/bootstrap/compile.rs | 29 +++++++++++++++++++++++++- src/build_helper/lib.rs | 6 +++--- src/libprofiler_builtins/build.rs | 4 +--- src/libstd/Cargo.toml | 6 +++--- src/llvm-project | 2 +- 6 files changed, 53 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index db9f0069ced0..b651faac9028 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -25,7 +25,7 @@ dependencies = [ name = "alloc" version = "0.0.0" dependencies = [ - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (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)", @@ -123,7 +123,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.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (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", ] @@ -462,7 +462,7 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", @@ -744,7 +744,7 @@ name = "dlmalloc" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (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", ] @@ -910,7 +910,7 @@ name = "fortanix-sgx-abi" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -1071,7 +1071,7 @@ name = "hashbrown" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-alloc 1.0.0", "rustc-std-workspace-core 1.0.0", ] @@ -1772,7 +1772,7 @@ dependencies = [ name = "panic_abort" version = "0.0.0" dependencies = [ - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (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)", ] @@ -1782,7 +1782,7 @@ name = "panic_unwind" version = "0.0.0" dependencies = [ "alloc 0.0.0", - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (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", @@ -1967,7 +1967,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.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2492,7 +2492,7 @@ name = "rustc-demangle" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-std-workspace-core 1.0.0", ] @@ -2620,7 +2620,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.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2850,7 +2850,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.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -2912,7 +2912,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.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -3029,7 +3029,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.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", ] @@ -3298,7 +3298,7 @@ dependencies = [ "alloc 0.0.0", "backtrace-sys 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (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)", @@ -3889,7 +3889,7 @@ name = "unwind" version = "0.0.0" dependencies = [ "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "compiler_builtins 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "compiler_builtins 0.1.15 (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)", ] @@ -4087,7 +4087,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.14 (registry+https://github.com/rust-lang/crates.io-index)" = "e3f235c329e5cb9fa3d2ca2cc36256ba9a7f23fa76e0f4db6f68c23b73b2ac69" +"checksum compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "e899b947d7e71c3d35c0b6194d64025b84946640510e215090c815b20828964e" "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" diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index e1cdd226fd6e..2da5e1c5902c 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -161,7 +161,33 @@ pub fn std_cargo(builder: &Builder<'_>, cargo.env("MACOSX_DEPLOYMENT_TARGET", target); } + // Determine if we're going to compile in optimized C intrinsics to + // the `compiler-builtins` crate. These intrinsics live in LLVM's + // `compiler-rt` repository, but our `src/llvm-project` submodule isn't + // always checked out, so we need to conditionally look for this. (e.g. if + // an external LLVM is used we skip the LLVM submodule checkout). + // + // Note that this shouldn't affect the correctness of `compiler-builtins`, + // but only its speed. Some intrinsics in C haven't been translated to Rust + // yet but that's pretty rare. Other intrinsics have optimized + // implementations in C which have only had slower versions ported to Rust, + // so we favor the C version where we can, but it's not critical. + // + // If `compiler-rt` is available ensure that the `c` feature of the + // `compiler-builtins` crate is enabled and it's configured to learn where + // `compiler-rt` is located. + let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt"); + let compiler_builtins_c_feature = if compiler_builtins_root.exists() { + cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root); + " compiler-builtins-c".to_string() + } else { + String::new() + }; + if builder.no_std(target) == Some(true) { + let mut features = "compiler-builtins-mem".to_string(); + features.push_str(&compiler_builtins_c_feature); + // for no-std targets we only compile a few no_std crates cargo .args(&["-p", "alloc"]) @@ -170,7 +196,8 @@ pub fn std_cargo(builder: &Builder<'_>, .arg("--features") .arg("compiler-builtins-mem compiler-builtins-c"); } else { - let features = builder.std_features(); + let mut features = builder.std_features(); + features.push_str(&compiler_builtins_c_feature); if compiler.stage != 0 && builder.config.sanitizers { // This variable is used by the sanitizer runtime crates, e.g. diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index 60911d917899..8b00c1d81b08 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -288,9 +288,9 @@ pub fn sanitizer_lib_boilerplate(sanitizer_name: &str) } else { format!("static={}", link_name) }; - // The source for `compiler-rt` comes from the `compiler-builtins` crate, so - // load our env var set by cargo to find the source code. - let dir = env::var_os("DEP_COMPILER_RT_COMPILER_RT").unwrap(); + // This env var is provided by rustbuild to tell us where `compiler-rt` + // lives. + let dir = env::var_os("RUST_COMPILER_RT_ROOT").unwrap(); let lib = native_lib_boilerplate( dir.as_ref(), sanitizer_name, diff --git a/src/libprofiler_builtins/build.rs b/src/libprofiler_builtins/build.rs index 331edb73d6df..491986480deb 100644 --- a/src/libprofiler_builtins/build.rs +++ b/src/libprofiler_builtins/build.rs @@ -57,9 +57,7 @@ fn main() { cfg.define("COMPILER_RT_HAS_ATOMICS", Some("1")); } - // The source for `compiler-rt` comes from the `compiler-builtins` crate, so - // load our env var set by cargo to find the source code. - let root = env::var_os("DEP_COMPILER_RT_COMPILER_RT").unwrap(); + let root = env::var_os("RUST_COMPILER_RT_ROOT").unwrap(); let root = Path::new(&root); for src in profile_sources { diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 55e8b39974e0..c4c1170e539a 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -19,7 +19,7 @@ panic_unwind = { path = "../libpanic_unwind", optional = true } panic_abort = { path = "../libpanic_abort" } core = { path = "../libcore" } libc = { version = "0.2.51", default-features = false, features = ['rustc-dep-of-std'] } -compiler_builtins = { version = "0.1.14" } +compiler_builtins = { version = "0.1.15" } profiler_builtins = { path = "../libprofiler_builtins", optional = true } unwind = { path = "../libunwind" } hashbrown = { version = "0.3.0", features = ['rustc-dep-of-std'] } @@ -49,12 +49,12 @@ fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] } cc = "1.0" [features] -default = ["compiler_builtins_c", "std_detect_file_io", "std_detect_dlsym_getauxval"] +default = ["std_detect_file_io", "std_detect_dlsym_getauxval"] backtrace = ["backtrace-sys"] panic-unwind = ["panic_unwind"] profiler = ["profiler_builtins"] -compiler_builtins_c = ["alloc/compiler-builtins-c"] +compiler-builtins-c = ["alloc/compiler-builtins-c"] llvm-libunwind = ["unwind/llvm-libunwind"] # Make panics and failed asserts immediately abort without formatting any message diff --git a/src/llvm-project b/src/llvm-project index 2c5656ae5938..4efebe31651d 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 2c5656ae593851d0b2336a727cc14b77a06b8ac0 +Subproject commit 4efebe31651d5520bcba968878dbb8a4971d2045 From 194679c9dafa1864aaa979547253adf61d2514cc Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 22 May 2019 08:02:19 -0700 Subject: [PATCH 0265/3207] Disable LLVM/debug assertions in gnu-full-bootstrap This builder already is very close to the 2 hour mark and the debug assertions aren't really buying us anything over what all the other containers are enabling, so let's disable them for this slow builder. --- src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile b/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile index 70390c2ac1df..a157fee16cfd 100644 --- a/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile +++ b/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile @@ -20,3 +20,9 @@ ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ --enable-full-bootstrap ENV SCRIPT python2.7 ../x.py build + +# In general this just slows down the build and we're just a smoke test that +# a full bootstrap works in general, so there's not much need to take this +# penalty in build times. +ENV NO_LLVM_ASSERTIONS 1 +ENV NO_DEBUG_ASSERTIONS 1 From 3f2dd24adcb2d432e3950077e1bb5ab855baf5a4 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Wed, 22 May 2019 10:29:36 -0500 Subject: [PATCH 0266/3207] these errors can happen after all --- src/libsyntax/ext/tt/transcribe.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index e3586c1854c1..e6b49e61937d 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -170,9 +170,11 @@ pub fn transcribe( } LockstepIterSize::Contradiction(ref msg) => { - // This should never happen because the macro parser should generate - // properly-sized matches for all meta-vars. - cx.span_bug(seq.span(), &msg[..]); + // FIXME: this really ought to be caught at macro definition time... It + // happens when two meta-variables are used in the same repetition in a + // sequence, but they come from different sequence matchers and repeat + // different amounts. + cx.span_fatal(seq.span(), &msg[..]); } LockstepIterSize::Constraint(len, _) => { @@ -187,9 +189,10 @@ pub fn transcribe( // Is the repetition empty? if len == 0 { if seq.op == quoted::KleeneOp::OneOrMore { - // This should be impossible because the macro parser would not - // match the given macro arm. - cx.span_bug(sp.entire(), "this must repeat at least once"); + // FIXME: this really ought to be caught at macro definition + // time... It happens when the Kleene operator in the matcher and + // the body for the same meta-variable do not match. + cx.span_fatal(sp.entire(), "this must repeat at least once"); } } else { // 0 is the initial counter (we have done 0 repretitions so far). `len` @@ -327,8 +330,7 @@ impl LockstepIterSize { LockstepIterSize::Constraint(r_len, _) if l_len == r_len => self, LockstepIterSize::Constraint(r_len, r_id) => { let msg = format!( - "inconsistent lockstep iteration: \ - '{}' has {} items, but '{}' has {}", + "meta-variable `{}` repeats {} times, but `{}` repeats {} times", l_id, l_len, r_id, r_len ); LockstepIterSize::Contradiction(msg) From 8877f4c30daf3ceabe42037c86d3df05baa7d721 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Tue, 21 May 2019 09:42:49 +0200 Subject: [PATCH 0267/3207] Improve union of sparse and dense hybrid set This optimization speeds up the union of a hybrid bitset when that switches it from a sparse representation to a dense bitset. It now clones the dense bitset and integrate only the spare elements instead of densifying the sparse bitset, initializing all elements, and then a union on two dense bitset, touching all words a second time. --- src/librustc_data_structures/bit_set.rs | 49 +++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/src/librustc_data_structures/bit_set.rs b/src/librustc_data_structures/bit_set.rs index b9842b5b77a8..08b7185dbe21 100644 --- a/src/librustc_data_structures/bit_set.rs +++ b/src/librustc_data_structures/bit_set.rs @@ -181,6 +181,45 @@ impl BitSet { // Note: we currently don't bother trying to make a Sparse set. HybridBitSet::Dense(self.to_owned()) } + + /// Set `self = self | other`. In contrast to `union` returns `true` if the set contains at + /// least one bit that is not in `other` (i.e. `other` is not a superset of `self`). + /// + /// This is an optimization for union of a hybrid bitset. + fn reverse_union_sparse(&mut self, sparse: &SparseBitSet) -> bool { + assert!(sparse.domain_size == self.domain_size); + self.clear_excess_bits(); + + let mut not_already = false; + // Index of the current word not yet merged. + let mut current_index = 0; + // Mask of bits that came from the sparse set in the current word. + let mut new_bit_mask = 0; + for (word_index, mask) in sparse.iter().map(|x| word_index_and_mask(*x)) { + // Next bit is in a word not inspected yet. + if word_index > current_index { + self.words[current_index] |= new_bit_mask; + // Were there any bits in the old word that did not occur in the sparse set? + not_already |= (self.words[current_index] ^ new_bit_mask) != 0; + // Check all words we skipped for any set bit. + not_already |= self.words[current_index+1..word_index].iter().any(|&x| x != 0); + // Update next word. + current_index = word_index; + // Reset bit mask, no bits have been merged yet. + new_bit_mask = 0; + } + // Add bit and mark it as coming from the sparse set. + // self.words[word_index] |= mask; + new_bit_mask |= mask; + } + self.words[current_index] |= new_bit_mask; + // Any bits in the last inspected word that were not in the sparse set? + not_already |= (self.words[current_index] ^ new_bit_mask) != 0; + // Any bits in the tail? Note `clear_excess_bits` before. + not_already |= self.words[current_index+1..].iter().any(|&x| x != 0); + + not_already + } } /// This is implemented by all the bitsets so that BitSet::union() can be @@ -518,10 +557,12 @@ impl HybridBitSet { changed } HybridBitSet::Dense(other_dense) => { - // `self` is sparse and `other` is dense. Densify - // `self` and then do the bitwise union. - let mut new_dense = self_sparse.to_dense(); - let changed = new_dense.union(other_dense); + // `self` is sparse and `other` is dense. Clone the + // other set and do the bitwise union with sparse + // `self`. This avoids traversing the dense + // representation twice. + let mut new_dense = other_dense.clone(); + let changed = new_dense.reverse_union_sparse(self_sparse); *self = HybridBitSet::Dense(new_dense); changed } From 24f262f35e5a36a29f7f2f7ee3e128b489666871 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 22 May 2019 18:10:05 +0200 Subject: [PATCH 0268/3207] ci: toggle builders --- .azure-pipelines/auto.yml | 516 +++++++++++++++++++------------------- .azure-pipelines/try.yml | 267 +------------------- 2 files changed, 259 insertions(+), 524 deletions(-) diff --git a/.azure-pipelines/auto.yml b/.azure-pipelines/auto.yml index 3b6cfed70719..800cbb5a3aee 100644 --- a/.azure-pipelines/auto.yml +++ b/.azure-pipelines/auto.yml @@ -32,120 +32,120 @@ jobs: IMAGE: dist-x86_64-linux DEPLOY_ALT: 1 -# # Linux builders, remaining docker images -# arm-android: -# IMAGE: arm-android -# -# armhf-gnu: -# IMAGE: armhf-gnu -# -# dist-various-1: -# IMAGE: dist-various-1 -# DEPLOY: 1 -# -# dist-various-2: -# IMAGE: dist-various-2 -# DEPLOY: 1 -# -# dist-aarch64-linux: -# IMAGE: dist-aarch64-linux -# DEPLOY: 1 -# -# dist-android: -# IMAGE: dist-android -# DEPLOY: 1 -# -# dist-arm-linux: -# IMAGE: dist-arm-linux -# DEPLOY: 1 -# -# dist-armhf-linux: -# IMAGE: dist-armhf-linux -# DEPLOY: 1 -# -# dist-armv7-linux: -# IMAGE: dist-armv7-linux -# DEPLOY: 1 -# -# dist-i586-gnu-i586-i686-musl: -# IMAGE: dist-i586-gnu-i586-i686-musl -# DEPLOY: 1 -# -# dist-i686-freebsd: -# IMAGE: dist-i686-freebsd -# DEPLOY: 1 -# -# dist-i686-linux: -# IMAGE: dist-i686-linux -# DEPLOY: 1 -# -# dist-mips-linux: -# IMAGE: dist-mips-linux -# DEPLOY: 1 -# -# dist-mips64-linux: -# IMAGE: dist-mips64-linux -# DEPLOY: 1 -# -# dist-mips64el-linux: -# IMAGE: dist-mips64el-linux -# DEPLOY: 1 -# -# dist-mipsel-linux: -# IMAGE: dist-mipsel-linux -# DEPLOY: 1 -# -# dist-powerpc-linux: -# IMAGE: dist-powerpc-linux -# DEPLOY: 1 -# -# dist-powerpc64-linux: -# IMAGE: dist-powerpc64-linux -# DEPLOY: 1 -# -# dist-powerpc64le-linux: -# IMAGE: dist-powerpc64le-linux -# DEPLOY: 1 -# -# dist-s390x-linux: -# IMAGE: dist-s390x-linux -# DEPLOY: 1 -# -# dist-x86_64-freebsd: -# IMAGE: dist-x86_64-freebsd -# DEPLOY: 1 -# -# dist-x86_64-musl: -# IMAGE: dist-x86_64-musl -# DEPLOY: 1 -# -# dist-x86_64-netbsd: -# IMAGE: dist-x86_64-netbsd -# DEPLOY: 1 -# -# asmjs: -# IMAGE: asmjs -# i686-gnu: -# IMAGE: i686-gnu -# i686-gnu-nopt: -# IMAGE: i686-gnu-nopt -# test-various: -# IMAGE: test-various -# x86_64-gnu: -# IMAGE: x86_64-gnu -# x86_64-gnu-full-bootstrap: -# IMAGE: x86_64-gnu-full-bootstrap -# x86_64-gnu-aux: -# IMAGE: x86_64-gnu-aux -# x86_64-gnu-tools: -# IMAGE: x86_64-gnu-tools -# # FIXME if: branch = auto OR (type = pull_request AND commit_message =~ /(?i:^update.*\b(rls|rustfmt|clippy|miri|cargo)\b)/) -# x86_64-gnu-debug: -# IMAGE: x86_64-gnu-debug -# x86_64-gnu-nopt: -# IMAGE: x86_64-gnu-nopt -# x86_64-gnu-distcheck: -# IMAGE: x86_64-gnu-distcheck + # Linux builders, remaining docker images + arm-android: + IMAGE: arm-android + + armhf-gnu: + IMAGE: armhf-gnu + + dist-various-1: + IMAGE: dist-various-1 + DEPLOY: 1 + + dist-various-2: + IMAGE: dist-various-2 + DEPLOY: 1 + + dist-aarch64-linux: + IMAGE: dist-aarch64-linux + DEPLOY: 1 + + dist-android: + IMAGE: dist-android + DEPLOY: 1 + + dist-arm-linux: + IMAGE: dist-arm-linux + DEPLOY: 1 + + dist-armhf-linux: + IMAGE: dist-armhf-linux + DEPLOY: 1 + + dist-armv7-linux: + IMAGE: dist-armv7-linux + DEPLOY: 1 + + dist-i586-gnu-i586-i686-musl: + IMAGE: dist-i586-gnu-i586-i686-musl + DEPLOY: 1 + + dist-i686-freebsd: + IMAGE: dist-i686-freebsd + DEPLOY: 1 + + dist-i686-linux: + IMAGE: dist-i686-linux + DEPLOY: 1 + + dist-mips-linux: + IMAGE: dist-mips-linux + DEPLOY: 1 + + dist-mips64-linux: + IMAGE: dist-mips64-linux + DEPLOY: 1 + + dist-mips64el-linux: + IMAGE: dist-mips64el-linux + DEPLOY: 1 + + dist-mipsel-linux: + IMAGE: dist-mipsel-linux + DEPLOY: 1 + + dist-powerpc-linux: + IMAGE: dist-powerpc-linux + DEPLOY: 1 + + dist-powerpc64-linux: + IMAGE: dist-powerpc64-linux + DEPLOY: 1 + + dist-powerpc64le-linux: + IMAGE: dist-powerpc64le-linux + DEPLOY: 1 + + dist-s390x-linux: + IMAGE: dist-s390x-linux + DEPLOY: 1 + + dist-x86_64-freebsd: + IMAGE: dist-x86_64-freebsd + DEPLOY: 1 + + dist-x86_64-musl: + IMAGE: dist-x86_64-musl + DEPLOY: 1 + + dist-x86_64-netbsd: + IMAGE: dist-x86_64-netbsd + DEPLOY: 1 + + asmjs: + IMAGE: asmjs + i686-gnu: + IMAGE: i686-gnu + i686-gnu-nopt: + IMAGE: i686-gnu-nopt + test-various: + IMAGE: test-various + x86_64-gnu: + IMAGE: x86_64-gnu + x86_64-gnu-full-bootstrap: + IMAGE: x86_64-gnu-full-bootstrap + x86_64-gnu-aux: + IMAGE: x86_64-gnu-aux + x86_64-gnu-tools: + IMAGE: x86_64-gnu-tools + # FIXME if: branch = auto OR (type = pull_request AND commit_message =~ /(?i:^update.*\b(rls|rustfmt|clippy|miri|cargo)\b)/) + x86_64-gnu-debug: + IMAGE: x86_64-gnu-debug + x86_64-gnu-nopt: + IMAGE: x86_64-gnu-nopt + x86_64-gnu-distcheck: + IMAGE: x86_64-gnu-distcheck mingw-check: IMAGE: mingw-check @@ -183,33 +183,33 @@ jobs: NO_DEBUG_ASSERTIONS: 1 DIST_REQUIRE_ALL_TOOLS: 1 -# dist-x86_64-apple-alt: -# RUST_CHECK_TARGET: dist -# RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --enable-lldb --set rust.jemalloc -# DEPLOY_ALT: 1 -# RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 -# MACOSX_DEPLOYMENT_TARGET: 10.7 -# NO_LLVM_ASSERTIONS: 1 -# NO_DEBUG_ASSERTIONS: 1 -# -# i686-apple: -# RUST_CHECK_TARGET: check -# RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --set rust.jemalloc -# RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 -# MACOSX_DEPLOYMENT_TARGET: 10.8 -# MACOSX_STD_DEPLOYMENT_TARGET: 10.7 -# NO_LLVM_ASSERTIONS: 1 -# NO_DEBUG_ASSERTIONS: 1 -# -# dist-i686-apple: -# RUST_CHECK_TARGET: dist -# RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb --set rust.jemalloc -# DEPLOY: 1 -# RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 -# MACOSX_DEPLOYMENT_TARGET: 10.7 -# NO_LLVM_ASSERTIONS: 1 -# NO_DEBUG_ASSERTIONS: 1 -# DIST_REQUIRE_ALL_TOOLS: 1 + dist-x86_64-apple-alt: + RUST_CHECK_TARGET: dist + RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --enable-lldb --set rust.jemalloc + DEPLOY_ALT: 1 + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + + i686-apple: + RUST_CHECK_TARGET: check + RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --set rust.jemalloc + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.8 + MACOSX_STD_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + + dist-i686-apple: + RUST_CHECK_TARGET: dist + RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb --set rust.jemalloc + DEPLOY: 1 + RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 + MACOSX_DEPLOYMENT_TARGET: 10.7 + NO_LLVM_ASSERTIONS: 1 + NO_DEBUG_ASSERTIONS: 1 + DIST_REQUIRE_ALL_TOOLS: 1 @@ -220,89 +220,89 @@ jobs: - template: steps/run.yml strategy: matrix: -# # 32/64 bit MSVC tests -# x86_64-msvc-1: -# MSYS_BITS: 64 -# RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler -# SCRIPT: make ci-subset-1 -# # FIXME(#59637) -# NO_DEBUG_ASSERTIONS: 1 -# NO_LLVM_ASSERTIONS: 1 -# x86_64-msvc-2: -# MSYS_BITS: 64 -# RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler -# SCRIPT: make ci-subset-2 -# i686-msvc-1: -# MSYS_BITS: 32 -# RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc -# SCRIPT: make ci-subset-1 -# i686-msvc-2: -# MSYS_BITS: 32 -# RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc -# SCRIPT: make ci-subset-2 -# # MSVC aux tests -# x86_64-msvc-aux: -# MSYS_BITS: 64 -# RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1 -# RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc -# x86_64-msvc-cargo: -# MSYS_BITS: 64 -# SCRIPT: python x.py test src/tools/cargotest src/tools/cargo -# RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc -# VCVARS_BAT: vcvars64.bat -# # MSVC tools tests -# x86_64-msvc-tools: -# MSYS_BITS: 64 -# SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows -# RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri -# -# # 32/64-bit MinGW builds. -# # -# # We are using MinGW with posix threads since LLVM does not compile with -# # the win32 threads version due to missing support for C++'s std::thread. -# # -# # Instead of relying on the MinGW version installed on appveryor we download -# # and install one ourselves so we won't be surprised by changes to appveyor's -# # build image. -# # -# # Finally, note that the downloads below are all in the `rust-lang-ci` S3 -# # bucket, but they cleraly didn't originate there! The downloads originally -# # came from the mingw-w64 SourceForge download site. Unfortunately -# # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. -# i686-mingw-1: -# MSYS_BITS: 32 -# RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu -# SCRIPT: make ci-subset-1 -# MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror -# MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z -# MINGW_DIR: mingw32 -# # FIXME(#59637) -# NO_DEBUG_ASSERTIONS: 1 -# NO_LLVM_ASSERTIONS: 1 -# i686-mingw-2: -# MSYS_BITS: 32 -# RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu -# SCRIPT: make ci-subset-2 -# MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror -# MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z -# MINGW_DIR: mingw32 -# x86_64-mingw-1: -# MSYS_BITS: 64 -# SCRIPT: make ci-subset-1 -# RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu -# MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror -# MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z -# MINGW_DIR: mingw64 -# # FIXME(#59637) -# NO_DEBUG_ASSERTIONS: 1 -# NO_LLVM_ASSERTIONS: 1 -# x86_64-mingw-2: -# MSYS_BITS: 64 -# SCRIPT: make ci-subset-2 -# RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu -# MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror -# MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z -# MINGW_DIR: mingw64 + # 32/64 bit MSVC tests + x86_64-msvc-1: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + SCRIPT: make ci-subset-1 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + x86_64-msvc-2: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + SCRIPT: make ci-subset-2 + i686-msvc-1: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc + SCRIPT: make ci-subset-1 + i686-msvc-2: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc + SCRIPT: make ci-subset-2 + # MSVC aux tests + x86_64-msvc-aux: + MSYS_BITS: 64 + RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + x86_64-msvc-cargo: + MSYS_BITS: 64 + SCRIPT: python x.py test src/tools/cargotest src/tools/cargo + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc + VCVARS_BAT: vcvars64.bat + # MSVC tools tests + x86_64-msvc-tools: + MSYS_BITS: 64 + SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri + + # 32/64-bit MinGW builds. + # + # We are using MinGW with posix threads since LLVM does not compile with + # the win32 threads version due to missing support for C++'s std::thread. + # + # Instead of relying on the MinGW version installed on appveryor we download + # and install one ourselves so we won't be surprised by changes to appveyor's + # build image. + # + # Finally, note that the downloads below are all in the `rust-lang-ci` S3 + # bucket, but they cleraly didn't originate there! The downloads originally + # came from the mingw-w64 SourceForge download site. Unfortunately + # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. + i686-mingw-1: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + SCRIPT: make ci-subset-1 + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z + MINGW_DIR: mingw32 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + i686-mingw-2: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu + SCRIPT: make ci-subset-2 + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z + MINGW_DIR: mingw32 + x86_64-mingw-1: + MSYS_BITS: 64 + SCRIPT: make ci-subset-1 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z + MINGW_DIR: mingw64 + # FIXME(#59637) + NO_DEBUG_ASSERTIONS: 1 + NO_LLVM_ASSERTIONS: 1 + x86_64-mingw-2: + MSYS_BITS: 64 + SCRIPT: make ci-subset-2 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z + MINGW_DIR: mingw64 # 32/64 bit MSVC and GNU deployment dist-x86_64-msvc: @@ -314,37 +314,37 @@ jobs: SCRIPT: python x.py dist DIST_REQUIRE_ALL_TOOLS: 1 DEPLOY: 1 -# dist-i686-msvc: -# RUST_CONFIGURE_ARGS: > -# --build=i686-pc-windows-msvc -# --target=i586-pc-windows-msvc -# --enable-full-tools -# --enable-profiler -# SCRIPT: python x.py dist -# DIST_REQUIRE_ALL_TOOLS: 1 -# DEPLOY: 1 -# dist-i686-mingw: -# MSYS_BITS: 32 -# RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools -# SCRIPT: python x.py dist -# MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror -# MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z -# MINGW_DIR: mingw32 -# DIST_REQUIRE_ALL_TOOLS: 1 -# DEPLOY: 1 -# dist-x86_64-mingw: -# MSYS_BITS: 64 -# SCRIPT: python x.py dist -# RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools -# MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror -# MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z -# MINGW_DIR: mingw64 -# DIST_REQUIRE_ALL_TOOLS: 1 -# DEPLOY: 1 -# -# # "alternate" deployment, see .travis.yml for more info -# dist-x86_64-msvc-alt: -# MSYS_BITS: 64 -# RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler -# SCRIPT: python x.py dist -# DEPLOY_ALT: 1 + dist-i686-msvc: + RUST_CONFIGURE_ARGS: > + --build=i686-pc-windows-msvc + --target=i586-pc-windows-msvc + --enable-full-tools + --enable-profiler + SCRIPT: python x.py dist + DIST_REQUIRE_ALL_TOOLS: 1 + DEPLOY: 1 + dist-i686-mingw: + MSYS_BITS: 32 + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools + SCRIPT: python x.py dist + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z + MINGW_DIR: mingw32 + DIST_REQUIRE_ALL_TOOLS: 1 + DEPLOY: 1 + dist-x86_64-mingw: + MSYS_BITS: 64 + SCRIPT: python x.py dist + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools + MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror + MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z + MINGW_DIR: mingw64 + DIST_REQUIRE_ALL_TOOLS: 1 + DEPLOY: 1 + + # "alternate" deployment, see .travis.yml for more info + dist-x86_64-msvc-alt: + MSYS_BITS: 64 + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler + SCRIPT: python x.py dist + DEPLOY_ALT: 1 diff --git a/.azure-pipelines/try.yml b/.azure-pipelines/try.yml index 5c76d2053345..f37bb7d26ed6 100644 --- a/.azure-pipelines/try.yml +++ b/.azure-pipelines/try.yml @@ -18,132 +18,14 @@ jobs: - template: steps/run.yml strategy: matrix: - x86_64-gnu-llvm-6.0: - IMAGE: x86_64-gnu-llvm-6.0 - RUST_BACKTRACE: 1 - dist-x86_64-linux: IMAGE: dist-x86_64-linux DEPLOY: 1 + dist-x86_64-linux-alt: IMAGE: dist-x86_64-linux DEPLOY_ALT: 1 - arm-android: - IMAGE: arm-android - - armhf-gnu: - IMAGE: armhf-gnu - - dist-various-1: - IMAGE: dist-various-1 - DEPLOY: 1 - - dist-various-2: - IMAGE: dist-various-2 - DEPLOY: 1 - - dist-aarch64-linux: - IMAGE: dist-aarch64-linux - DEPLOY: 1 - - dist-android: - IMAGE: dist-android - DEPLOY: 1 - - dist-arm-linux: - IMAGE: dist-arm-linux - DEPLOY: 1 - - dist-armhf-linux: - IMAGE: dist-armhf-linux - DEPLOY: 1 - - dist-armv7-linux: - IMAGE: dist-armv7-linux - DEPLOY: 1 - - dist-i586-gnu-i586-i686-musl: - IMAGE: dist-i586-gnu-i586-i686-musl - DEPLOY: 1 - - dist-i686-freebsd: - IMAGE: dist-i686-freebsd - DEPLOY: 1 - - dist-i686-linux: - IMAGE: dist-i686-linux - DEPLOY: 1 - - dist-mips-linux: - IMAGE: dist-mips-linux - DEPLOY: 1 - - dist-mips64-linux: - IMAGE: dist-mips64-linux - DEPLOY: 1 - - dist-mips64el-linux: - IMAGE: dist-mips64el-linux - DEPLOY: 1 - - dist-mipsel-linux: - IMAGE: dist-mipsel-linux - DEPLOY: 1 - - dist-powerpc-linux: - IMAGE: dist-powerpc-linux - DEPLOY: 1 - - dist-powerpc64-linux: - IMAGE: dist-powerpc64-linux - DEPLOY: 1 - - dist-powerpc64le-linux: - IMAGE: dist-powerpc64le-linux - DEPLOY: 1 - - dist-s390x-linux: - IMAGE: dist-s390x-linux - DEPLOY: 1 - - dist-x86_64-freebsd: - IMAGE: dist-x86_64-freebsd - DEPLOY: 1 - - dist-x86_64-musl: - IMAGE: dist-x86_64-musl - DEPLOY: 1 - - dist-x86_64-netbsd: - IMAGE: dist-x86_64-netbsd - DEPLOY: 1 - - asmjs: - IMAGE: asmjs - i686-gnu: - IMAGE: i686-gnu - i686-gnu-nopt: - IMAGE: i686-gnu-nopt - test-various: - IMAGE: test-various - x86_64-gnu: - IMAGE: x86_64-gnu - x86_64-gnu-full-bootstrap: - IMAGE: x86_64-gnu-full-bootstrap - x86_64-gnu-aux: - IMAGE: x86_64-gnu-aux - x86_64-gnu-tools: - IMAGE: x86_64-gnu-tools - x86_64-gnu-debug: - IMAGE: x86_64-gnu-debug - x86_64-gnu-nopt: - IMAGE: x86_64-gnu-nopt - x86_64-gnu-distcheck: - IMAGE: x86_64-gnu-distcheck - mingw-check: - IMAGE: mingw-check - - job: macOS timeoutInMinutes: 600 pool: @@ -152,21 +34,6 @@ jobs: - template: steps/run.yml strategy: matrix: - # OSX builders running tests, these run the full test suite. - # NO_DEBUG_ASSERTIONS=1 to make them go faster, but also do have some - # runners that run `//ignore-debug` tests. - # - # Note that the compiler is compiled to target 10.8 here because the Xcode - # version that we're using, 8.2, cannot compile LLVM for OSX 10.7. - x86_64-apple: - RUST_CHECK_TARGET: check - RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.8 - MACOSX_STD_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - dist-x86_64-apple: RUST_CHECK_TARGET: dist RUST_CONFIGURE_ARGS: --target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --enable-lldb --set rust.jemalloc @@ -186,25 +53,6 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 - i686-apple: - RUST_CHECK_TARGET: check - RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --set rust.jemalloc - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.8 - MACOSX_STD_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - - dist-i686-apple: - RUST_CHECK_TARGET: dist - RUST_CONFIGURE_ARGS: --build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb --set rust.jemalloc - DEPLOY: 1 - RUSTC_RETRY_LINKER_ON_SEGFAULT: 1 - MACOSX_DEPLOYMENT_TARGET: 10.7 - NO_LLVM_ASSERTIONS: 1 - NO_DEBUG_ASSERTIONS: 1 - DIST_REQUIRE_ALL_TOOLS: 1 - - job: Windows timeoutInMinutes: 600 pool: @@ -213,91 +61,6 @@ jobs: - template: steps/run.yml strategy: matrix: - # 32/64 bit MSVC tests - x86_64-msvc-1: - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler - SCRIPT: make ci-subset-1 - # FIXME(#59637) - NO_DEBUG_ASSERTIONS: 1 - NO_LLVM_ASSERTIONS: 1 - x86_64-msvc-2: - MSYS_BITS: 64 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler - SCRIPT: make ci-subset-2 - i686-msvc-1: - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc - SCRIPT: make ci-subset-1 - i686-msvc-2: - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc - SCRIPT: make ci-subset-2 - # MSVC aux tests - x86_64-msvc-aux: - MSYS_BITS: 64 - RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc - x86_64-msvc-cargo: - MSYS_BITS: 64 - SCRIPT: python x.py test src/tools/cargotest src/tools/cargo - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc - VCVARS_BAT: vcvars64.bat - # MSVC tools tests - x86_64-msvc-tools: - MSYS_BITS: 64 - SCRIPT: src/ci/docker/x86_64-gnu-tools/checktools.sh x.py /tmp/toolstates.json windows - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --save-toolstates=/tmp/toolstates.json --enable-test-miri - - # 32/64-bit MinGW builds. - # - # We are using MinGW with posix threads since LLVM does not compile with - # the win32 threads version due to missing support for C++'s std::thread. - # - # Instead of relying on the MinGW version installed on appveryor we download - # and install one ourselves so we won't be surprised by changes to appveyor's - # build image. - # - # Finally, note that the downloads below are all in the `rust-lang-ci` S3 - # bucket, but they cleraly didn't originate there! The downloads originally - # came from the mingw-w64 SourceForge download site. Unfortunately - # SourceForge is notoriously flaky, so we mirror it on our own infrastructure. - i686-mingw-1: - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - SCRIPT: make ci-subset-1 - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z - MINGW_DIR: mingw32 - # FIXME(#59637) - NO_DEBUG_ASSERTIONS: 1 - NO_LLVM_ASSERTIONS: 1 - i686-mingw-2: - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu - SCRIPT: make ci-subset-2 - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z - MINGW_DIR: mingw32 - x86_64-mingw-1: - MSYS_BITS: 64 - SCRIPT: make ci-subset-1 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z - MINGW_DIR: mingw64 - # FIXME(#59637) - NO_DEBUG_ASSERTIONS: 1 - NO_LLVM_ASSERTIONS: 1 - x86_64-mingw-2: - MSYS_BITS: 64 - SCRIPT: make ci-subset-2 - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z - MINGW_DIR: mingw64 - - # 32/64 bit MSVC and GNU deployment dist-x86_64-msvc: RUST_CONFIGURE_ARGS: > --build=x86_64-pc-windows-msvc @@ -307,35 +70,7 @@ jobs: SCRIPT: python x.py dist DIST_REQUIRE_ALL_TOOLS: 1 DEPLOY: 1 - dist-i686-msvc: - RUST_CONFIGURE_ARGS: > - --build=i686-pc-windows-msvc - --target=i586-pc-windows-msvc - --enable-full-tools - --enable-profiler - SCRIPT: python x.py dist - DIST_REQUIRE_ALL_TOOLS: 1 - DEPLOY: 1 - dist-i686-mingw: - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools - SCRIPT: python x.py dist - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z - MINGW_DIR: mingw32 - DIST_REQUIRE_ALL_TOOLS: 1 - DEPLOY: 1 - dist-x86_64-mingw: - MSYS_BITS: 64 - SCRIPT: python x.py dist - RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools - MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror - MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z - MINGW_DIR: mingw64 - DIST_REQUIRE_ALL_TOOLS: 1 - DEPLOY: 1 - # "alternate" deployment, see .travis.yml for more info dist-x86_64-msvc-alt: MSYS_BITS: 64 RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler From dc82626262605665bbcea8f24925442e48dc897c Mon Sep 17 00:00:00 2001 From: "@amit.chandra" <@amit.chandra> Date: Fri, 26 Apr 2019 19:53:18 +0530 Subject: [PATCH 0269/3207] wip nth_back on chunks Signed-off-by: wizAmit --- src/libcore/slice/mod.rs | 16 ++++++++++++++++ src/libcore/tests/slice.rs | 13 +++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index d06d107d32a4..54c5285bc495 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4178,6 +4178,22 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { Some(snd) } } + + #[inline] + fn nth_back(&mut self, n: usize) { + let (end, overflow) = self.v.len().overflowing_sub(n); + if end < self.v.len() || overflow { + self.v = &[]; + None + } else { + let start = match end.checked_sub(self.chunk_size) { + Some(sum) => cmp::min(self.v.len(), sum), + None => self.v.len(), + }; + let nth = &self.v[start..end]; + self.v = &self.v[end..]; + } + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index acf6b03791f0..0233b96d3a72 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -134,6 +134,19 @@ fn test_chunks_nth() { assert_eq!(c2.next(), None); } +#[test] +fn test_chunks_nth_back() { + let v: &[i32] = &[0, 1, 2, 3, 4, 5]; + let mut c = v.chunks(2); + assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); + assert_eq!(c.next().unwrap(), &[4, 5]); + + let v2: &[i32] = &[0, 1, 2, 3, 4]; + let mut c2 = v2.chunks(3); + assert_eq!(c2.nth_back(1).unwrap(), &[0, 1]); + assert_eq!(c2.next(), None); +} + #[test] fn test_chunks_last() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; From 2080b86566358dad8cb8c967e321a172a69c49f7 Mon Sep 17 00:00:00 2001 From: "@amit.chandra" <@amit.chandra> Date: Wed, 1 May 2019 23:34:07 +0530 Subject: [PATCH 0270/3207] hopefully working nth_back on chunks Signed-off-by: wizAmit --- src/libcore/slice/mod.rs | 17 +++++++++-------- src/libcore/tests/slice.rs | 9 ++++++++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 54c5285bc495..b138ae3449f8 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4180,18 +4180,19 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { } #[inline] - fn nth_back(&mut self, n: usize) { - let (end, overflow) = self.v.len().overflowing_sub(n); - if end < self.v.len() || overflow { - self.v = &[]; + fn nth_back(&mut self, n: usize) -> Option { + let (end, overflow) = self.v.len().overflowing_sub(n * self.chunk_size); + if overflow { + self.v = &mut []; None } else { let start = match end.checked_sub(self.chunk_size) { - Some(sum) => cmp::min(self.v.len(), sum), - None => self.v.len(), + Some(res) => cmp::min(self.v.len(), res), + None => 0, }; - let nth = &self.v[start..end]; - self.v = &self.v[end..]; + let nth_back = &self.v[start..end]; + self.v = &self.v[..start]; + Some(nth_back) } } } diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 0233b96d3a72..edea405fad79 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -139,12 +139,19 @@ fn test_chunks_nth_back() { let v: &[i32] = &[0, 1, 2, 3, 4, 5]; let mut c = v.chunks(2); assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); - assert_eq!(c.next().unwrap(), &[4, 5]); + assert_eq!(c.next().unwrap(), &[0, 1]); + assert_eq!(c.next(), None); let v2: &[i32] = &[0, 1, 2, 3, 4]; let mut c2 = v2.chunks(3); assert_eq!(c2.nth_back(1).unwrap(), &[0, 1]); assert_eq!(c2.next(), None); + assert_eq!(c2.next_back(), None); + + let v3: &[i32] = &[0, 1, 2, 3, 4]; + let mut c3 = v3.chunks(10); + assert_eq!(c3.nth_back(0).unwrap(), &[0, 1, 2, 3, 4]); + assert_eq!(c3.next(), None); } #[test] From 29a103daa92bb3607fd4cd34169d4ff6170987fa Mon Sep 17 00:00:00 2001 From: "@amit.chandra" <@amit.chandra> Date: Fri, 26 Apr 2019 19:53:18 +0530 Subject: [PATCH 0271/3207] wip nth_back on chunks Signed-off-by: wizAmit --- src/libcore/slice/mod.rs | 17 ----------------- src/libcore/tests/slice.rs | 19 ------------------- 2 files changed, 36 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index b138ae3449f8..d06d107d32a4 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -4178,23 +4178,6 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { Some(snd) } } - - #[inline] - fn nth_back(&mut self, n: usize) -> Option { - let (end, overflow) = self.v.len().overflowing_sub(n * self.chunk_size); - if overflow { - self.v = &mut []; - None - } else { - let start = match end.checked_sub(self.chunk_size) { - Some(res) => cmp::min(self.v.len(), res), - None => 0, - }; - let nth_back = &self.v[start..end]; - self.v = &self.v[..start]; - Some(nth_back) - } - } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index edea405fad79..1cba4b38382a 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -134,25 +134,6 @@ fn test_chunks_nth() { assert_eq!(c2.next(), None); } -#[test] -fn test_chunks_nth_back() { - let v: &[i32] = &[0, 1, 2, 3, 4, 5]; - let mut c = v.chunks(2); - assert_eq!(c.nth_back(1).unwrap(), &[2, 3]); - assert_eq!(c.next().unwrap(), &[0, 1]); - assert_eq!(c.next(), None); - - let v2: &[i32] = &[0, 1, 2, 3, 4]; - let mut c2 = v2.chunks(3); - assert_eq!(c2.nth_back(1).unwrap(), &[0, 1]); - assert_eq!(c2.next(), None); - assert_eq!(c2.next_back(), None); - - let v3: &[i32] = &[0, 1, 2, 3, 4]; - let mut c3 = v3.chunks(10); - assert_eq!(c3.nth_back(0).unwrap(), &[0, 1, 2, 3, 4]); - assert_eq!(c3.next(), None); -} #[test] fn test_chunks_last() { From 59a382122fb09e2a9b4629e36efbc63a321eab6a Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 11 May 2019 17:41:37 +0300 Subject: [PATCH 0272/3207] Simplify use of keyword symbols --- src/librustc/hir/lowering.rs | 22 +- src/librustc/hir/map/def_collector.rs | 4 +- src/librustc/hir/map/mod.rs | 2 +- src/librustc/hir/mod.rs | 17 +- src/librustc/hir/print.rs | 10 +- src/librustc/middle/liveness.rs | 4 +- src/librustc/middle/resolve_lifetime.rs | 10 +- src/librustc/ty/context.rs | 4 +- src/librustc/ty/mod.rs | 4 +- src/librustc/ty/print/pretty.rs | 2 +- src/librustc/ty/sty.rs | 6 +- src/librustc_codegen_ssa/mir/mod.rs | 6 +- src/librustc_lint/builtin.rs | 4 +- src/librustc_lint/unused.rs | 4 +- src/librustc_macros/src/symbols.rs | 19 +- src/librustc_metadata/encoder.rs | 4 +- .../borrow_check/mutability_errors.rs | 4 +- .../nll/region_infer/error_reporting/mod.rs | 4 +- .../error_reporting/region_name.rs | 4 +- src/librustc_mir/build/mod.rs | 4 +- src/librustc_passes/ast_validation.rs | 8 +- src/librustc_privacy/lib.rs | 4 +- src/librustc_resolve/build_reduced_graph.rs | 30 +- src/librustc_resolve/diagnostics.rs | 14 +- src/librustc_resolve/lib.rs | 74 ++-- src/librustc_resolve/macros.rs | 12 +- src/librustc_resolve/resolve_imports.rs | 16 +- src/librustc_typeck/check/mod.rs | 8 +- src/librustc_typeck/collect.rs | 8 +- src/librustdoc/clean/mod.rs | 17 +- src/librustdoc/html/layout.rs | 2 +- src/libsyntax/ast.rs | 12 +- src/libsyntax/attr/mod.rs | 8 +- src/libsyntax/diagnostics/plugin.rs | 4 +- src/libsyntax/ext/base.rs | 4 +- src/libsyntax/ext/build.rs | 6 +- src/libsyntax/ext/expand.rs | 18 +- src/libsyntax/ext/placeholders.rs | 4 +- src/libsyntax/ext/tt/macro_parser.rs | 8 +- src/libsyntax/ext/tt/macro_rules.rs | 2 +- src/libsyntax/ext/tt/quoted.rs | 10 +- src/libsyntax/mut_visit.rs | 4 +- src/libsyntax/parse/literal.rs | 2 +- src/libsyntax/parse/parser.rs | 415 +++++++++--------- src/libsyntax/parse/token.rs | 72 +-- src/libsyntax/print/pprust.rs | 14 +- src/libsyntax/std_inject.rs | 6 +- src/libsyntax/test.rs | 6 +- src/libsyntax/util/parser.rs | 4 +- src/libsyntax_ext/deriving/clone.rs | 5 +- src/libsyntax_ext/deriving/generic/mod.rs | 8 +- src/libsyntax_ext/deriving/generic/ty.rs | 4 +- src/libsyntax_ext/env.rs | 4 +- src/libsyntax_ext/proc_macro_decls.rs | 4 +- src/libsyntax_ext/proc_macro_server.rs | 6 +- src/libsyntax_ext/trace_macros.rs | 6 +- src/libsyntax_pos/hygiene.rs | 14 +- src/libsyntax_pos/symbol.rs | 55 +-- 58 files changed, 502 insertions(+), 534 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 3ec4d4e8cc8f..7cf5b4a9021d 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -64,7 +64,7 @@ use syntax::ptr::P; use syntax::source_map::{respan, CompilerDesugaringKind, Spanned}; use syntax::source_map::CompilerDesugaringKind::IfTemporary; use syntax::std_inject; -use syntax::symbol::{keywords, Symbol, sym}; +use syntax::symbol::{kw, sym, Symbol}; use syntax::tokenstream::{TokenStream, TokenTree}; use syntax::parse::token::Token; use syntax::visit::{self, Visitor}; @@ -927,11 +927,11 @@ impl<'a> LoweringContext<'a> { hir::LifetimeParamKind::InBand, ), ParamName::Fresh(_) => ( - keywords::UnderscoreLifetime.name().as_interned_str(), + kw::UnderscoreLifetime.as_interned_str(), hir::LifetimeParamKind::Elided, ), ParamName::Error => ( - keywords::UnderscoreLifetime.name().as_interned_str(), + kw::UnderscoreLifetime.as_interned_str(), hir::LifetimeParamKind::Error, ), }; @@ -1415,7 +1415,7 @@ impl<'a> LoweringContext<'a> { P(hir::Path { res, segments: hir_vec![hir::PathSegment::from_ident( - keywords::SelfUpper.ident() + Ident::with_empty_ctxt(kw::SelfUpper) )], span: t.span, }), @@ -1614,7 +1614,7 @@ impl<'a> LoweringContext<'a> { trace!("registering existential type with id {:#?}", exist_ty_id); let exist_ty_item = hir::Item { hir_id: exist_ty_id, - ident: keywords::Invalid.ident(), + ident: Ident::with_empty_ctxt(kw::Invalid), attrs: Default::default(), node: exist_ty_item_kind, vis: respan(span.shrink_to_lo(), hir::VisibilityKind::Inherited), @@ -1747,7 +1747,7 @@ impl<'a> LoweringContext<'a> { let (name, kind) = match name { hir::LifetimeName::Underscore => ( - hir::ParamName::Plain(keywords::UnderscoreLifetime.ident()), + hir::ParamName::Plain(Ident::with_empty_ctxt(kw::UnderscoreLifetime)), hir::LifetimeParamKind::Elided, ), hir::LifetimeName::Param(param_name) => ( @@ -2296,7 +2296,7 @@ impl<'a> LoweringContext<'a> { .iter() .map(|arg| match arg.pat.node { PatKind::Ident(_, ident, _) => ident, - _ => Ident::new(keywords::Invalid.name(), arg.pat.span), + _ => Ident::new(kw::Invalid, arg.pat.span), }) .collect() } @@ -2585,9 +2585,9 @@ impl<'a> LoweringContext<'a> { fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime { let span = l.ident.span; match l.ident { - ident if ident.name == keywords::StaticLifetime.name() => + ident if ident.name == kw::StaticLifetime => self.new_named_lifetime(l.id, span, hir::LifetimeName::Static), - ident if ident.name == keywords::UnderscoreLifetime.name() => + ident if ident.name == kw::UnderscoreLifetime => match self.anonymous_lifetime_mode { AnonymousLifetimeMode::CreateParameter => { let fresh_name = self.collect_fresh_in_band_lifetime(span); @@ -2709,7 +2709,7 @@ impl<'a> LoweringContext<'a> { // Don't expose `Self` (recovered "keyword used as ident" parse error). // `rustc::ty` expects `Self` to be only used for a trait's `Self`. // Instead, use `gensym("Self")` to create a distinct name that looks the same. - let ident = if param.ident.name == keywords::SelfUpper.name() { + let ident = if param.ident.name == kw::SelfUpper { param.ident.gensym() } else { param.ident @@ -3325,7 +3325,7 @@ impl<'a> LoweringContext<'a> { // Correctly resolve `self` imports. if path.segments.len() > 1 - && path.segments.last().unwrap().ident.name == keywords::SelfLower.name() + && path.segments.last().unwrap().ident.name == kw::SelfLower { let _ = path.segments.pop(); if rename.is_none() { diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 6e7a8f5bc234..77fd8cc062f3 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -5,7 +5,7 @@ use crate::session::CrateDisambiguator; use syntax::ast::*; use syntax::ext::hygiene::Mark; use syntax::visit; -use syntax::symbol::keywords; +use syntax::symbol::kw; use syntax::symbol::Symbol; use syntax::parse::token::{self, Token}; use syntax_pos::Span; @@ -138,7 +138,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { // information we encapsulate into, the better let def_data = match i.node { ItemKind::Impl(..) => DefPathData::Impl, - ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => { + ItemKind::Mod(..) if i.ident == Ident::with_empty_ctxt(kw::Invalid) => { return visit::walk_item(self, i); } ItemKind::Mod(..) | ItemKind::Trait(..) | ItemKind::TraitAlias(..) | diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 23f4d2085713..e5ca97b82ab4 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -519,7 +519,7 @@ impl<'hir> Map<'hir> { pub fn ty_param_name(&self, id: HirId) -> Name { match self.get_by_hir_id(id) { Node::Item(&Item { node: ItemKind::Trait(..), .. }) | - Node::Item(&Item { node: ItemKind::TraitAlias(..), .. }) => keywords::SelfUpper.name(), + Node::Item(&Item { node: ItemKind::TraitAlias(..), .. }) => kw::SelfUpper, Node::GenericParam(param) => param.name.ident().name, _ => bug!("ty_param_name: {} not a type parameter", self.hir_to_string(id)), } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index d2b926d18869..e5e6c408a062 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -24,7 +24,7 @@ use syntax::ast::{Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy}; use syntax::attr::{InlineAttr, OptimizeAttr}; use syntax::ext::hygiene::SyntaxContext; use syntax::ptr::P; -use syntax::symbol::{Symbol, keywords}; +use syntax::symbol::{Symbol, kw}; use syntax::tokenstream::TokenStream; use syntax::util::parser::ExprPrecedence; use crate::ty::AdtKind; @@ -160,7 +160,7 @@ pub struct Lifetime { pub span: Span, /// Either "`'a`", referring to a named lifetime definition, - /// or "``" (i.e., `keywords::Invalid`), for elision placeholders. + /// or "``" (i.e., `kw::Invalid`), for elision placeholders. /// /// HIR lowering inserts these placeholders in type paths that /// refer to type definitions needing lifetime parameters, @@ -199,7 +199,8 @@ impl ParamName { pub fn ident(&self) -> Ident { match *self { ParamName::Plain(ident) => ident, - ParamName::Error | ParamName::Fresh(_) => keywords::UnderscoreLifetime.ident(), + ParamName::Fresh(_) | + ParamName::Error => Ident::with_empty_ctxt(kw::UnderscoreLifetime), } } @@ -233,10 +234,10 @@ pub enum LifetimeName { impl LifetimeName { pub fn ident(&self) -> Ident { match *self { - LifetimeName::Implicit => keywords::Invalid.ident(), - LifetimeName::Error => keywords::Invalid.ident(), - LifetimeName::Underscore => keywords::UnderscoreLifetime.ident(), - LifetimeName::Static => keywords::StaticLifetime.ident(), + LifetimeName::Implicit => Ident::with_empty_ctxt(kw::Invalid), + LifetimeName::Error => Ident::with_empty_ctxt(kw::Invalid), + LifetimeName::Underscore => Ident::with_empty_ctxt(kw::UnderscoreLifetime), + LifetimeName::Static => Ident::with_empty_ctxt(kw::StaticLifetime), LifetimeName::Param(param_name) => param_name.ident(), } } @@ -305,7 +306,7 @@ pub struct Path { impl Path { pub fn is_global(&self) -> bool { - !self.segments.is_empty() && self.segments[0].ident.name == keywords::PathRoot.name() + !self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot } } diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 8a9028e54439..60511ecc883c 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -7,7 +7,7 @@ use syntax::print::pp::{self, Breaks}; use syntax::print::pp::Breaks::{Consistent, Inconsistent}; use syntax::print::pprust::{self, PrintState}; use syntax::ptr::P; -use syntax::symbol::keywords; +use syntax::symbol::kw; use syntax::util::parser::{self, AssocOp, Fixity}; use syntax_pos::{self, BytePos, FileName}; @@ -798,7 +798,7 @@ impl<'a> State<'a> { hir::VisibilityKind::Restricted { ref path, .. } => { self.s.word("pub(")?; if path.segments.len() == 1 && - path.segments[0].ident.name == keywords::Super.name() { + path.segments[0].ident.name == kw::Super { // Special case: `super` can print like `pub(super)`. self.s.word("super")?; } else { @@ -1559,7 +1559,7 @@ impl<'a> State<'a> { if i > 0 { self.s.word("::")? } - if segment.ident.name != keywords::PathRoot.name() { + if segment.ident.name != kw::PathRoot { self.print_ident(segment.ident)?; segment.with_generic_args(|generic_args| { self.print_generic_args(generic_args, segment.infer_types, @@ -1572,7 +1572,7 @@ impl<'a> State<'a> { } pub fn print_path_segment(&mut self, segment: &hir::PathSegment) -> io::Result<()> { - if segment.ident.name != keywords::PathRoot.name() { + if segment.ident.name != kw::PathRoot { self.print_ident(segment.ident)?; segment.with_generic_args(|generic_args| { self.print_generic_args(generic_args, segment.infer_types, false) @@ -1599,7 +1599,7 @@ impl<'a> State<'a> { if i > 0 { self.s.word("::")? } - if segment.ident.name != keywords::PathRoot.name() { + if segment.ident.name != kw::PathRoot { self.print_ident(segment.ident)?; segment.with_generic_args(|generic_args| { self.print_generic_args(generic_args, diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index cb333b5b0cba..91a19852c6c0 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -112,7 +112,7 @@ use std::io; use std::rc::Rc; use syntax::ast::{self, NodeId}; use syntax::ptr::P; -use syntax::symbol::{keywords, sym}; +use syntax::symbol::{kw, sym}; use syntax_pos::Span; use crate::hir; @@ -1552,7 +1552,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { let sp = ident.span; let var = self.variable(hir_id, sp); // Ignore unused self. - if ident.name != keywords::SelfLower.name() { + if ident.name != kw::SelfLower { if !self.warn_about_unused(vec![sp], hir_id, entry_ln, var) { if self.live_on_entry(entry_ln, var).is_none() { self.report_dead_assign(hir_id, sp, var, true); diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 2402d0eefde4..6a4d2e0966b9 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -23,7 +23,7 @@ use std::mem::replace; use syntax::ast; use syntax::attr; use syntax::ptr::P; -use syntax::symbol::{keywords, sym}; +use syntax::symbol::{kw, sym}; use syntax_pos::Span; use crate::hir::intravisit::{self, NestedVisitorMap, Visitor}; @@ -711,7 +711,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { GenericParamKind::Lifetime { .. } => { let (name, reg) = Region::early(&self.tcx.hir(), &mut index, ¶m); if let hir::ParamName::Plain(param_name) = name { - if param_name.name == keywords::UnderscoreLifetime.name() { + if param_name.name == kw::UnderscoreLifetime { // Pick the elided lifetime "definition" if one exists // and use it to make an elision scope. elision = Some(reg); @@ -1602,7 +1602,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } { debug!("id = {:?} span = {:?} name = {:?}", id, span, name); - if name == keywords::UnderscoreLifetime.ident() { + if name == ast::Ident::with_empty_ctxt(kw::UnderscoreLifetime) { continue; } @@ -2525,8 +2525,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { for (i, (lifetime_i, lifetime_i_name)) in lifetimes.iter().enumerate() { if let hir::ParamName::Plain(_) = lifetime_i_name { let name = lifetime_i_name.ident().name; - if name == keywords::UnderscoreLifetime.name() - || name == keywords::StaticLifetime.name() + if name == kw::UnderscoreLifetime + || name == kw::StaticLifetime { let mut err = struct_span_err!( self.tcx.sess, diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index c9fee02f66bb..b5a17684c0ff 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -74,7 +74,7 @@ use syntax::ast; use syntax::attr; use syntax::source_map::MultiSpan; use syntax::feature_gate; -use syntax::symbol::{Symbol, keywords, InternedString, sym}; +use syntax::symbol::{Symbol, InternedString, kw, sym}; use syntax_pos::Span; use crate::hir; @@ -2735,7 +2735,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { #[inline] pub fn mk_self_type(self) -> Ty<'tcx> { - self.mk_ty_param(0, keywords::SelfUpper.name().as_interned_str()) + self.mk_ty_param(0, kw::SelfUpper.as_interned_str()) } pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> Kind<'tcx> { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 4d242265e618..a2c89489b95d 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -47,7 +47,7 @@ use std::ops::Range; use syntax::ast::{self, Name, Ident, NodeId}; use syntax::attr; use syntax::ext::hygiene::Mark; -use syntax::symbol::{keywords, sym, Symbol, LocalInternedString, InternedString}; +use syntax::symbol::{kw, sym, Symbol, LocalInternedString, InternedString}; use syntax_pos::Span; use smallvec; @@ -835,7 +835,7 @@ impl ty::EarlyBoundRegion { /// Does this early bound region have a name? Early bound regions normally /// always have names except when using anonymous lifetimes (`'_`). pub fn has_name(&self) -> bool { - self.name != keywords::UnderscoreLifetime.name().as_interned_str() + self.name != kw::UnderscoreLifetime.as_interned_str() } } diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index c18852a832fc..5199da8fbbc5 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -980,7 +980,7 @@ impl Printer<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> { if self.tcx.sess.rust_2018() { // We add the `crate::` keyword on Rust 2018, only when desired. if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) { - write!(self, "{}", keywords::Crate.name())?; + write!(self, "{}", kw::Crate)?; self.empty_path = false; } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index e8f3bad4d3ee..0b5a6fce5cb8 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -22,7 +22,7 @@ use std::marker::PhantomData; use std::ops::Range; use rustc_target::spec::abi; use syntax::ast::{self, Ident}; -use syntax::symbol::{keywords, InternedString}; +use syntax::symbol::{kw, InternedString}; use serialize; use self::InferTy::*; @@ -1121,7 +1121,7 @@ impl<'a, 'gcx, 'tcx> ParamTy { } pub fn for_self() -> ParamTy { - ParamTy::new(0, keywords::SelfUpper.name().as_interned_str()) + ParamTy::new(0, kw::SelfUpper.as_interned_str()) } pub fn for_def(def: &ty::GenericParamDef) -> ParamTy { @@ -1136,7 +1136,7 @@ impl<'a, 'gcx, 'tcx> ParamTy { // FIXME(#50125): Ignoring `Self` with `index != 0` might lead to weird behavior elsewhere, // but this should only be possible when using `-Z continue-parse-after-error` like // `compile-fail/issue-36638.rs`. - self.name.as_symbol() == keywords::SelfUpper.name() && self.index == 0 + self.name.as_symbol() == kw::SelfUpper && self.index == 0 } } diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 060d7d18625f..fed12c9a29fd 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -10,7 +10,7 @@ use crate::debuginfo::{self, VariableAccess, VariableKind, FunctionDebugContext} use crate::traits::*; use syntax_pos::{DUMMY_SP, NO_EXPANSION, BytePos, Span}; -use syntax::symbol::keywords; +use syntax::symbol::kw; use std::iter; @@ -496,7 +496,7 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( }; bx.declare_local( &fx.debug_context, - arg_decl.name.unwrap_or(keywords::Invalid.name()), + arg_decl.name.unwrap_or(kw::Invalid), arg_ty, scope, variable_access, VariableKind::ArgumentVariable(arg_index + 1), @@ -613,7 +613,7 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( bx.declare_local( &fx.debug_context, - arg_decl.name.unwrap_or(keywords::Invalid.name()), + arg_decl.name.unwrap_or(kw::Invalid), arg.layout.ty, scope, variable_access, diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index d17a92efb066..d52e497cf63d 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -42,7 +42,7 @@ use syntax::edition::Edition; use syntax::feature_gate::{AttributeGate, AttributeTemplate, AttributeType}; use syntax::feature_gate::{Stability, deprecated_attributes}; use syntax_pos::{BytePos, Span, SyntaxContext}; -use syntax::symbol::{Symbol, keywords, sym}; +use syntax::symbol::{Symbol, kw, sym}; use syntax::errors::{Applicability, DiagnosticBuilder}; use syntax::print::pprust::expr_to_string; use syntax::visit::FnKind; @@ -607,7 +607,7 @@ impl EarlyLintPass for AnonymousParameters { for arg in sig.decl.inputs.iter() { match arg.pat.node { ast::PatKind::Ident(_, ident, None) => { - if ident.name == keywords::Invalid.name() { + if ident.name == kw::Invalid { let ty_snip = cx .sess .source_map() diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index c3dfd44ad857..34f7e04c1642 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -12,7 +12,7 @@ use syntax::attr; use syntax::errors::Applicability; use syntax::feature_gate::{AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use syntax::print::pprust; -use syntax::symbol::{keywords, sym}; +use syntax::symbol::{kw, sym}; use syntax::symbol::Symbol; use syntax::util::parser; use syntax_pos::Span; @@ -455,7 +455,7 @@ impl UnusedImportBraces { match items[0].0.kind { ast::UseTreeKind::Simple(rename, ..) => { let orig_ident = items[0].0.prefix.segments.last().unwrap().ident; - if orig_ident.name == keywords::SelfLower.name() { + if orig_ident.name == kw::SelfLower { return; } node_ident = rename.unwrap_or(orig_ident); diff --git a/src/librustc_macros/src/symbols.rs b/src/librustc_macros/src/symbols.rs index a4c7daf088ff..3883682fa9df 100644 --- a/src/librustc_macros/src/symbols.rs +++ b/src/librustc_macros/src/symbols.rs @@ -97,7 +97,6 @@ pub fn symbols(input: TokenStream) -> TokenStream { let mut keyword_stream = quote! {}; let mut symbols_stream = quote! {}; let mut prefill_stream = quote! {}; - let mut from_str_stream = quote! {}; let mut counter = 0u32; let mut keys = HashSet::::new(); @@ -115,12 +114,7 @@ pub fn symbols(input: TokenStream) -> TokenStream { #value, }); keyword_stream.extend(quote! { - pub const #name: Keyword = Keyword { - ident: Ident::with_empty_ctxt(super::Symbol::new(#counter)) - }; - }); - from_str_stream.extend(quote! { - #value => Ok(#name), + pub const #name: Symbol = Symbol::new(#counter); }); counter += 1; } @@ -145,17 +139,6 @@ pub fn symbols(input: TokenStream) -> TokenStream { macro_rules! keywords { () => { #keyword_stream - - impl std::str::FromStr for Keyword { - type Err = (); - - fn from_str(s: &str) -> Result { - match s { - #from_str_stream - _ => Err(()), - } - } - } } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 7f0993e799f5..dfc3439fc553 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -33,7 +33,7 @@ use std::u32; use syntax::ast; use syntax::attr; use syntax::source_map::Spanned; -use syntax::symbol::{keywords, sym}; +use syntax::symbol::{kw, sym}; use syntax_pos::{self, FileName, SourceFile, Span}; use log::{debug, trace}; @@ -1042,7 +1042,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { self.lazy_seq(body.arguments.iter().map(|arg| { match arg.pat.node { PatKind::Binding(_, _, ident, _) => ident.name, - _ => keywords::Invalid.name(), + _ => kw::Invalid, } })) }) diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 32088ff9f61e..4bee7f9c4bf8 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -8,7 +8,7 @@ use rustc::mir::{Terminator, TerminatorKind}; use rustc::ty::{self, Const, DefIdTree, Ty, TyS, TyCtxt}; use rustc_data_structures::indexed_vec::Idx; use syntax_pos::Span; -use syntax_pos::symbol::keywords; +use syntax_pos::symbol::kw; use crate::dataflow::move_paths::InitLocation; use crate::borrow_check::MirBorrowckCtxt; @@ -256,7 +256,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { // Deliberately fall into this case for all implicit self types, // so that we don't fall in to the next case with them. *kind == mir::ImplicitSelfKind::MutRef - } else if Some(keywords::SelfLower.name()) == local_decl.name { + } else if Some(kw::SelfLower) == local_decl.name { // Otherwise, check if the name is the self kewyord - in which case // we have an explicit self. Do the same thing in this case and check // for a `self: &mut Self` to suggest removing the `&mut`. diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs index 00e81ee04918..18ca105070e8 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs @@ -15,7 +15,7 @@ use rustc_data_structures::indexed_vec::IndexVec; use rustc_errors::{Diagnostic, DiagnosticBuilder}; use std::collections::VecDeque; use syntax::errors::Applicability; -use syntax::symbol::keywords; +use syntax::symbol::kw; use syntax_pos::Span; mod region_name; @@ -631,7 +631,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { "add_static_impl_trait_suggestion: has_static_predicate={:?}", has_static_predicate ); - let static_str = keywords::StaticLifetime.name(); + let static_str = kw::StaticLifetime; // If there is a static predicate, then the only sensible suggestion is to replace // fr with `'static`. if has_static_predicate { diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index 4d8acd241acd..f3cfc1a59a98 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -12,7 +12,7 @@ use rustc::ty::subst::{SubstsRef, UnpackedKind}; use rustc::ty::{self, RegionKind, RegionVid, Ty, TyCtxt}; use rustc::ty::print::RegionHighlightMode; use rustc_errors::DiagnosticBuilder; -use syntax::symbol::keywords; +use syntax::symbol::kw; use syntax_pos::Span; use syntax_pos::symbol::InternedString; @@ -216,7 +216,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } ty::ReStatic => Some(RegionName { - name: keywords::StaticLifetime.name().as_interned_str(), + name: kw::StaticLifetime.as_interned_str(), source: RegionNameSource::Static }), diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index e46c51535552..199b0176601e 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -20,7 +20,7 @@ use std::mem; use std::u32; use rustc_target::spec::abi::Abi; use syntax::attr::{self, UnwindAttr}; -use syntax::symbol::keywords; +use syntax::symbol::kw; use syntax_pos::Span; use super::lints; @@ -660,7 +660,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, ty::UpvarCapture::ByRef(..) => true, }; let mut debuginfo = UpvarDebuginfo { - debug_name: keywords::Invalid.name(), + debug_name: kw::Invalid, by_ref, }; let mut mutability = Mutability::Not; diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 2bea1db841ae..3091570d1480 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -15,7 +15,7 @@ use rustc_data_structures::fx::FxHashMap; use syntax::ast::*; use syntax::attr; use syntax::source_map::Spanned; -use syntax::symbol::{keywords, sym}; +use syntax::symbol::{kw, sym}; use syntax::ptr::P; use syntax::visit::{self, Visitor}; use syntax::{span_err, struct_span_err, walk_list}; @@ -177,9 +177,9 @@ impl<'a> AstValidator<'a> { } fn check_lifetime(&self, ident: Ident) { - let valid_names = [keywords::UnderscoreLifetime.name(), - keywords::StaticLifetime.name(), - keywords::Invalid.name()]; + let valid_names = [kw::UnderscoreLifetime, + kw::StaticLifetime, + kw::Invalid]; if !valid_names.contains(&ident.name) && ident.without_first_quote().is_reserved() { self.err_handler().span_err(ident.span, "lifetimes cannot use keyword names"); } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index cd21713cddf9..1df42a950427 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -27,7 +27,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; use syntax::ast::Ident; use syntax::attr; -use syntax::symbol::{keywords, sym}; +use syntax::symbol::{kw, sym}; use syntax_pos::Span; use std::{cmp, fmt, mem}; @@ -844,7 +844,7 @@ impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> { span: Span, // span of the field pattern, e.g., `x: 0` def: &'tcx ty::AdtDef, // definition of the struct or enum field: &'tcx ty::FieldDef) { // definition of the field - let ident = Ident::new(keywords::Invalid.name(), use_ctxt); + let ident = Ident::new(kw::Invalid, use_ctxt); let current_hir = self.current_item; let def_id = self.tcx.adjust_ident(ident, def.did, current_hir).1; if !def.is_enum() && !field.vis.is_accessible_from(def_id, self.tcx) { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 3b58a99d19fe..782f36a77dac 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -37,7 +37,7 @@ use syntax::feature_gate::is_builtin_attr; use syntax::parse::token::{self, Token}; use syntax::span_err; use syntax::std_inject::injected_crate_name; -use syntax::symbol::{keywords, sym}; +use syntax::symbol::{kw, sym}; use syntax::visit::{self, Visitor}; use syntax_pos::{Span, DUMMY_SP}; @@ -143,7 +143,7 @@ impl<'a> Resolver<'a> { } _ => None, }.map(|ctxt| Segment::from_ident(Ident::new( - keywords::PathRoot.name(), use_tree.prefix.span.shrink_to_lo().with_ctxt(ctxt) + kw::PathRoot, use_tree.prefix.span.shrink_to_lo().with_ctxt(ctxt) ))); let prefix = crate_root.into_iter().chain(prefix_iter).collect::>(); @@ -151,7 +151,7 @@ impl<'a> Resolver<'a> { let empty_for_self = |prefix: &[Segment]| { prefix.is_empty() || - prefix.len() == 1 && prefix[0].ident.name == keywords::PathRoot.name() + prefix.len() == 1 && prefix[0].ident.name == kw::PathRoot }; match use_tree.kind { ast::UseTreeKind::Simple(rename, ..) => { @@ -162,7 +162,7 @@ impl<'a> Resolver<'a> { if nested { // Correctly handle `self` - if source.ident.name == keywords::SelfLower.name() { + if source.ident.name == kw::SelfLower { type_ns_only = true; if empty_for_self(&module_path) { @@ -183,14 +183,14 @@ impl<'a> Resolver<'a> { } } else { // Disallow `self` - if source.ident.name == keywords::SelfLower.name() { + if source.ident.name == kw::SelfLower { resolve_error(self, use_tree.span, ResolutionError::SelfImportsOnlyAllowedWithin); } // Disallow `use $crate;` - if source.ident.name == keywords::DollarCrate.name() && module_path.is_empty() { + if source.ident.name == kw::DollarCrate && module_path.is_empty() { let crate_root = self.resolve_crate_root(source.ident); let crate_name = match crate_root.kind { ModuleKind::Def(.., name) => name, @@ -199,11 +199,11 @@ impl<'a> Resolver<'a> { // HACK(eddyb) unclear how good this is, but keeping `$crate` // in `source` breaks `src/test/compile-fail/import-crate-var.rs`, // while the current crate doesn't have a valid `crate_name`. - if crate_name != keywords::Invalid.name() { + if crate_name != kw::Invalid { // `crate_name` should not be interpreted as relative. module_path.push(Segment { ident: Ident { - name: keywords::PathRoot.name(), + name: kw::PathRoot, span: source.ident.span, }, id: Some(self.session.next_node_id()), @@ -221,7 +221,7 @@ impl<'a> Resolver<'a> { } } - if ident.name == keywords::Crate.name() { + if ident.name == kw::Crate { self.session.span_err(ident.span, "crate root imports need to be explicitly named: \ `use crate as name;`"); @@ -276,7 +276,7 @@ impl<'a> Resolver<'a> { // Ensure there is at most one `self` in the list let self_spans = items.iter().filter_map(|&(ref use_tree, _)| { if let ast::UseTreeKind::Simple(..) = use_tree.kind { - if use_tree.ident().name == keywords::SelfLower.name() { + if use_tree.ident().name == kw::SelfLower { return Some(use_tree.span); } } @@ -311,7 +311,7 @@ impl<'a> Resolver<'a> { let new_span = prefix[prefix.len() - 1].ident.span; let tree = ast::UseTree { prefix: ast::Path::from_ident( - Ident::new(keywords::SelfLower.name(), new_span) + Ident::new(kw::SelfLower, new_span) ), kind: ast::UseTreeKind::Simple( Some(Ident::from_str_and_span("__dummy", new_span).gensym()), @@ -350,7 +350,7 @@ impl<'a> Resolver<'a> { } ItemKind::ExternCrate(orig_name) => { - let module = if orig_name.is_none() && ident.name == keywords::SelfLower.name() { + let module = if orig_name.is_none() && ident.name == kw::SelfLower { self.session .struct_span_err(item.span, "`extern crate self;` requires renaming") .span_suggestion( @@ -361,7 +361,7 @@ impl<'a> Resolver<'a> { ) .emit(); return; - } else if orig_name == Some(keywords::SelfLower.name()) { + } else if orig_name == Some(kw::SelfLower) { self.graph_root } else { let crate_id = self.crate_loader.process_extern_crate(item, &self.definitions); @@ -420,7 +420,7 @@ impl<'a> Resolver<'a> { ItemKind::GlobalAsm(..) => {} - ItemKind::Mod(..) if ident == keywords::Invalid.ident() => {} // Crate root + ItemKind::Mod(..) if ident == Ident::with_empty_ctxt(kw::Invalid) => {} // Crate root ItemKind::Mod(..) => { let def_id = self.definitions.local_def_id(item.id); @@ -831,7 +831,7 @@ impl<'a> Resolver<'a> { "an `extern crate` loading macros must be at the crate root"); } if let ItemKind::ExternCrate(Some(orig_name)) = item.node { - if orig_name == keywords::SelfLower.name() { + if orig_name == kw::SelfLower { self.session.span_err(attr.span, "`macro_use` is not supported on `extern crate self`"); } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 509aa95bb61d..730927d2bb57 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -7,7 +7,7 @@ use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use rustc::session::{Session, config::nightly_options}; use syntax::ast::{self, Expr, ExprKind, Ident}; use syntax::ext::base::MacroKind; -use syntax::symbol::{Symbol, keywords}; +use syntax::symbol::{Symbol, kw}; use syntax_pos::{BytePos, Span}; type Res = def::Res; @@ -48,7 +48,7 @@ impl<'a> Resolver<'a> { let item_span = path.last().unwrap().ident.span; let (mod_prefix, mod_str) = if path.len() == 1 { (String::new(), "this scope".to_string()) - } else if path.len() == 2 && path[0].ident.name == keywords::PathRoot.name() { + } else if path.len() == 2 && path[0].ident.name == kw::PathRoot { (String::new(), "the crate root".to_string()) } else { let mod_path = &path[..path.len() - 1]; @@ -454,13 +454,13 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { match (path.get(0), path.get(1)) { // `{{root}}::ident::...` on both editions. // On 2015 `{{root}}` is usually added implicitly. - (Some(fst), Some(snd)) if fst.ident.name == keywords::PathRoot.name() && + (Some(fst), Some(snd)) if fst.ident.name == kw::PathRoot && !snd.ident.is_path_segment_keyword() => {} // `ident::...` on 2018. (Some(fst), _) if fst.ident.span.rust_2018() && !fst.ident.is_path_segment_keyword() => { // Insert a placeholder that's later replaced by `self`/`super`/etc. - path.insert(0, Segment::from_ident(keywords::Invalid.ident())); + path.insert(0, Segment::from_ident(Ident::with_empty_ctxt(kw::Invalid))); } _ => return None, } @@ -485,7 +485,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { parent_scope: &ParentScope<'b>, ) -> Option<(Vec, Vec)> { // Replace first ident with `self` and check if that is valid. - path[0].ident.name = keywords::SelfLower.name(); + path[0].ident.name = kw::SelfLower; let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { @@ -509,7 +509,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { parent_scope: &ParentScope<'b>, ) -> Option<(Vec, Vec)> { // Replace first ident with `crate` and check if that is valid. - path[0].ident.name = keywords::Crate.name(); + path[0].ident.name = kw::Crate; let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); debug!("make_missing_crate_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { @@ -540,7 +540,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { parent_scope: &ParentScope<'b>, ) -> Option<(Vec, Vec)> { // Replace first ident with `crate` and check if that is valid. - path[0].ident.name = keywords::Super.name(); + path[0].ident.name = kw::Super; let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No); debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result); if let PathResult::Module(..) = result { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index c4a4dd306055..748cf691f8dd 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -43,7 +43,7 @@ use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy}; use syntax::ext::base::SyntaxExtension; use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; use syntax::ext::base::MacroKind; -use syntax::symbol::{Symbol, keywords, sym}; +use syntax::symbol::{Symbol, kw, sym}; use syntax::util::lev_distance::find_best_match_for_name; use syntax::visit::{self, FnKind, Visitor}; @@ -820,7 +820,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { self.smart_resolve_path(ty.id, qself.as_ref(), path, PathSource::Type); } TyKind::ImplicitSelf => { - let self_ty = keywords::SelfUpper.ident(); + let self_ty = Ident::with_empty_ctxt(kw::SelfUpper); let res = self.resolve_ident_in_lexical_scope(self_ty, TypeNS, Some(ty.id), ty.span) .map_or(Res::Err, |d| d.res()); self.record_partial_res(ty.id, PartialRes::new(res)); @@ -1817,18 +1817,17 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> { is_value: bool ) -> hir::Path { let root = if crate_root.is_some() { - keywords::PathRoot + kw::PathRoot } else { - keywords::Crate + kw::Crate }; - let segments = iter::once(root.ident()) + let segments = iter::once(Ident::with_empty_ctxt(root)) .chain( crate_root.into_iter() .chain(components.iter().cloned()) .map(Ident::with_empty_ctxt) ).map(|i| self.new_ast_path_segment(i)).collect::>(); - let path = ast::Path { span, segments, @@ -1866,7 +1865,7 @@ impl<'a> Resolver<'a> { let path = if path_str.starts_with("::") { ast::Path { span, - segments: iter::once(keywords::PathRoot.ident()) + segments: iter::once(Ident::with_empty_ctxt(kw::PathRoot)) .chain({ path_str.split("::").skip(1).map(Ident::from_str) }) @@ -1961,7 +1960,7 @@ impl<'a> Resolver<'a> { let root_module_kind = ModuleKind::Def( DefKind::Mod, root_def_id, - keywords::Invalid.name(), + kw::Invalid, ); let graph_root = arenas.alloc_module(ModuleData { no_implicit_prelude: attr::contains_name(&krate.attrs, sym::no_implicit_prelude), @@ -2187,10 +2186,10 @@ impl<'a> Resolver<'a> { path_span: Span) -> Option> { assert!(ns == TypeNS || ns == ValueNS); - if ident.name == keywords::Invalid.name() { + if ident.name == kw::Invalid { return Some(LexicalScopeBinding::Res(Res::Err)); } - ident.span = if ident.name == keywords::SelfUpper.name() { + ident.span = if ident.name == kw::SelfUpper { // FIXME(jseyfried) improve `Self` hygiene ident.span.with_ctxt(SyntaxContext::empty()) } else if ns == TypeNS { @@ -2405,7 +2404,7 @@ impl<'a> Resolver<'a> { fn resolve_crate_root(&mut self, ident: Ident) -> Module<'a> { let mut ctxt = ident.span.ctxt(); - let mark = if ident.name == keywords::DollarCrate.name() { + let mark = if ident.name == kw::DollarCrate { // When resolving `$crate` from a `macro_rules!` invoked in a `macro`, // we don't want to pretend that the `macro_rules!` definition is in the `macro` // as described in `SyntaxContext::apply_mark`, so we ignore prepended modern marks. @@ -2851,7 +2850,7 @@ impl<'a> Resolver<'a> { let mut self_type_rib = Rib::new(NormalRibKind); // Plain insert (no renaming, since types are not currently hygienic) - self_type_rib.bindings.insert(keywords::SelfUpper.ident(), self_res); + self_type_rib.bindings.insert(Ident::with_empty_ctxt(kw::SelfUpper), self_res); self.ribs[TypeNS].push(self_type_rib); f(self); self.ribs[TypeNS].pop(); @@ -2862,7 +2861,7 @@ impl<'a> Resolver<'a> { { let self_res = Res::SelfCtor(impl_id); let mut self_type_rib = Rib::new(NormalRibKind); - self_type_rib.bindings.insert(keywords::SelfUpper.ident(), self_res); + self_type_rib.bindings.insert(Ident::with_empty_ctxt(kw::SelfUpper), self_res); self.ribs[ValueNS].push(self_type_rib); f(self); self.ribs[ValueNS].pop(); @@ -3199,7 +3198,7 @@ impl<'a> Resolver<'a> { } None => { // A completely fresh binding, add to the lists if it's valid. - if ident.name != keywords::Invalid.name() { + if ident.name != kw::Invalid { bindings.insert(ident, outer_pat_id); self.ribs[ValueNS].last_mut().unwrap().bindings.insert(ident, res); } @@ -3494,13 +3493,13 @@ impl<'a> Resolver<'a> { } fn self_type_is_available(&mut self, span: Span) -> bool { - let binding = self.resolve_ident_in_lexical_scope(keywords::SelfUpper.ident(), + let binding = self.resolve_ident_in_lexical_scope(Ident::with_empty_ctxt(kw::SelfUpper), TypeNS, None, span); if let Some(LexicalScopeBinding::Res(res)) = binding { res != Res::Err } else { false } } fn self_value_is_available(&mut self, self_span: Span, path_span: Span) -> bool { - let ident = Ident::new(keywords::SelfLower.name(), self_span); + let ident = Ident::new(kw::SelfLower, self_span); let binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None, path_span); if let Some(LexicalScopeBinding::Res(res)) = binding { res != Res::Err } else { false } } @@ -3657,8 +3656,8 @@ impl<'a> Resolver<'a> { }; if path.len() > 1 && !global_by_default && result.base_res() != Res::Err && - path[0].ident.name != keywords::PathRoot.name() && - path[0].ident.name != keywords::DollarCrate.name() { + path[0].ident.name != kw::PathRoot && + path[0].ident.name != kw::DollarCrate { let unqualified_result = { match self.resolve_path_without_parent_scope( &[*path.last().unwrap()], @@ -3739,11 +3738,11 @@ impl<'a> Resolver<'a> { let name = ident.name; allow_super &= ns == TypeNS && - (name == keywords::SelfLower.name() || - name == keywords::Super.name()); + (name == kw::SelfLower || + name == kw::Super); if ns == TypeNS { - if allow_super && name == keywords::Super.name() { + if allow_super && name == kw::Super { let mut ctxt = ident.span.ctxt().modern(); let self_module = match i { 0 => Some(self.resolve_self(&mut ctxt, self.current_module)), @@ -3768,25 +3767,25 @@ impl<'a> Resolver<'a> { }; } if i == 0 { - if name == keywords::SelfLower.name() { + if name == kw::SelfLower { let mut ctxt = ident.span.ctxt().modern(); module = Some(ModuleOrUniformRoot::Module( self.resolve_self(&mut ctxt, self.current_module))); continue; } - if name == keywords::PathRoot.name() && ident.span.rust_2018() { + if name == kw::PathRoot && ident.span.rust_2018() { module = Some(ModuleOrUniformRoot::ExternPrelude); continue; } - if name == keywords::PathRoot.name() && + if name == kw::PathRoot && ident.span.rust_2015() && self.session.rust_2018() { // `::a::b` from 2015 macro on 2018 global edition module = Some(ModuleOrUniformRoot::CrateRootAndExternPrelude); continue; } - if name == keywords::PathRoot.name() || - name == keywords::Crate.name() || - name == keywords::DollarCrate.name() { + if name == kw::PathRoot || + name == kw::Crate || + name == kw::DollarCrate { // `::a::b`, `crate::a::b` or `$crate::a::b` module = Some(ModuleOrUniformRoot::Module( self.resolve_crate_root(ident))); @@ -3797,12 +3796,12 @@ impl<'a> Resolver<'a> { // Report special messages for path segment keywords in wrong positions. if ident.is_path_segment_keyword() && i != 0 { - let name_str = if name == keywords::PathRoot.name() { + let name_str = if name == kw::PathRoot { "crate root".to_string() } else { format!("`{}`", name) }; - let label = if i == 1 && path[0].ident.name == keywords::PathRoot.name() { + let label = if i == 1 && path[0].ident.name == kw::PathRoot { format!("global paths cannot start with {}", name_str) } else { format!("{} in paths can only be used in start position", name_str) @@ -3971,13 +3970,13 @@ impl<'a> Resolver<'a> { // We're only interested in `use` paths which should start with // `{{root}}` currently. - if first_name != keywords::PathRoot.name() { + if first_name != kw::PathRoot { return } match path.get(1) { // If this import looks like `crate::...` it's already good - Some(Segment { ident, .. }) if ident.name == keywords::Crate.name() => return, + Some(Segment { ident, .. }) if ident.name == kw::Crate => return, // Otherwise go below to see if it's an extern crate Some(_) => {} // If the path has length one (and it's `PathRoot` most likely) @@ -4670,7 +4669,7 @@ impl<'a> Resolver<'a> { { let mut candidates = Vec::new(); let mut seen_modules = FxHashSet::default(); - let not_local_module = crate_name != keywords::Crate.ident(); + let not_local_module = crate_name != Ident::with_empty_ctxt(kw::Crate); let mut worklist = vec![(start_module, Vec::::new(), not_local_module)]; while let Some((in_module, @@ -4764,7 +4763,8 @@ impl<'a> Resolver<'a> { where FilterFn: Fn(Res) -> bool { let mut suggestions = self.lookup_import_candidates_from_module( - lookup_ident, namespace, self.graph_root, keywords::Crate.ident(), &filter_fn); + lookup_ident, namespace, self.graph_root, Ident::with_empty_ctxt(kw::Crate), &filter_fn + ); if lookup_ident.span.rust_2018() { let extern_prelude_names = self.extern_prelude.clone(); @@ -4883,7 +4883,7 @@ impl<'a> Resolver<'a> { } else { let ctxt = ident.span.ctxt(); Some(Segment::from_ident(Ident::new( - keywords::PathRoot.name(), path.span.shrink_to_lo().with_ctxt(ctxt) + kw::PathRoot, path.span.shrink_to_lo().with_ctxt(ctxt) ))) }; @@ -5352,17 +5352,17 @@ impl<'a> Resolver<'a> { } fn is_self_type(path: &[Segment], namespace: Namespace) -> bool { - namespace == TypeNS && path.len() == 1 && path[0].ident.name == keywords::SelfUpper.name() + namespace == TypeNS && path.len() == 1 && path[0].ident.name == kw::SelfUpper } fn is_self_value(path: &[Segment], namespace: Namespace) -> bool { - namespace == ValueNS && path.len() == 1 && path[0].ident.name == keywords::SelfLower.name() + namespace == ValueNS && path.len() == 1 && path[0].ident.name == kw::SelfLower } fn names_to_string(idents: &[Ident]) -> String { let mut result = String::new(); for (i, ident) in idents.iter() - .filter(|ident| ident.name != keywords::PathRoot.name()) + .filter(|ident| ident.name != kw::PathRoot) .enumerate() { if i > 0 { result.push_str("::"); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index d07f7b65275f..9bb607a2cc28 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -22,7 +22,7 @@ use syntax::ext::tt::macro_rules; use syntax::feature_gate::{ feature_err, is_builtin_attr_name, AttributeGate, GateIssue, Stability, BUILTIN_ATTRIBUTES, }; -use syntax::symbol::{Symbol, keywords, sym}; +use syntax::symbol::{Symbol, kw, sym}; use syntax::visit::Visitor; use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::{Span, DUMMY_SP}; @@ -137,10 +137,10 @@ impl<'a> base::Resolver for Resolver<'a> { } impl<'a> Visitor<'a> for ResolveDollarCrates<'a, '_> { fn visit_ident(&mut self, ident: Ident) { - if ident.name == keywords::DollarCrate.name() { + if ident.name == kw::DollarCrate { let name = match self.resolver.resolve_crate_root(ident).kind { - ModuleKind::Def(.., name) if name != keywords::Invalid.name() => name, - _ => keywords::Crate.name(), + ModuleKind::Def(.., name) if name != kw::Invalid => name, + _ => kw::Crate, }; ident.span.ctxt().set_dollar_crate_name(name); } @@ -415,7 +415,7 @@ impl<'a> Resolver<'a> { if kind == MacroKind::Bang && path.len() == 1 && path[0].ident.span.ctxt().outer().expn_info() .map_or(false, |info| info.local_inner_macros) { - let root = Ident::new(keywords::DollarCrate.name(), path[0].ident.span); + let root = Ident::new(kw::DollarCrate, path[0].ident.span); path.insert(0, Segment::from_ident(root)); } @@ -613,7 +613,7 @@ impl<'a> Resolver<'a> { _ => Err(Determinacy::Determined), } WhereToResolve::CrateRoot => { - let root_ident = Ident::new(keywords::PathRoot.name(), orig_ident.span); + let root_ident = Ident::new(kw::PathRoot, orig_ident.span); let root_module = self.resolve_crate_root(root_ident); let binding = self.resolve_ident_in_module_ext( ModuleOrUniformRoot::Module(root_module), diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 3a6a8b56ff35..ab873ea27012 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -29,7 +29,7 @@ use rustc::{bug, span_bug}; use syntax::ast::{self, Ident, Name, NodeId, CRATE_NODE_ID}; use syntax::ext::base::Determinacy::{self, Determined, Undetermined}; use syntax::ext::hygiene::Mark; -use syntax::symbol::{keywords, sym}; +use syntax::symbol::{kw, sym}; use syntax::util::lev_distance::find_best_match_for_name; use syntax::{struct_span_err, unwrap_or}; use syntax_pos::{MultiSpan, Span}; @@ -217,15 +217,15 @@ impl<'a> Resolver<'a> { parent_scope.expect("no parent scope for a single-segment import"); if ns == TypeNS { - if ident.name == keywords::Crate.name() || - ident.name == keywords::DollarCrate.name() { + if ident.name == kw::Crate || + ident.name == kw::DollarCrate { let module = self.resolve_crate_root(ident); let binding = (module, ty::Visibility::Public, module.span, Mark::root()) .to_name_binding(self.arenas); return Ok(binding); - } else if ident.name == keywords::Super.name() || - ident.name == keywords::SelfLower.name() { + } else if ident.name == kw::Super || + ident.name == kw::SelfLower { // FIXME: Implement these with renaming requirements so that e.g. // `use super;` doesn't work, but `use super as name;` does. // Fall through here to get an error from `early_resolve_...`. @@ -992,7 +992,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { // HACK(eddyb) `lint_if_path_starts_with_module` needs at least // 2 segments, so the `resolve_path` above won't trigger it. let mut full_path = directive.module_path.clone(); - full_path.push(Segment::from_ident(keywords::Invalid.ident())); + full_path.push(Segment::from_ident(Ident::with_empty_ctxt(kw::Invalid))); self.lint_if_path_starts_with_module( directive.crate_lint(), &full_path, @@ -1484,8 +1484,8 @@ fn import_path_to_string(names: &[Ident], subclass: &ImportDirectiveSubclass<'_>, span: Span) -> String { let pos = names.iter() - .position(|p| span == p.span && p.name != keywords::PathRoot.name()); - let global = !names.is_empty() && names[0].name == keywords::PathRoot.name(); + .position(|p| span == p.span && p.name != kw::PathRoot); + let global = !names.is_empty() && names[0].name == kw::PathRoot; if let Some(pos) = pos { let names = if global { &names[1..pos + 1] } else { &names[..pos + 1] }; names_to_string(names) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 362b6f0504d9..a20a91b3e6f6 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -123,7 +123,7 @@ use syntax::attr; use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax::ptr::P; use syntax::source_map::{DUMMY_SP, original_sp}; -use syntax::symbol::{Symbol, LocalInternedString, keywords, sym}; +use syntax::symbol::{Symbol, LocalInternedString, kw, sym}; use syntax::util::lev_distance::find_best_match_for_name; use std::cell::{Cell, RefCell, Ref, RefMut}; @@ -3290,7 +3290,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Ok(method) } Err(error) => { - if segment.ident.name != keywords::Invalid.name() { + if segment.ident.name != kw::Invalid { self.report_method_error(span, rcvr_t, segment.ident, @@ -3402,7 +3402,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } err.emit(); field_ty - } else if field.name == keywords::Invalid.name() { + } else if field.name == kw::Invalid { self.tcx().types.err } else if self.method_exists(field, expr_t, expr.hir_id, true) { let mut err = type_error_struct!(self.tcx().sess, field.span, expr_t, E0615, @@ -4672,7 +4672,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { method::MethodError::PrivateMatch(kind, def_id, _) => Ok((kind, def_id)), _ => Err(ErrorReported), }; - if item_name.name != keywords::Invalid.name() { + if item_name.name != kw::Invalid { self.report_method_error( span, ty, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 7adf86a99bd4..2a4d8f304b59 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -39,7 +39,7 @@ use syntax::ast::{Ident, MetaItemKind}; use syntax::attr::{InlineAttr, OptimizeAttr, list_contains_name, mark_used}; use syntax::source_map::Spanned; use syntax::feature_gate; -use syntax::symbol::{InternedString, keywords, Symbol, sym}; +use syntax::symbol::{InternedString, kw, Symbol, sym}; use syntax_pos::{Span, DUMMY_SP}; use rustc::hir::def::{CtorKind, Res, DefKind}; @@ -939,7 +939,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty opt_self = Some(ty::GenericParamDef { index: 0, - name: keywords::SelfUpper.name().as_interned_str(), + name: kw::SelfUpper.as_interned_str(), def_id: tcx.hir().local_def_id_from_hir_id(param_id), pure_wrt_drop: false, kind: ty::GenericParamDefKind::Type { @@ -1008,7 +1008,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty synthetic, .. } => { - if param.name.ident().name == keywords::SelfUpper.name() { + if param.name.ident().name == kw::SelfUpper { span_bug!( param.span, "`Self` should not be the name of a regular parameter" @@ -1038,7 +1038,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty } } GenericParamKind::Const { .. } => { - if param.name.ident().name == keywords::SelfUpper.name() { + if param.name.ident().name == kw::SelfUpper { span_bug!( param.span, "`Self` should not be the name of a regular parameter", diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 6d03a5ad63bb..1bbbe581c3ce 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -31,8 +31,7 @@ use syntax::attr; use syntax::ext::base::MacroKind; use syntax::source_map::{dummy_spanned, Spanned}; use syntax::ptr::P; -use syntax::symbol::keywords::{self, Keyword}; -use syntax::symbol::{Symbol, sym}; +use syntax::symbol::{Symbol, kw, sym}; use syntax::symbol::InternedString; use syntax_pos::{self, Pos, FileName}; @@ -43,7 +42,6 @@ use std::default::Default; use std::{mem, slice, vec}; use std::iter::{FromIterator, once}; use std::rc::Rc; -use std::str::FromStr; use std::cell::RefCell; use std::sync::Arc; use std::u32; @@ -309,10 +307,9 @@ impl Clean for CrateNum { for attr in attrs.lists(sym::doc) { if let Some(v) = attr.value_str() { if attr.check_name(sym::keyword) { - keyword = Keyword::from_str(&v.as_str()).ok() - .map(|x| x.name().to_string()); - if keyword.is_some() { - break + if v.is_doc_keyword() { + keyword = Some(v.to_string()); + break; } // FIXME: should warn on unknown keywords? } @@ -1702,7 +1699,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, let stripped_typarams = gens.params.iter().filter_map(|param| match param.kind { ty::GenericParamDefKind::Lifetime => None, ty::GenericParamDefKind::Type { .. } => { - if param.name.as_symbol() == keywords::SelfUpper.name() { + if param.name.as_symbol() == kw::SelfUpper { assert_eq!(param.index, 0); return None; } @@ -3596,7 +3593,7 @@ fn qpath_to_string(p: &hir::QPath) -> String { if i > 0 { s.push_str("::"); } - if seg.ident.name != keywords::PathRoot.name() { + if seg.ident.name != kw::PathRoot { s.push_str(&*seg.ident.as_str()); } } @@ -4176,7 +4173,7 @@ fn resolve_type(cx: &DocContext<'_>, hir::Float(float_ty) => return Primitive(float_ty.into()), }, Res::SelfTy(..) if path.segments.len() == 1 => { - return Generic(keywords::SelfUpper.name().to_string()); + return Generic(kw::SelfUpper.to_string()); } Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => { return Generic(format!("{:#}", path)); diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index ae0bd1aafa8f..71d8665f3b30 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -44,7 +44,7 @@ pub fn render( \ \ \ - \ + \ {title}\ \ , } @@ -100,7 +100,7 @@ impl Path { } pub fn is_global(&self) -> bool { - !self.segments.is_empty() && self.segments[0].ident.name == keywords::PathRoot.name() + !self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot } } @@ -128,7 +128,7 @@ impl PathSegment { PathSegment { ident, id: DUMMY_NODE_ID, args: None } } pub fn path_root(span: Span) -> Self { - PathSegment::from_ident(Ident::new(keywords::PathRoot.name(), span)) + PathSegment::from_ident(Ident::new(kw::PathRoot, span)) } } @@ -1782,7 +1782,7 @@ pub type ExplicitSelf = Spanned; impl Arg { pub fn to_self(&self) -> Option { if let PatKind::Ident(BindingMode::ByValue(mutbl), ident, _) = self.pat.node { - if ident.name == keywords::SelfLower.name() { + if ident.name == kw::SelfLower { return match self.ty.node { TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))), TyKind::Rptr(lt, MutTy { ref ty, mutbl }) if ty.node.is_implicit_self() => { @@ -1800,7 +1800,7 @@ impl Arg { pub fn is_self(&self) -> bool { if let PatKind::Ident(_, ident, _) = self.pat.node { - ident.name == keywords::SelfLower.name() + ident.name == kw::SelfLower } else { false } diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 592b40df1764..3e93ac23a531 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -22,7 +22,7 @@ use crate::parse::parser::Parser; use crate::parse::{self, ParseSess, PResult}; use crate::parse::token::{self, Token}; use crate::ptr::P; -use crate::symbol::{keywords, Symbol, sym}; +use crate::symbol::{kw, sym, Symbol}; use crate::ThinVec; use crate::tokenstream::{TokenStream, TokenTree, DelimSpan}; use crate::GLOBALS; @@ -90,7 +90,7 @@ impl NestedMetaItem { self.meta_item().and_then(|meta_item| meta_item.ident()) } pub fn name_or_empty(&self) -> Symbol { - self.ident().unwrap_or(keywords::Invalid.ident()).name + self.ident().unwrap_or(Ident::invalid()).name } /// Gets the string value if self is a MetaItem and the MetaItem is a @@ -168,7 +168,7 @@ impl Attribute { } } pub fn name_or_empty(&self) -> Symbol { - self.ident().unwrap_or(keywords::Invalid.ident()).name + self.ident().unwrap_or(Ident::invalid()).name } pub fn value_str(&self) -> Option { @@ -206,7 +206,7 @@ impl MetaItem { } } pub fn name_or_empty(&self) -> Symbol { - self.ident().unwrap_or(keywords::Invalid.ident()).name + self.ident().unwrap_or(Ident.invalid()).name } // #[attribute(name = "value")] diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index c988dc61bec4..e9476e2fdfd5 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -7,7 +7,7 @@ use crate::ext::base::{ExtCtxt, MacEager, MacResult}; use crate::ext::build::AstBuilder; use crate::parse::token; use crate::ptr::P; -use crate::symbol::keywords; +use crate::symbol::kw; use crate::tokenstream::{TokenTree}; use smallvec::smallvec; @@ -185,7 +185,7 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt<'_>, (descriptions.len(), ecx.expr_vec(span, descriptions)) }); - let static_ = ecx.lifetime(span, keywords::StaticLifetime.ident()); + let static_ = ecx.lifetime(span, Ident::with_empty_ctxt(kw::StaticLifetime)); let ty_str = ecx.ty_rptr( span, ecx.ty_ident(span, ecx.ident_of("str")), diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 489fac4f1ca4..f1a20d540657 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -10,7 +10,7 @@ use crate::mut_visit::{self, MutVisitor}; use crate::parse::{self, parser, DirectoryOwnership}; use crate::parse::token; use crate::ptr::P; -use crate::symbol::{keywords, Ident, Symbol, sym}; +use crate::symbol::{kw, sym, Ident, Symbol}; use crate::ThinVec; use crate::tokenstream::{self, TokenStream}; @@ -971,7 +971,7 @@ impl<'a> ExtCtxt<'a> { } pub fn std_path(&self, components: &[&str]) -> Vec { let def_site = DUMMY_SP.apply_mark(self.current_expansion.mark); - iter::once(Ident::new(keywords::DollarCrate.name(), def_site)) + iter::once(Ident::new(kw::DollarCrate, def_site)) .chain(components.iter().map(|s| self.ident_of(s))) .collect() } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index d24106f697e1..77d5fa238f21 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -3,7 +3,7 @@ use crate::attr; use crate::source_map::{dummy_spanned, respan, Spanned}; use crate::ext::base::ExtCtxt; use crate::ptr::P; -use crate::symbol::{Symbol, keywords}; +use crate::symbol::{Symbol, kw}; use crate::ThinVec; use rustc_target::spec::abi::Abi; @@ -628,7 +628,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.expr_path(self.path_ident(span, id)) } fn expr_self(&self, span: Span) -> P { - self.expr_ident(span, keywords::SelfLower.ident()) + self.expr_ident(span, Ident::with_empty_ctxt(kw::SelfLower)) } fn expr_binary(&self, sp: Span, op: ast::BinOpKind, @@ -1175,7 +1175,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { vis: ast::Visibility, vp: P) -> P { P(ast::Item { id: ast::DUMMY_NODE_ID, - ident: keywords::Invalid.ident(), + ident: Ident::with_empty_ctxt(kw::Invalid), attrs: vec![], node: ast::ItemKind::Use(vp), vis, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 478ae4de82b7..5f9c84c61265 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -14,7 +14,7 @@ use crate::parse::token::{self, Token}; use crate::parse::parser::Parser; use crate::ptr::P; use crate::symbol::Symbol; -use crate::symbol::{keywords, sym}; +use crate::symbol::{kw, sym}; use crate::tokenstream::{TokenStream, TokenTree}; use crate::visit::{self, Visitor}; use crate::util::map_in_place::MapInPlace; @@ -198,7 +198,7 @@ fn macro_bang_format(path: &ast::Path) -> ExpnFormat { if i != 0 { path_str.push_str("::"); } - if segment.ident.name != keywords::PathRoot.name() { + if segment.ident.name != kw::PathRoot { path_str.push_str(&segment.ident.as_str()) } } @@ -271,7 +271,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { attrs: krate.attrs, span: krate.span, node: ast::ItemKind::Mod(krate.module), - ident: keywords::Invalid.ident(), + ident: Ident::with_empty_ctxt(kw::Invalid), id: ast::DUMMY_NODE_ID, vis: respan(krate.span.shrink_to_lo(), ast::VisibilityKind::Public), tokens: None, @@ -708,7 +708,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }; let path = &mac.node.path; - let ident = ident.unwrap_or_else(|| keywords::Invalid.ident()); + let ident = ident.unwrap_or_else(|| Ident::with_empty_ctxt(kw::Invalid)); let validate_and_set_expn_info = |this: &mut Self, // arg instead of capture def_site_span: Option, allow_internal_unstable, @@ -736,7 +736,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } - if ident.name != keywords::Invalid.name() { + if ident.name != kw::Invalid { let msg = format!("macro {}! expects no ident argument, given '{}'", path, ident); this.cx.span_err(path.span, &msg); this.cx.trace_macros_diag(); @@ -792,7 +792,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } IdentTT { ref expander, span: tt_span, ref allow_internal_unstable } => { - if ident.name == keywords::Invalid.name() { + if ident.name == kw::Invalid { self.cx.span_err(path.span, &format!("macro {}! expects an ident argument", path)); self.cx.trace_macros_diag(); @@ -828,7 +828,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } SyntaxExtension::ProcMacro { ref expander, ref allow_internal_unstable, edition } => { - if ident.name != keywords::Invalid.name() { + if ident.name != kw::Invalid { let msg = format!("macro {}! expects no ident argument, given '{}'", path, ident); self.cx.span_err(path.span, &msg); @@ -929,7 +929,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { invoc.expansion_data.mark.set_expn_info(expn_info); let span = span.with_ctxt(self.cx.backtrace()); let dummy = ast::MetaItem { // FIXME(jseyfried) avoid this - path: Path::from_ident(keywords::Invalid.ident()), + path: Path::from_ident(Ident::with_empty_ctxt(kw::Invalid)), span: DUMMY_SP, node: ast::MetaItemKind::Word, }; @@ -1338,7 +1338,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { }) } ast::ItemKind::Mod(ast::Mod { inner, .. }) => { - if item.ident == keywords::Invalid.ident() { + if item.ident == Ident::with_empty_ctxt(kw::Invalid) { return noop_flat_map_item(item, self); } diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs index f5e18e98436e..9ba1ff0ec7ea 100644 --- a/src/libsyntax/ext/placeholders.rs +++ b/src/libsyntax/ext/placeholders.rs @@ -6,7 +6,7 @@ use crate::ext::hygiene::Mark; use crate::tokenstream::TokenStream; use crate::mut_visit::*; use crate::ptr::P; -use crate::symbol::keywords; +use crate::symbol::kw; use crate::ThinVec; use smallvec::{smallvec, SmallVec}; @@ -22,7 +22,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment { }) } - let ident = keywords::Invalid.ident(); + let ident = ast::Ident::with_empty_ctxt(kw::Invalid); let attrs = Vec::new(); let generics = ast::Generics::default(); let vis = dummy_spanned(ast::VisibilityKind::Inherited); diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 084a69f4cda0..fa1f85c0e7b5 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -80,7 +80,7 @@ use crate::parse::{Directory, ParseSess}; use crate::parse::parser::{Parser, PathStyle}; use crate::parse::token::{self, DocComment, Nonterminal, Token}; use crate::print::pprust; -use crate::symbol::keywords; +use crate::symbol::kw; use crate::tokenstream::{DelimSpan, TokenStream}; use errors::FatalError; @@ -382,7 +382,7 @@ fn nameize>( TokenTree::Delimited(_, ref delim) => for next_m in &delim.tts { n_rec(sess, next_m, res.by_ref(), ret_val)?; }, - TokenTree::MetaVarDecl(span, _, id) if id.name == keywords::Invalid.name() => { + TokenTree::MetaVarDecl(span, _, id) if id.name == kw::Invalid => { if sess.missing_fragment_specifiers.borrow_mut().remove(&span) { return Err((span, "missing fragment specifier".to_string())); } @@ -587,7 +587,7 @@ fn inner_parse_loop<'root, 'tt>( } // We need to match a metavar (but the identifier is invalid)... this is an error - TokenTree::MetaVarDecl(span, _, id) if id.name == keywords::Invalid.name() => { + TokenTree::MetaVarDecl(span, _, id) if id.name == kw::Invalid => { if sess.missing_fragment_specifiers.borrow_mut().remove(&span) { return Error(span, "missing fragment specifier".to_string()); } @@ -802,7 +802,7 @@ pub fn parse( /// We prohibit passing `_` to macros expecting `ident` for now. fn get_macro_ident(token: &Token) -> Option<(Ident, bool)> { match *token { - token::Ident(ident, is_raw) if ident.name != keywords::Underscore.name() => + token::Ident(ident, is_raw) if ident.name != kw::Underscore => Some((ident, is_raw)), _ => None, } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 672b7b428552..8adee4be75fb 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -1107,7 +1107,7 @@ fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> IsInFollow { _ => IsInFollow::No(tokens), } }, - "" => IsInFollow::Yes, // keywords::Invalid + "" => IsInFollow::Yes, // kw::Invalid _ => IsInFollow::Invalid(format!("invalid fragment specifier `{}`", frag), VALID_FRAGMENT_NAMES_MSG), } diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index ed8395f11ad5..2f1a98346744 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -6,7 +6,7 @@ use crate::parse::{token, ParseSess}; use crate::print::pprust; use crate::tokenstream::{self, DelimSpan}; use crate::ast; -use crate::symbol::keywords; +use crate::symbol::kw; use syntax_pos::{edition::Edition, BytePos, Span}; @@ -228,7 +228,7 @@ pub fn parse( result.push(TokenTree::MetaVarDecl( span, ident, - keywords::Invalid.ident(), + ast::Ident::with_empty_ctxt(kw::Invalid), )); } @@ -319,8 +319,8 @@ where Some(tokenstream::TokenTree::Token(ident_span, ref token)) if token.is_ident() => { let (ident, is_raw) = token.ident().unwrap(); let span = ident_span.with_lo(span.lo()); - if ident.name == keywords::Crate.name() && !is_raw { - let ident = ast::Ident::new(keywords::DollarCrate.name(), ident.span); + if ident.name == kw::Crate && !is_raw { + let ident = ast::Ident::new(kw::DollarCrate, ident.span); TokenTree::Token(span, token::Ident(ident, is_raw)) } else { TokenTree::MetaVar(span, ident) @@ -334,7 +334,7 @@ where pprust::token_to_string(&tok) ); sess.span_diagnostic.span_err(span, &msg); - TokenTree::MetaVar(span, keywords::Invalid.ident()) + TokenTree::MetaVar(span, ast::Ident::with_empty_ctxt(kw::Invalid)) } // There are no more tokens. Just return the `$` we already have. diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 8fdd15a029f1..8dae4756c82c 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -11,7 +11,7 @@ use crate::ast::*; use crate::source_map::{Spanned, respan}; use crate::parse::token::{self, Token}; use crate::ptr::P; -use crate::symbol::keywords; +use crate::symbol::kw; use crate::ThinVec; use crate::tokenstream::*; use crate::util::map_in_place::MapInPlace; @@ -977,7 +977,7 @@ pub fn noop_visit_mod(Mod { inner, items, inline: _ }: &mut Mod, pub fn noop_visit_crate(krate: &mut Crate, vis: &mut T) { visit_clobber(krate, |Crate { module, attrs, span }| { let item = P(Item { - ident: keywords::Invalid.ident(), + ident: Ident::with_empty_ctxt(kw::Invalid), attrs, id: DUMMY_NODE_ID, vis: respan(span.shrink_to_lo(), VisibilityKind::Public), diff --git a/src/libsyntax/parse/literal.rs b/src/libsyntax/parse/literal.rs index 53195421ddce..6db1a6694936 100644 --- a/src/libsyntax/parse/literal.rs +++ b/src/libsyntax/parse/literal.rs @@ -6,7 +6,7 @@ use crate::parse::PResult; use crate::parse::token::{self, Token}; use crate::parse::unescape::{unescape_str, unescape_char, unescape_byte_str, unescape_byte}; use crate::print::pprust; -use crate::symbol::{keywords, Symbol}; +use crate::symbol::{kw, Symbol}; use crate::tokenstream::{TokenStream, TokenTree}; use errors::{Applicability, Handler}; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 24d120376def..0099dd3d3c8e 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -46,7 +46,7 @@ use crate::ptr::P; use crate::parse::PResult; use crate::ThinVec; use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint}; -use crate::symbol::{keywords, sym, Symbol}; +use crate::symbol::{kw, sym, Symbol}; use errors::{Applicability, DiagnosticBuilder, DiagnosticId, FatalError}; use rustc_target::spec::abi::{self, Abi}; @@ -379,7 +379,7 @@ impl TokenCursor { #[derive(Clone, PartialEq)] crate enum TokenType { Token(token::Token), - Keyword(keywords::Keyword), + Keyword(Symbol), Operator, Lifetime, Ident, @@ -392,7 +392,7 @@ impl TokenType { crate fn to_string(&self) -> String { match *self { TokenType::Token(ref t) => format!("`{}`", pprust::token_to_string(t)), - TokenType::Keyword(kw) => format!("`{}`", kw.name()), + TokenType::Keyword(kw) => format!("`{}`", kw), TokenType::Operator => "an operator".to_string(), TokenType::Lifetime => "lifetime".to_string(), TokenType::Ident => "identifier".to_string(), @@ -510,7 +510,7 @@ impl From> for LhsExpr { /// Creates a placeholder argument. fn dummy_arg(span: Span) -> Arg { - let ident = Ident::new(keywords::Invalid.name(), span); + let ident = Ident::new(kw::Invalid, span); let pat = P(Pat { id: ast::DUMMY_NODE_ID, node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None), @@ -771,15 +771,15 @@ impl<'a> Parser<'a> { TokenType::Token(token::Semi) => true, // we expect a `;` here _ => false, }) && ( // a `;` would be expected before the current keyword - self.token.is_keyword(keywords::Break) || - self.token.is_keyword(keywords::Continue) || - self.token.is_keyword(keywords::For) || - self.token.is_keyword(keywords::If) || - self.token.is_keyword(keywords::Let) || - self.token.is_keyword(keywords::Loop) || - self.token.is_keyword(keywords::Match) || - self.token.is_keyword(keywords::Return) || - self.token.is_keyword(keywords::While) + self.token.is_keyword(kw::Break) || + self.token.is_keyword(kw::Continue) || + self.token.is_keyword(kw::For) || + self.token.is_keyword(kw::If) || + self.token.is_keyword(kw::Let) || + self.token.is_keyword(kw::Loop) || + self.token.is_keyword(kw::Match) || + self.token.is_keyword(kw::Return) || + self.token.is_keyword(kw::While) ); let cm = self.sess.source_map(); match (cm.lookup_line(self.span.lo()), cm.lookup_line(sp.lo())) { @@ -913,14 +913,14 @@ impl<'a> Parser<'a> { is_present } - fn check_keyword(&mut self, kw: keywords::Keyword) -> bool { + fn check_keyword(&mut self, kw: Symbol) -> bool { self.expected_tokens.push(TokenType::Keyword(kw)); self.token.is_keyword(kw) } /// If the next token is the given keyword, eats it and returns /// `true`. Otherwise, returns `false`. - pub fn eat_keyword(&mut self, kw: keywords::Keyword) -> bool { + pub fn eat_keyword(&mut self, kw: Symbol) -> bool { if self.check_keyword(kw) { self.bump(); true @@ -929,7 +929,7 @@ impl<'a> Parser<'a> { } } - fn eat_keyword_noexpect(&mut self, kw: keywords::Keyword) -> bool { + fn eat_keyword_noexpect(&mut self, kw: Symbol) -> bool { if self.token.is_keyword(kw) { self.bump(); true @@ -941,7 +941,7 @@ impl<'a> Parser<'a> { /// If the given word is not a keyword, signals an error. /// If the next token is not the given word, signals an error. /// Otherwise, eats it. - fn expect_keyword(&mut self, kw: keywords::Keyword) -> PResult<'a, ()> { + fn expect_keyword(&mut self, kw: Symbol) -> PResult<'a, ()> { if !self.eat_keyword(kw) { self.unexpected() } else { @@ -1375,9 +1375,9 @@ impl<'a> Parser<'a> { /// Is the current token one of the keywords that signals a bare function type? fn token_is_bare_fn_keyword(&mut self) -> bool { - self.check_keyword(keywords::Fn) || - self.check_keyword(keywords::Unsafe) || - self.check_keyword(keywords::Extern) + self.check_keyword(kw::Fn) || + self.check_keyword(kw::Unsafe) || + self.check_keyword(kw::Extern) } /// Parses a `TyKind::BareFn` type. @@ -1395,13 +1395,13 @@ impl<'a> Parser<'a> { */ let unsafety = self.parse_unsafety(); - let abi = if self.eat_keyword(keywords::Extern) { + let abi = if self.eat_keyword(kw::Extern) { self.parse_opt_abi()?.unwrap_or(Abi::C) } else { Abi::Rust }; - self.expect_keyword(keywords::Fn)?; + self.expect_keyword(kw::Fn)?; let (inputs, c_variadic) = self.parse_fn_args(false, true)?; let ret_ty = self.parse_ret_ty(false)?; let decl = P(FnDecl { @@ -1419,7 +1419,7 @@ impl<'a> Parser<'a> { /// Parses asyncness: `async` or nothing. fn parse_asyncness(&mut self) -> IsAsync { - if self.eat_keyword(keywords::Async) { + if self.eat_keyword(kw::Async) { IsAsync::Async { closure_id: ast::DUMMY_NODE_ID, return_impl_trait_id: ast::DUMMY_NODE_ID, @@ -1432,7 +1432,7 @@ impl<'a> Parser<'a> { /// Parses unsafety: `unsafe` or nothing. fn parse_unsafety(&mut self) -> Unsafety { - if self.eat_keyword(keywords::Unsafe) { + if self.eat_keyword(kw::Unsafe) { Unsafety::Unsafe } else { Unsafety::Normal @@ -1462,10 +1462,10 @@ impl<'a> Parser<'a> { mut attrs: Vec) -> PResult<'a, TraitItem> { let lo = self.span; self.eat_bad_pub(); - let (name, node, generics) = if self.eat_keyword(keywords::Type) { + let (name, node, generics) = if self.eat_keyword(kw::Type) { self.parse_trait_item_assoc_ty()? } else if self.is_const_item() { - self.expect_keyword(keywords::Const)?; + self.expect_keyword(kw::Const)?; let ident = self.parse_ident()?; self.expect(&token::Colon)?; let ty = self.parse_ty()?; @@ -1480,7 +1480,9 @@ impl<'a> Parser<'a> { (ident, TraitItemKind::Const(ty, default), ast::Generics::default()) } else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? { // trait item macro. - (keywords::Invalid.ident(), ast::TraitItemKind::Macro(mac), ast::Generics::default()) + (Ident::with_empty_ctxt(kw::Invalid), + ast::TraitItemKind::Macro(mac), + ast::Generics::default()) } else { let (constness, unsafety, mut asyncness, abi) = self.parse_fn_front_matter()?; @@ -1654,7 +1656,7 @@ impl<'a> Parser<'a> { // Reference self.expect_and()?; self.parse_borrowed_pointee()? - } else if self.eat_keyword_noexpect(keywords::Typeof) { + } else if self.eat_keyword_noexpect(kw::Typeof) { // `typeof(EXPR)` // In order to not be ambiguous, the type must be surrounded by parens. self.expect(&token::OpenDelim(token::Paren))?; @@ -1664,13 +1666,13 @@ impl<'a> Parser<'a> { }; self.expect(&token::CloseDelim(token::Paren))?; TyKind::Typeof(e) - } else if self.eat_keyword(keywords::Underscore) { + } else if self.eat_keyword(kw::Underscore) { // A type to be inferred `_` TyKind::Infer } else if self.token_is_bare_fn_keyword() { // Function pointer type self.parse_ty_bare_fn(Vec::new())? - } else if self.check_keyword(keywords::For) { + } else if self.check_keyword(kw::For) { // Function pointer type or bound list (trait object type) starting with a poly-trait. // `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T` // `for<'lt> Trait1<'lt> + Trait2 + 'a` @@ -1683,12 +1685,12 @@ impl<'a> Parser<'a> { let parse_plus = allow_plus && self.check_plus(); self.parse_remaining_bounds(lifetime_defs, path, lo, parse_plus)? } - } else if self.eat_keyword(keywords::Impl) { + } else if self.eat_keyword(kw::Impl) { // Always parse bounds greedily for better error recovery. let bounds = self.parse_generic_bounds(None)?; impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus; TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds) - } else if self.check_keyword(keywords::Dyn) && + } else if self.check_keyword(kw::Dyn) && (self.span.rust_2018() || self.look_ahead(1, |t| t.can_begin_bound() && !can_continue_type_after_non_fn_ident(t))) { @@ -1766,9 +1768,9 @@ impl<'a> Parser<'a> { } fn parse_ptr(&mut self) -> PResult<'a, MutTy> { - let mutbl = if self.eat_keyword(keywords::Mut) { + let mutbl = if self.eat_keyword(kw::Mut) { Mutability::Mutable - } else if self.eat_keyword(keywords::Const) { + } else if self.eat_keyword(kw::Const) { Mutability::Immutable } else { let span = self.prev_span; @@ -1790,7 +1792,7 @@ impl<'a> Parser<'a> { _ => 0, } token::BinOp(token::And) | token::AndAnd => 1, - _ if self.token.is_keyword(keywords::Mut) => 1, + _ if self.token.is_keyword(kw::Mut) => 1, _ => 0, }; @@ -1891,7 +1893,7 @@ impl<'a> Parser<'a> { } match ty { Ok(ty) => { - let ident = Ident::new(keywords::Invalid.name(), self.prev_span); + let ident = Ident::new(kw::Invalid, self.prev_span); let pat = P(Pat { id: ast::DUMMY_NODE_ID, node: PatKind::Ident( @@ -2006,7 +2008,7 @@ impl<'a> Parser<'a> { fn parse_ident_or_underscore(&mut self) -> PResult<'a, ast::Ident> { match self.token { - token::Ident(ident, false) if ident.name == keywords::Underscore.name() => { + token::Ident(ident, false) if ident.name == kw::Underscore => { let span = self.span; self.bump(); Ok(Ident::new(ident.name, span)) @@ -2034,7 +2036,7 @@ impl<'a> Parser<'a> { // above). `path_span` has the span of that path, or an empty // span in the case of something like `::Bar`. let (mut path, path_span); - if self.eat_keyword(keywords::As) { + if self.eat_keyword(kw::As) { let path_lo = self.span; path = self.parse_path(PathStyle::Type)?; path_span = path_lo.to(self.prev_span); @@ -2233,7 +2235,7 @@ impl<'a> Parser<'a> { /// Parses mutability (`mut` or nothing). fn parse_mutability(&mut self) -> Mutability { - if self.eat_keyword(keywords::Mut) { + if self.eat_keyword(kw::Mut) { Mutability::Mutable } else { Mutability::Immutable @@ -2465,37 +2467,37 @@ impl<'a> Parser<'a> { hi = path.span; return Ok(self.mk_expr(lo.to(hi), ExprKind::Path(Some(qself), path), attrs)); } - if self.span.rust_2018() && self.check_keyword(keywords::Async) { + if self.span.rust_2018() && self.check_keyword(kw::Async) { return if self.is_async_block() { // check for `async {` and `async move {` self.parse_async_block(attrs) } else { self.parse_lambda_expr(attrs) }; } - if self.check_keyword(keywords::Move) || self.check_keyword(keywords::Static) { + if self.check_keyword(kw::Move) || self.check_keyword(kw::Static) { return self.parse_lambda_expr(attrs); } - if self.eat_keyword(keywords::If) { + if self.eat_keyword(kw::If) { return self.parse_if_expr(attrs); } - if self.eat_keyword(keywords::For) { + if self.eat_keyword(kw::For) { let lo = self.prev_span; return self.parse_for_expr(None, lo, attrs); } - if self.eat_keyword(keywords::While) { + if self.eat_keyword(kw::While) { let lo = self.prev_span; return self.parse_while_expr(None, lo, attrs); } if let Some(label) = self.eat_label() { let lo = label.ident.span; self.expect(&token::Colon)?; - if self.eat_keyword(keywords::While) { + if self.eat_keyword(kw::While) { return self.parse_while_expr(Some(label), lo, attrs) } - if self.eat_keyword(keywords::For) { + if self.eat_keyword(kw::For) { return self.parse_for_expr(Some(label), lo, attrs) } - if self.eat_keyword(keywords::Loop) { + if self.eat_keyword(kw::Loop) { return self.parse_loop_expr(Some(label), lo, attrs) } if self.token == token::OpenDelim(token::Brace) { @@ -2509,24 +2511,24 @@ impl<'a> Parser<'a> { err.span_label(self.span, msg); return Err(err); } - if self.eat_keyword(keywords::Loop) { + if self.eat_keyword(kw::Loop) { let lo = self.prev_span; return self.parse_loop_expr(None, lo, attrs); } - if self.eat_keyword(keywords::Continue) { + if self.eat_keyword(kw::Continue) { let label = self.eat_label(); let ex = ExprKind::Continue(label); let hi = self.prev_span; return Ok(self.mk_expr(lo.to(hi), ex, attrs)); } - if self.eat_keyword(keywords::Match) { + if self.eat_keyword(kw::Match) { let match_sp = self.prev_span; return self.parse_match_expr(attrs).map_err(|mut err| { err.span_label(match_sp, "while parsing this match expression"); err }); } - if self.eat_keyword(keywords::Unsafe) { + if self.eat_keyword(kw::Unsafe) { return self.parse_block_expr( None, lo, @@ -2540,10 +2542,10 @@ impl<'a> Parser<'a> { } if self.is_try_block() { let lo = self.span; - assert!(self.eat_keyword(keywords::Try)); + assert!(self.eat_keyword(kw::Try)); return self.parse_try_block(lo, attrs); } - if self.eat_keyword(keywords::Return) { + if self.eat_keyword(kw::Return) { if self.token.can_begin_expr() { let e = self.parse_expr()?; hi = e.span; @@ -2551,7 +2553,7 @@ impl<'a> Parser<'a> { } else { ex = ExprKind::Ret(None); } - } else if self.eat_keyword(keywords::Break) { + } else if self.eat_keyword(kw::Break) { let label = self.eat_label(); let e = if self.token.can_begin_expr() && !(self.token == token::OpenDelim(token::Brace) @@ -2563,7 +2565,7 @@ impl<'a> Parser<'a> { }; ex = ExprKind::Break(label, e); hi = self.prev_span; - } else if self.eat_keyword(keywords::Yield) { + } else if self.eat_keyword(kw::Yield) { if self.token.can_begin_expr() { let e = self.parse_expr()?; hi = e.span; @@ -2571,14 +2573,14 @@ impl<'a> Parser<'a> { } else { ex = ExprKind::Yield(None); } - } else if self.token.is_keyword(keywords::Let) { + } else if self.token.is_keyword(kw::Let) { // Catch this syntax error here, instead of in `parse_ident`, so // that we can explicitly mention that let is not to be used as an expression let mut db = self.fatal("expected expression, found statement (`let`)"); db.span_label(self.span, "expected expression"); db.note("variable declaration using `let` is a statement"); return Err(db); - } else if self.span.rust_2018() && self.eat_keyword(keywords::Await) { + } else if self.span.rust_2018() && self.eat_keyword(kw::Await) { let (await_hi, e_kind) = self.parse_await_macro_or_alt(lo, self.prev_span)?; hi = await_hi; ex = e_kind; @@ -2879,7 +2881,7 @@ impl<'a> Parser<'a> { // Assuming we have just parsed `.`, continue parsing into an expression. fn parse_dot_suffix(&mut self, self_arg: P, lo: Span) -> PResult<'a, P> { - if self.span.rust_2018() && self.eat_keyword(keywords::Await) { + if self.span.rust_2018() && self.eat_keyword(kw::Await) { let span = lo.to(self.prev_span); let await_expr = self.mk_expr( span, @@ -3250,7 +3252,7 @@ impl<'a> Parser<'a> { let (span, e) = self.interpolated_or_expr_span(e)?; (lo.to(span), ExprKind::AddrOf(m, e)) } - token::Ident(..) if self.token.is_keyword(keywords::In) => { + token::Ident(..) if self.token.is_keyword(kw::In) => { self.bump(); let place = self.parse_expr_res( Restrictions::NO_STRUCT_LITERAL, @@ -3261,7 +3263,7 @@ impl<'a> Parser<'a> { let blk_expr = self.mk_expr(span, ExprKind::Block(blk, None), ThinVec::new()); (lo.to(span), ExprKind::ObsoleteInPlace(place, blk_expr)) } - token::Ident(..) if self.token.is_keyword(keywords::Box) => { + token::Ident(..) if self.token.is_keyword(kw::Box) => { self.bump(); let e = self.parse_prefix_expr(None); let (span, e) = self.interpolated_or_expr_span(e)?; @@ -3683,7 +3685,7 @@ impl<'a> Parser<'a> { /// Parses an `if` or `if let` expression (`if` token already eaten). fn parse_if_expr(&mut self, attrs: ThinVec) -> PResult<'a, P> { - if self.check_keyword(keywords::Let) { + if self.check_keyword(kw::Let) { return self.parse_if_let_expr(attrs); } let lo = self.prev_span; @@ -3693,7 +3695,7 @@ impl<'a> Parser<'a> { // verify that the last statement is either an implicit return (no `;`) or an explicit // return. This won't catch blocks with an explicit `return`, but that would be caught by // the dead code lint. - if self.eat_keyword(keywords::Else) || !cond.returns() { + if self.eat_keyword(kw::Else) || !cond.returns() { let sp = self.sess.source_map().next_point(lo); let mut err = self.diagnostic() .struct_span_err(sp, "missing condition for `if` statemement"); @@ -3709,7 +3711,7 @@ impl<'a> Parser<'a> { })?; let mut els: Option> = None; let mut hi = thn.span; - if self.eat_keyword(keywords::Else) { + if self.eat_keyword(kw::Else) { let elexpr = self.parse_else_expr()?; hi = elexpr.span; els = Some(elexpr); @@ -3721,12 +3723,12 @@ impl<'a> Parser<'a> { fn parse_if_let_expr(&mut self, attrs: ThinVec) -> PResult<'a, P> { let lo = self.prev_span; - self.expect_keyword(keywords::Let)?; + self.expect_keyword(kw::Let)?; let pats = self.parse_pats()?; self.expect(&token::Eq)?; let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; let thn = self.parse_block()?; - let (hi, els) = if self.eat_keyword(keywords::Else) { + let (hi, els) = if self.eat_keyword(kw::Else) { let expr = self.parse_else_expr()?; (expr.span, Some(expr)) } else { @@ -3741,7 +3743,7 @@ impl<'a> Parser<'a> { -> PResult<'a, P> { let lo = self.span; - let movability = if self.eat_keyword(keywords::Static) { + let movability = if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable @@ -3751,7 +3753,7 @@ impl<'a> Parser<'a> { } else { IsAsync::NotAsync }; - let capture_clause = if self.eat_keyword(keywords::Move) { + let capture_clause = if self.eat_keyword(kw::Move) { CaptureBy::Value } else { CaptureBy::Ref @@ -3779,7 +3781,7 @@ impl<'a> Parser<'a> { // `else` token already eaten fn parse_else_expr(&mut self) -> PResult<'a, P> { - if self.eat_keyword(keywords::If) { + if self.eat_keyword(kw::If) { return self.parse_if_expr(ThinVec::new()); } else { let blk = self.parse_block()?; @@ -3794,7 +3796,7 @@ impl<'a> Parser<'a> { // Parse: `for in ` let pat = self.parse_top_level_pat()?; - if !self.eat_keyword(keywords::In) { + if !self.eat_keyword(kw::In) { let in_span = self.prev_span.between(self.span); let mut err = self.sess.span_diagnostic .struct_span_err(in_span, "missing `in` in `for` loop"); @@ -3806,7 +3808,7 @@ impl<'a> Parser<'a> { err.emit(); } let in_span = self.prev_span; - if self.eat_keyword(keywords::In) { + if self.eat_keyword(kw::In) { // a common typo: `for _ in in bar {}` let mut err = self.sess.span_diagnostic.struct_span_err( self.prev_span, @@ -3835,7 +3837,7 @@ impl<'a> Parser<'a> { fn parse_while_expr(&mut self, opt_label: Option