From f89ba5da4a7f9a6446b91cb621ed000d28529d82 Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Tue, 18 Oct 2016 10:56:12 -0700 Subject: [PATCH 01/33] Fix some mistakes in HRTB docs The example code for higher-ranked trait bounds on closures had an unnecessary `mut` which was confusing, and the text referred to an mutable reference which does not exist in the code (and isn't needed). Removed the `mut`s and fixed the text to better describe the actual error for the failing example. --- src/doc/book/closures.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/doc/book/closures.md b/src/doc/book/closures.md index 3ed85c1a90b69..60b99c08825ee 100644 --- a/src/doc/book/closures.md +++ b/src/doc/book/closures.md @@ -327,7 +327,7 @@ that takes a reference like so: fn call_with_ref(some_closure:F) -> i32 where F: Fn(&i32) -> i32 { - let mut value = 0; + let value = 0; some_closure(&value) } ``` @@ -340,14 +340,15 @@ fn call_with_ref<'a, F>(some_closure:F) -> i32 where F: Fn(&'a i32) -> i32 { ``` -However this presents a problem in our case. When you specify the explicit -lifetime on a function it binds that lifetime to the *entire* scope of the function -instead of just the invocation scope of our closure. This means that the borrow checker -will see a mutable reference in the same lifetime as our immutable reference and fail -to compile. +However, this presents a problem in our case. When a function has an explicit +lifetime parameter, that lifetime must be at least as long as the *entire* +call to that function. The borrow checker will complain that `value` doesn't +live long enough, because it is only in scope after its declaration inside the +function body. -In order to say that we only need the lifetime to be valid for the invocation scope -of the closure we can use Higher-Ranked Trait Bounds with the `for<...>` syntax: +What we need is a closure that can borrow its argument only for its own +invocation scope, not for the outer function's scope. In order to say that, +we can use Higher-Ranked Trait Bounds with the `for<...>` syntax: ```ignore fn call_with_ref(some_closure:F) -> i32 @@ -362,7 +363,7 @@ expect. fn call_with_ref(some_closure:F) -> i32 where F: for<'a> Fn(&'a i32) -> i32 { - let mut value = 0; + let value = 0; some_closure(&value) } ``` From 9ae9930e2fbdb2610843e6dc1ae0fb0759507218 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Thu, 20 Oct 2016 14:07:06 +0200 Subject: [PATCH 02/33] Introduce iterator trait TrustedLen --- src/libcore/iter/mod.rs | 33 +++++++++++++++++++++++++++++++++ src/libcore/iter/range.rs | 5 ++++- src/libcore/iter/traits.rs | 7 +++++++ src/libcore/slice.rs | 6 ++++++ 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 9eeb2608071c2..9fa950cd94d9e 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -328,6 +328,8 @@ pub use self::traits::{FromIterator, IntoIterator, DoubleEndedIterator, Extend}; pub use self::traits::{ExactSizeIterator, Sum, Product}; #[unstable(feature = "fused", issue = "35602")] pub use self::traits::FusedIterator; +#[unstable(feature = "trusted_len", issue = "0")] +pub use self::traits::TrustedLen; mod iterator; mod range; @@ -372,6 +374,10 @@ impl ExactSizeIterator for Rev impl FusedIterator for Rev where I: FusedIterator + DoubleEndedIterator {} +#[unstable(feature = "trusted_len", issue = "0")] +unsafe impl TrustedLen for Rev + where I: TrustedLen + DoubleEndedIterator {} + /// An iterator that clones the elements of an underlying iterator. /// /// This `struct` is created by the [`cloned()`] method on [`Iterator`]. See its @@ -432,6 +438,12 @@ unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned fn may_have_side_effect() -> bool { true } } +#[unstable(feature = "trusted_len", issue = "0")] +unsafe impl<'a, I, T: 'a> TrustedLen for Cloned + where I: TrustedLen, + T: Clone +{} + /// An iterator that repeats endlessly. /// /// This `struct` is created by the [`cycle()`] method on [`Iterator`]. See its @@ -642,6 +654,11 @@ impl FusedIterator for Chain B: FusedIterator, {} +#[unstable(feature = "trusted_len", issue = "0")] +unsafe impl TrustedLen for Chain + where A: TrustedLen, B: TrustedLen, +{} + /// An iterator that iterates two other iterators simultaneously. /// /// This `struct` is created by the [`zip()`] method on [`Iterator`]. See its @@ -859,6 +876,11 @@ unsafe impl TrustedRandomAccess for Zip impl FusedIterator for Zip where A: FusedIterator, B: FusedIterator, {} +#[unstable(feature = "trusted_len", issue = "0")] +unsafe impl TrustedLen for Zip + where A: TrustedLen, B: TrustedLen, +{} + /// An iterator that maps the values of `iter` with `f`. /// /// This `struct` is created by the [`map()`] method on [`Iterator`]. See its @@ -959,6 +981,11 @@ impl ExactSizeIterator for Map impl FusedIterator for Map where F: FnMut(I::Item) -> B {} +#[unstable(feature = "trusted_len", issue = "0")] +unsafe impl TrustedLen for Map + where I: TrustedLen, + F: FnMut(I::Item) -> B {} + #[doc(hidden)] unsafe impl TrustedRandomAccess for Map where I: TrustedRandomAccess, @@ -1195,6 +1222,12 @@ unsafe impl TrustedRandomAccess for Enumerate #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for Enumerate where I: FusedIterator {} +#[unstable(feature = "trusted_len", issue = "0")] +unsafe impl TrustedLen for Enumerate + where I: TrustedLen, +{} + + /// An iterator with a `peek()` that returns an optional reference to the next /// element. /// diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index eaa3d50c88ade..39da578d54913 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -12,7 +12,7 @@ use mem; use ops::{self, Add, Sub}; use usize; -use super::FusedIterator; +use super::{FusedIterator, TrustedLen}; /// Objects that can be stepped over in both directions. /// @@ -533,6 +533,9 @@ impl DoubleEndedIterator for ops::Range where impl FusedIterator for ops::Range where A: Step, for<'a> &'a A: Add<&'a A, Output = A> {} +#[unstable(feature = "trusted_len", issue = "0")] +unsafe impl TrustedLen for ops::Range { } + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for ops::RangeFrom where for<'a> &'a A: Add<&'a A, Output = A> diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index b55d6f96af9bf..da150f1d57a63 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -665,3 +665,10 @@ pub trait FusedIterator: Iterator {} #[unstable(feature = "fused", issue = "35602")] impl<'a, I: FusedIterator + ?Sized> FusedIterator for &'a mut I {} + +/// An iterator that has correct length +#[unstable(feature = "trusted_len", issue = "0")] +pub unsafe trait TrustedLen : Iterator {} + +#[unstable(feature = "trusted_len", issue = "0")] +unsafe impl<'a, I: TrustedLen + ?Sized> TrustedLen for &'a mut I {} diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 31be404ba905a..64d38c54c4767 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -988,6 +988,9 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> {} #[unstable(feature = "fused", issue = "35602")] impl<'a, T> FusedIterator for Iter<'a, T> {} +#[unstable(feature = "trusted_len", issue = "0")] +unsafe impl<'a, T> TrustedLen for Iter<'a, T> {} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Clone for Iter<'a, T> { fn clone(&self) -> Iter<'a, T> { Iter { ptr: self.ptr, end: self.end, _marker: self._marker } } @@ -1109,6 +1112,9 @@ impl<'a, T> ExactSizeIterator for IterMut<'a, T> {} #[unstable(feature = "fused", issue = "35602")] impl<'a, T> FusedIterator for IterMut<'a, T> {} +#[unstable(feature = "trusted_len", issue = "0")] +unsafe impl<'a, T> TrustedLen for IterMut<'a, T> {} + /// An internal abstraction over the splitting iterators, so that /// splitn, splitn_mut etc can be implemented once. #[doc(hidden)] From 49557112d64f5877093bfe43acaf5dc8d5b947a7 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Thu, 20 Oct 2016 14:07:31 +0200 Subject: [PATCH 03/33] Use TrustedLen for Vec's FromIterator and Extend --- src/libcollections/lib.rs | 1 + src/libcollections/vec.rs | 46 ++++++++++++++++++++++++++++++--------- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 990de541b6783..23d6edd6d794e 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -50,6 +50,7 @@ #![feature(specialization)] #![feature(staged_api)] #![feature(step_by)] +#![feature(trusted_len)] #![feature(unicode)] #![feature(unique)] #![cfg_attr(test, feature(rand, test))] diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index f3d78c20a4d6b..cd628a39af8b8 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -68,7 +68,7 @@ use core::cmp::Ordering; use core::fmt; use core::hash::{self, Hash}; use core::intrinsics::{arith_offset, assume}; -use core::iter::{FromIterator, FusedIterator}; +use core::iter::{FromIterator, FusedIterator, TrustedLen}; use core::mem; use core::ops::{Index, IndexMut}; use core::ops; @@ -1589,6 +1589,18 @@ impl SpecExtend> for Vec { } } +trait IsTrustedLen : Iterator { + fn trusted_len(&self) -> Option { None } +} +impl IsTrustedLen for I where I: Iterator { } + +impl IsTrustedLen for I where I: TrustedLen +{ + fn trusted_len(&self) -> Option { + self.size_hint().1 + } +} + impl Vec { fn extend_desugared>(&mut self, mut iterator: I) { // This function should be the moral equivalent of: @@ -1596,16 +1608,30 @@ impl Vec { // for item in iterator { // self.push(item); // } - while let Some(element) = iterator.next() { - let len = self.len(); - if len == self.capacity() { - let (lower, _) = iterator.size_hint(); - self.reserve(lower.saturating_add(1)); - } + if let Some(additional) = iterator.trusted_len() { + self.reserve(additional); unsafe { - ptr::write(self.get_unchecked_mut(len), element); - // NB can't overflow since we would have had to alloc the address space - self.set_len(len + 1); + let mut ptr = self.as_mut_ptr().offset(self.len() as isize); + let mut local_len = SetLenOnDrop::new(&mut self.len); + for element in iterator { + ptr::write(ptr, element); + ptr = ptr.offset(1); + // NB can't overflow since we would have had to alloc the address space + local_len.increment_len(1); + } + } + } else { + while let Some(element) = iterator.next() { + let len = self.len(); + if len == self.capacity() { + let (lower, _) = iterator.size_hint(); + self.reserve(lower.saturating_add(1)); + } + unsafe { + ptr::write(self.get_unchecked_mut(len), element); + // NB can't overflow since we would have had to alloc the address space + self.set_len(len + 1); + } } } } From 69b9400b796f545226415feae36b9ea4f8cc70c0 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Thu, 20 Oct 2016 14:34:34 +0200 Subject: [PATCH 04/33] Implement TrustedLen for more iterators --- src/libcore/iter/range.rs | 26 +++++++++++++++++++++++--- src/libcore/option.rs | 11 ++++++++++- src/libcore/result.rs | 11 ++++++++++- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 39da578d54913..ab55ee9d9d7b0 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -480,6 +480,22 @@ macro_rules! range_incl_exact_iter_impl { )*) } +macro_rules! range_trusted_len_impl { + ($($t:ty)*) => ($( + #[unstable(feature = "trusted_len", issue = "0")] + unsafe impl TrustedLen for ops::Range<$t> { } + )*) +} + +macro_rules! range_incl_trusted_len_impl { + ($($t:ty)*) => ($( + #[unstable(feature = "inclusive_range", + reason = "recently added, follows RFC", + issue = "28237")] + unsafe impl TrustedLen for ops::RangeInclusive<$t> { } + )*) +} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for ops::Range where for<'a> &'a A: Add<&'a A, Output = A> @@ -513,6 +529,13 @@ impl Iterator for ops::Range where range_exact_iter_impl!(usize u8 u16 u32 isize i8 i16 i32); range_incl_exact_iter_impl!(u8 u16 i8 i16); +// These macros generate `TrustedLen` impls. +// +// They need to guarantee that .size_hint() is either exact, or that +// the upper bound is None when it does not fit the type limits. +range_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64); +range_incl_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64); + #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for ops::Range where for<'a> &'a A: Add<&'a A, Output = A>, @@ -533,9 +556,6 @@ impl DoubleEndedIterator for ops::Range where impl FusedIterator for ops::Range where A: Step, for<'a> &'a A: Add<&'a A, Output = A> {} -#[unstable(feature = "trusted_len", issue = "0")] -unsafe impl TrustedLen for ops::Range { } - #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for ops::RangeFrom where for<'a> &'a A: Add<&'a A, Output = A> diff --git a/src/libcore/option.rs b/src/libcore/option.rs index cb18feff73422..28845ef5e8c11 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -145,7 +145,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -use iter::{FromIterator, FusedIterator}; +use iter::{FromIterator, FusedIterator, TrustedLen}; use mem; // Note that this is not a lang item per se, but it has a hidden dependency on @@ -803,6 +803,7 @@ impl DoubleEndedIterator for Item { impl ExactSizeIterator for Item {} impl FusedIterator for Item {} +unsafe impl TrustedLen for Item {} /// An iterator over a reference of the contained item in an [`Option`]. /// @@ -833,6 +834,9 @@ impl<'a, A> ExactSizeIterator for Iter<'a, A> {} #[unstable(feature = "fused", issue = "35602")] impl<'a, A> FusedIterator for Iter<'a, A> {} +#[unstable(feature = "trusted_len", issue = "0")] +unsafe impl<'a, A> TrustedLen for Iter<'a, A> {} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, A> Clone for Iter<'a, A> { fn clone(&self) -> Iter<'a, A> { @@ -868,6 +872,8 @@ impl<'a, A> ExactSizeIterator for IterMut<'a, A> {} #[unstable(feature = "fused", issue = "35602")] impl<'a, A> FusedIterator for IterMut<'a, A> {} +#[unstable(feature = "trusted_len", issue = "0")] +unsafe impl<'a, A> TrustedLen for IterMut<'a, A> {} /// An iterator over the item contained inside an [`Option`]. /// @@ -898,6 +904,9 @@ impl ExactSizeIterator for IntoIter {} #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for IntoIter {} +#[unstable(feature = "trusted_len", issue = "0")] +unsafe impl TrustedLen for IntoIter {} + ///////////////////////////////////////////////////////////////////////////// // FromIterator ///////////////////////////////////////////////////////////////////////////// diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 96845259299be..8985e7c8251e1 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -249,7 +249,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use fmt; -use iter::{FromIterator, FusedIterator}; +use iter::{FromIterator, FusedIterator, TrustedLen}; /// `Result` is a type that represents either success (`Ok`) or failure (`Err`). /// @@ -886,6 +886,9 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> {} #[unstable(feature = "fused", issue = "35602")] impl<'a, T> FusedIterator for Iter<'a, T> {} +#[unstable(feature = "trusted_len", issue = "0")] +unsafe impl<'a, A> TrustedLen for Iter<'a, A> {} + #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Clone for Iter<'a, T> { fn clone(&self) -> Iter<'a, T> { Iter { inner: self.inner } } @@ -924,6 +927,9 @@ impl<'a, T> ExactSizeIterator for IterMut<'a, T> {} #[unstable(feature = "fused", issue = "35602")] impl<'a, T> FusedIterator for IterMut<'a, T> {} +#[unstable(feature = "trusted_len", issue = "0")] +unsafe impl<'a, A> TrustedLen for IterMut<'a, A> {} + /// An iterator over the value in a [`Ok`] variant of a [`Result`]. This struct is /// created by the [`into_iter`] method on [`Result`][`Result`] (provided by /// the [`IntoIterator`] trait). @@ -961,6 +967,9 @@ impl ExactSizeIterator for IntoIter {} #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for IntoIter {} +#[unstable(feature = "trusted_len", issue = "0")] +unsafe impl TrustedLen for IntoIter {} + ///////////////////////////////////////////////////////////////////////////// // FromIterator ///////////////////////////////////////////////////////////////////////////// From a3cab90fda3b1ccfa4eb952dda49677c8d06c1ef Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Thu, 20 Oct 2016 14:44:31 +0200 Subject: [PATCH 05/33] =?UTF-8?q?Document=20TrustedLen=E2=80=99s=20contrac?= =?UTF-8?q?t?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libcore/iter/traits.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index da150f1d57a63..a56a864f6180d 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -666,7 +666,19 @@ pub trait FusedIterator: Iterator {} #[unstable(feature = "fused", issue = "35602")] impl<'a, I: FusedIterator + ?Sized> FusedIterator for &'a mut I {} -/// An iterator that has correct length +/// An iterator that reports an accurate length using size_hint. +/// +/// The iterator reports a size hint where it is either exact +/// (lower bound is equal to upper bound), or the upper bound is `None`. +/// The upper bound must only be `None` if the actual iterator length is +/// larger than `usize::MAX`. +/// +/// The iterator must produce exactly the number of elements it reported. +/// +/// # Safety +/// +/// This trait must only be implemented when the contract is upheld. +/// Consumers of this trait must inspect `.size_hint()`’s upper bound. #[unstable(feature = "trusted_len", issue = "0")] pub unsafe trait TrustedLen : Iterator {} From e47da0c23c91feea24e5b961a662754d689bb082 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 20 Oct 2016 17:59:41 -0700 Subject: [PATCH 06/33] Add release notes for 1.12.1 --- RELEASES.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index e6f18f9f7ba55..222ad3aa112af 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,30 @@ +Version 1.12.1 (2016-10-20) +=========================== + +Regression Fixes +---------------- + +* [ICE: 'rustc' panicked at 'assertion failed: concrete_substs.is_normalized_for_trans()' #36381][36381] +* [Confusion with double negation and booleans][36856] +* [rustc 1.12.0 fails with SIGSEGV in release mode (syn crate 0.8.0)][36875] +* [Rustc 1.12.0 Windows build of `ethcore` crate fails with LLVM error][36924] +* [1.12.0: High memory usage when linking in release mode with debug info][36926] +* [Corrupted memory after updated to 1.12][36936] +* ["Let NullaryConstructor = something;" causes internal compiler error: "tried to overwrite interned AdtDef"][37026] +* [Fix ICE: inject bitcast if types mismatch for invokes/calls/stores][37112] +* [debuginfo: Handle spread_arg case in MIR-trans in a more stable way.][37153] + +[36381]: https://github.com/rust-lang/rust/issues/36381 +[36856]: https://github.com/rust-lang/rust/issues/36856 +[36875]: https://github.com/rust-lang/rust/issues/36875 +[36924]: https://github.com/rust-lang/rust/issues/36924 +[36926]: https://github.com/rust-lang/rust/issues/36926 +[36936]: https://github.com/rust-lang/rust/issues/36936 +[37026]: https://github.com/rust-lang/rust/issues/37026 +[37112]: https://github.com/rust-lang/rust/issues/37112 +[37153]: https://github.com/rust-lang/rust/issues/37153 + + Version 1.12.0 (2016-09-29) =========================== From 622f24f6d9cc952ccf2bb4dbe5bf65bb966194d3 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Fri, 21 Oct 2016 13:51:31 +0200 Subject: [PATCH 07/33] vec: Use Vec::extend specializations in extend_from_slice and more The new Vec::extend covers the duties of .extend_from_slice() and some previous specializations. --- src/libcollections/vec.rs | 40 ++------------------------------------- 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index cd628a39af8b8..50ad48567472c 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1212,26 +1212,7 @@ impl Vec { /// ``` #[stable(feature = "vec_extend_from_slice", since = "1.6.0")] pub fn extend_from_slice(&mut self, other: &[T]) { - self.reserve(other.len()); - - // Unsafe code so this can be optimised to a memcpy (or something - // similarly fast) when T is Copy. LLVM is easily confused, so any - // extra operations during the loop can prevent this optimisation. - unsafe { - let len = self.len(); - let ptr = self.get_unchecked_mut(len) as *mut T; - // Use SetLenOnDrop to work around bug where compiler - // may not realize the store through `ptr` trough self.set_len() - // don't alias. - let mut local_len = SetLenOnDrop::new(&mut self.len); - - for i in 0..other.len() { - ptr::write(ptr.offset(i as isize), other.get_unchecked(i).clone()); - local_len.increment_len(1); - } - - // len set by scope guard - } + self.extend(other.iter().cloned()) } } @@ -1640,24 +1621,7 @@ impl Vec { #[stable(feature = "extend_ref", since = "1.2.0")] impl<'a, T: 'a + Copy> Extend<&'a T> for Vec { fn extend>(&mut self, iter: I) { - >::extend_vec(iter, self); - } -} - -// helper trait for specialization of Vec's Extend impl -trait SpecExtendVec { - fn extend_vec(self, vec: &mut Vec); -} - -impl <'a, T: 'a + Copy, I: IntoIterator> SpecExtendVec for I { - default fn extend_vec(self, vec: &mut Vec) { - vec.extend(self.into_iter().cloned()); - } -} - -impl<'a, T: Copy> SpecExtendVec for &'a [T] { - fn extend_vec(self, vec: &mut Vec) { - vec.extend_from_slice(self); + self.extend(iter.into_iter().map(|&x| x)) } } From ee84ec1fa183dbfa9ce2e26e6e8c12ded3ffddb6 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Fri, 21 Oct 2016 19:18:08 +0200 Subject: [PATCH 08/33] vec: Add a debug assertion where TrustedLen is used --- src/libcollections/vec.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 50ad48567472c..8bed02c79e0a8 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1578,7 +1578,13 @@ impl IsTrustedLen for I where I: Iterator { } impl IsTrustedLen for I where I: TrustedLen { fn trusted_len(&self) -> Option { - self.size_hint().1 + let (low, high) = self.size_hint(); + if let Some(high_value) = high { + debug_assert_eq!(low, high_value, + "TrustedLen iterator's size hint is not exact: {:?}", + (low, high)); + } + high } } From f69cd1b30e70487147d812225baea37c39918e3b Mon Sep 17 00:00:00 2001 From: Cristi Cobzarenco Date: Sun, 23 Oct 2016 14:27:49 +0100 Subject: [PATCH 09/33] Implement ops on `&Wrapping` --- src/libcore/internal_macros.rs | 62 ++++++++++++++++++++++++++++++++++ src/libcore/lib.rs | 3 ++ src/libcore/num/wrapping.rs | 10 ++++++ src/libcore/ops.rs | 52 ---------------------------- 4 files changed, 75 insertions(+), 52 deletions(-) create mode 100644 src/libcore/internal_macros.rs diff --git a/src/libcore/internal_macros.rs b/src/libcore/internal_macros.rs new file mode 100644 index 0000000000000..f2cdc9d6a98c5 --- /dev/null +++ b/src/libcore/internal_macros.rs @@ -0,0 +1,62 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +// implements the unary operator "op &T" +// based on "op T" where T is expected to be `Copy`able +macro_rules! forward_ref_unop { + (impl $imp:ident, $method:ident for $t:ty) => { + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a> $imp for &'a $t { + type Output = <$t as $imp>::Output; + + #[inline] + fn $method(self) -> <$t as $imp>::Output { + $imp::$method(*self) + } + } + } +} + +// implements binary operators "&T op U", "T op &U", "&T op &U" +// based on "T op U" where T and U are expected to be `Copy`able +macro_rules! forward_ref_binop { + (impl $imp:ident, $method:ident for $t:ty, $u:ty) => { + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a> $imp<$u> for &'a $t { + type Output = <$t as $imp<$u>>::Output; + + #[inline] + fn $method(self, other: $u) -> <$t as $imp<$u>>::Output { + $imp::$method(*self, other) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a> $imp<&'a $u> for $t { + type Output = <$t as $imp<$u>>::Output; + + #[inline] + fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output { + $imp::$method(self, *other) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl<'a, 'b> $imp<&'a $u> for &'b $t { + type Output = <$t as $imp<$u>>::Output; + + #[inline] + fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output { + $imp::$method(*self, *other) + } + } + } +} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 28101d21fc25e..07f5e725e2003 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -100,6 +100,9 @@ use prelude::v1::*; #[macro_use] mod macros; +#[macro_use] +mod internal_macros; + #[path = "num/float_macros.rs"] #[macro_use] mod float_macros; diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index d35c451ac2604..50d64838a5c0b 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -131,6 +131,7 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_add(other.0)) } } + forward_ref_binop! { impl Add, add for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl AddAssign for Wrapping<$t> { @@ -149,6 +150,7 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_sub(other.0)) } } + forward_ref_binop! { impl Sub, sub for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl SubAssign for Wrapping<$t> { @@ -167,6 +169,7 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_mul(other.0)) } } + forward_ref_binop! { impl Mul, mul for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl MulAssign for Wrapping<$t> { @@ -185,6 +188,7 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_div(other.0)) } } + forward_ref_binop! { impl Div, div for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl DivAssign for Wrapping<$t> { @@ -203,6 +207,7 @@ macro_rules! wrapping_impl { Wrapping(self.0.wrapping_rem(other.0)) } } + forward_ref_binop! { impl Rem, rem for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl RemAssign for Wrapping<$t> { @@ -221,6 +226,7 @@ macro_rules! wrapping_impl { Wrapping(!self.0) } } + forward_ref_unop! { impl Not, not for Wrapping<$t> } #[stable(feature = "rust1", since = "1.0.0")] impl BitXor for Wrapping<$t> { @@ -231,6 +237,7 @@ macro_rules! wrapping_impl { Wrapping(self.0 ^ other.0) } } + forward_ref_binop! { impl BitXor, bitxor for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl BitXorAssign for Wrapping<$t> { @@ -249,6 +256,7 @@ macro_rules! wrapping_impl { Wrapping(self.0 | other.0) } } + forward_ref_binop! { impl BitOr, bitor for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl BitOrAssign for Wrapping<$t> { @@ -267,6 +275,7 @@ macro_rules! wrapping_impl { Wrapping(self.0 & other.0) } } + forward_ref_binop! { impl BitAnd, bitand for Wrapping<$t>, Wrapping<$t> } #[stable(feature = "op_assign_traits", since = "1.8.0")] impl BitAndAssign for Wrapping<$t> { @@ -284,6 +293,7 @@ macro_rules! wrapping_impl { Wrapping(0) - self } } + forward_ref_unop! { impl Neg, neg for Wrapping<$t> } )*) } diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 72e951a7c347c..06b662ea20d77 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -196,58 +196,6 @@ pub trait Drop { fn drop(&mut self); } -// implements the unary operator "op &T" -// based on "op T" where T is expected to be `Copy`able -macro_rules! forward_ref_unop { - (impl $imp:ident, $method:ident for $t:ty) => { - #[stable(feature = "rust1", since = "1.0.0")] - impl<'a> $imp for &'a $t { - type Output = <$t as $imp>::Output; - - #[inline] - fn $method(self) -> <$t as $imp>::Output { - $imp::$method(*self) - } - } - } -} - -// implements binary operators "&T op U", "T op &U", "&T op &U" -// based on "T op U" where T and U are expected to be `Copy`able -macro_rules! forward_ref_binop { - (impl $imp:ident, $method:ident for $t:ty, $u:ty) => { - #[stable(feature = "rust1", since = "1.0.0")] - impl<'a> $imp<$u> for &'a $t { - type Output = <$t as $imp<$u>>::Output; - - #[inline] - fn $method(self, other: $u) -> <$t as $imp<$u>>::Output { - $imp::$method(*self, other) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl<'a> $imp<&'a $u> for $t { - type Output = <$t as $imp<$u>>::Output; - - #[inline] - fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output { - $imp::$method(self, *other) - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl<'a, 'b> $imp<&'a $u> for &'b $t { - type Output = <$t as $imp<$u>>::Output; - - #[inline] - fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output { - $imp::$method(*self, *other) - } - } - } -} - /// The `Add` trait is used to specify the functionality of `+`. /// /// # Examples From df0e5a97fb326ade900567d80977f40b83aea565 Mon Sep 17 00:00:00 2001 From: Cristi Cobzarenco Date: Sat, 22 Oct 2016 20:12:30 +0100 Subject: [PATCH 10/33] Add `Sum` and `Product` impls for `Wrapping` --- src/libcore/iter/traits.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index b55d6f96af9bf..79c000d058e7a 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. use ops::{Mul, Add}; +use num::Wrapping; /// Conversion from an `Iterator`. /// @@ -584,35 +585,39 @@ pub trait Product: Sized { // NB: explicitly use Add and Mul here to inherit overflow checks macro_rules! integer_sum_product { - ($($a:ident)*) => ($( + (@impls $zero:expr, $one:expr, $($a:ty)*) => ($( #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl Sum for $a { fn sum>(iter: I) -> $a { - iter.fold(0, Add::add) + iter.fold($zero, Add::add) } } #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl Product for $a { fn product>(iter: I) -> $a { - iter.fold(1, Mul::mul) + iter.fold($one, Mul::mul) } } #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl<'a> Sum<&'a $a> for $a { fn sum>(iter: I) -> $a { - iter.cloned().fold(0, Add::add) + iter.fold($zero, Add::add) } } #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl<'a> Product<&'a $a> for $a { fn product>(iter: I) -> $a { - iter.cloned().fold(1, Mul::mul) + iter.fold($one, Mul::mul) } } - )*) + )*); + ($($a:ty)*) => ( + integer_sum_product!(@impls 0, 1, $($a)+); + integer_sum_product!(@impls Wrapping(0), Wrapping(1), $(Wrapping<$a>)+); + ); } macro_rules! float_sum_product { From 8b2108c6cb6b60f01b2ff01ef81861dcbc02fec7 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Wed, 26 Oct 2016 23:05:06 +0200 Subject: [PATCH 11/33] core::ptr: Add .wrapping_offset() methods .wrapping_offset() exposes the arith_offset intrinsic in the core module. This is the first step in making it possible to stabilize the interface later. `arith_offset` is a useful tool for developing iterators for two reasons: 1. `arith_offset` is used by the slice's iterator, the most important iterator in libcore, and it is natural that Rust users need the same power available to implement similar iterators. 2. It is a good way to implement raw pointer iterations with step greater than one. The name seems to fit the style of methods like "wrapping_add". --- src/libcore/ptr.rs | 80 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index f0510422a07d7..befab1b3669b3 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -344,6 +344,46 @@ impl *const T { pub unsafe fn offset(self, count: isize) -> *const T where T: Sized { intrinsics::offset(self, count) } + + /// Calculates the offset from a pointer using wrapping arithmetic. + /// `count` is in units of T; e.g. a `count` of 3 represents a pointer + /// offset of `3 * sizeof::()` bytes. + /// + /// # Safety + /// + /// The resulting pointer does not need to be in bounds, but it is + /// potentially hazardous to dereference (which requires `unsafe`). + /// + /// Always use `.offset(count)` instead when possible, because `offset` + /// allows the compiler to optimize better. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(ptr_wrapping_offset)] + /// // Iterate using a raw pointer in increments of two elements + /// let data = [1u8, 2, 3, 4, 5]; + /// let mut ptr: *const u8 = data.as_ptr(); + /// let step = 2; + /// let end_rounded_up = ptr.wrapping_offset(6); + /// + /// // This loop prints "1, 3, 5, " + /// while ptr != end_rounded_up { + /// unsafe { + /// print!("{}, ", *ptr); + /// } + /// ptr = ptr.wrapping_offset(step); + /// } + /// ``` + #[unstable(feature = "ptr_wrapping_offset", issue = "0")] + #[inline] + pub fn wrapping_offset(self, count: isize) -> *const T where T: Sized { + unsafe { + intrinsics::arith_offset(self, count) + } + } } #[lang = "mut_ptr"] @@ -429,6 +469,46 @@ impl *mut T { intrinsics::offset(self, count) as *mut T } + /// Calculates the offset from a pointer using wrapping arithmetic. + /// `count` is in units of T; e.g. a `count` of 3 represents a pointer + /// offset of `3 * sizeof::()` bytes. + /// + /// # Safety + /// + /// The resulting pointer does not need to be in bounds, but it is + /// potentially hazardous to dereference (which requires `unsafe`). + /// + /// Always use `.offset(count)` instead when possible, because `offset` + /// allows the compiler to optimize better. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(ptr_wrapping_offset)] + /// // Iterate using a raw pointer in increments of two elements + /// let mut data = [1u8, 2, 3, 4, 5]; + /// let mut ptr: *mut u8 = data.as_mut_ptr(); + /// let step = 2; + /// let end_rounded_up = ptr.wrapping_offset(6); + /// + /// while ptr != end_rounded_up { + /// unsafe { + /// *ptr = 0; + /// } + /// ptr = ptr.wrapping_offset(step); + /// } + /// assert_eq!(&data, &[0, 2, 0, 4, 0]); + /// ``` + #[unstable(feature = "ptr_wrapping_offset", issue = "0")] + #[inline] + pub fn wrapping_offset(self, count: isize) -> *mut T where T: Sized { + unsafe { + intrinsics::arith_offset(self, count) as *mut T + } + } + /// Returns `None` if the pointer is null, or else returns a mutable /// reference to the value wrapped in `Some`. /// From 2411be5cae59e2640a9795c7301f66fb47325cce Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Thu, 27 Oct 2016 00:18:13 +0200 Subject: [PATCH 12/33] impl TrustedLen for vec::IntoIter --- src/libcollections/vec.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 8bed02c79e0a8..c42926b09526c 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1944,6 +1944,9 @@ impl ExactSizeIterator for IntoIter {} #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for IntoIter {} +#[unstable(feature = "trusted_len", issue = "0")] +unsafe impl TrustedLen for IntoIter {} + #[stable(feature = "vec_into_iter_clone", since = "1.8.0")] impl Clone for IntoIter { fn clone(&self) -> IntoIter { From 5dc9db541e810839f4193fee43c62ebefbe6f260 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Thu, 27 Oct 2016 00:40:09 +0200 Subject: [PATCH 13/33] vec: Remove the Vec specialization for .extend() This now produces as good code (with optimizations) using the TrustedLen codepath. --- src/libcollections/vec.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index c42926b09526c..16331960cc198 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -76,7 +76,6 @@ use core::ptr; use core::ptr::Shared; use core::slice; -use super::SpecExtend; use super::range::RangeArgument; /// A contiguous growable array type, written `Vec` but pronounced 'vector.' @@ -1554,22 +1553,10 @@ impl<'a, T> IntoIterator for &'a mut Vec { impl Extend for Vec { #[inline] fn extend>(&mut self, iter: I) { - >::spec_extend(self, iter); - } -} - -impl SpecExtend for Vec { - default fn spec_extend(&mut self, iter: I) { self.extend_desugared(iter.into_iter()) } } -impl SpecExtend> for Vec { - fn spec_extend(&mut self, ref mut other: Vec) { - self.append(other); - } -} - trait IsTrustedLen : Iterator { fn trusted_len(&self) -> Option { None } } From 20c301330cf17dd98c58aaff602586b99f7676fc Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 31 Oct 2016 09:36:30 -0700 Subject: [PATCH 14/33] rustc: Add knowledge of Windows subsystems. This commit is an implementation of [RFC 1665] which adds support for the `#![windows_subsystem]` attribute. This attribute allows specifying either the "windows" or "console" subsystems on Windows to the linker. [RFC 1665]: https://github.com/rust-lang/rfcs/blob/master/text/1665-windows-subsystem.md Previously all Rust executables were compiled as the "console" subsystem which meant that if you wanted a graphical application it would erroneously pop up a console whenever opened. When compiling an application, however, this is undesired behavior and the "windows" subsystem is used instead to have control over user interactions. This attribute is validated, but ignored on all non-Windows platforms. cc #37499 --- src/librustc_trans/back/link.rs | 12 ++++++-- src/librustc_trans/back/linker.rs | 29 +++++++++++++++++++ src/librustc_trans/base.rs | 17 +++++++++-- src/librustc_trans/lib.rs | 1 + src/libsyntax/feature_gate.rs | 9 ++++++ .../compile-fail/windows-subsystem-gated.rs | 14 +++++++++ .../compile-fail/windows-subsystem-invalid.rs | 15 ++++++++++ src/test/run-make/windows-subsystem/Makefile | 5 ++++ .../run-make/windows-subsystem/console.rs | 15 ++++++++++ .../run-make/windows-subsystem/windows.rs | 14 +++++++++ 10 files changed, 127 insertions(+), 4 deletions(-) create mode 100644 src/test/compile-fail/windows-subsystem-gated.rs create mode 100644 src/test/compile-fail/windows-subsystem-invalid.rs create mode 100644 src/test/run-make/windows-subsystem/Makefile create mode 100644 src/test/run-make/windows-subsystem/console.rs create mode 100644 src/test/run-make/windows-subsystem/windows.rs diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index e46bdbb5ccf4a..ad8e0c1ee59f6 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -636,7 +636,7 @@ fn link_natively(sess: &Session, { let mut linker = trans.linker_info.to_linker(&mut cmd, &sess); link_args(&mut *linker, sess, crate_type, tmpdir, - objects, out_filename, outputs); + objects, out_filename, outputs, trans); } cmd.args(&sess.target.target.options.late_link_args); for obj in &sess.target.target.options.post_link_objects { @@ -711,7 +711,8 @@ fn link_args(cmd: &mut Linker, tmpdir: &Path, objects: &[PathBuf], out_filename: &Path, - outputs: &OutputFilenames) { + outputs: &OutputFilenames, + trans: &CrateTranslation) { // The default library location, we need this to find the runtime. // The location of crates will be determined as needed. @@ -726,6 +727,13 @@ fn link_args(cmd: &mut Linker, } cmd.output_filename(out_filename); + if crate_type == config::CrateTypeExecutable && + sess.target.target.options.is_like_windows { + if let Some(ref s) = trans.windows_subsystem { + cmd.subsystem(s); + } + } + // If we're building a dynamic library then some platforms need to make sure // that all symbols are exported correctly from the dynamic library. if crate_type != config::CrateTypeExecutable { diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index 3222571a76e17..860903d259fe5 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -92,6 +92,7 @@ pub trait Linker { fn whole_archives(&mut self); fn no_whole_archives(&mut self); fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType); + fn subsystem(&mut self, subsystem: &str); } pub struct GnuLinker<'a> { @@ -294,6 +295,10 @@ impl<'a> Linker for GnuLinker<'a> { self.cmd.arg(arg); } + + fn subsystem(&mut self, subsystem: &str) { + self.cmd.arg(&format!("-Wl,--subsystem,{}", subsystem)); + } } pub struct MsvcLinker<'a> { @@ -441,6 +446,30 @@ impl<'a> Linker for MsvcLinker<'a> { arg.push(path); self.cmd.arg(&arg); } + + fn subsystem(&mut self, subsystem: &str) { + // Note that previous passes of the compiler validated this subsystem, + // so we just blindly pass it to the linker. + self.cmd.arg(&format!("/SUBSYSTEM:{}", subsystem)); + + // Windows has two subsystems we're interested in right now, the console + // and windows subsystems. These both implicitly have different entry + // points (starting symbols). The console entry point starts with + // `mainCRTStartup` and the windows entry point starts with + // `WinMainCRTStartup`. These entry points, defined in system libraries, + // will then later probe for either `main` or `WinMain`, respectively to + // start the application. + // + // In Rust we just always generate a `main` function so we want control + // to always start there, so we force the entry point on the windows + // subsystem to be `mainCRTStartup` to get everything booted up + // correctly. + // + // For more information see RFC #1665 + if subsystem == "windows" { + self.cmd.arg("/ENTRY:mainCRTStartup"); + } + } } fn exported_symbols(scx: &SharedCrateContext, diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 977ababbf5688..d30183a13f1f8 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -1611,7 +1611,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, metadata: metadata, reachable: vec![], no_builtins: no_builtins, - linker_info: linker_info + linker_info: linker_info, + windows_subsystem: None, }; } @@ -1747,6 +1748,17 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let linker_info = LinkerInfo::new(&shared_ccx, &reachable_symbols); + let subsystem = attr::first_attr_value_str_by_name(&krate.attrs, + "windows_subsystem"); + let windows_subsystem = subsystem.map(|subsystem| { + if subsystem != "windows" && subsystem != "console" { + tcx.sess.fatal(&format!("invalid windows subsystem `{}`, only \ + `windows` and `console` are allowed", + subsystem)); + } + subsystem.to_string() + }); + CrateTranslation { modules: modules, metadata_module: metadata_module, @@ -1754,7 +1766,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, metadata: metadata, reachable: reachable_symbols, no_builtins: no_builtins, - linker_info: linker_info + linker_info: linker_info, + windows_subsystem: windows_subsystem, } } diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 07acc54962b87..37304f28e03f6 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -169,6 +169,7 @@ pub struct CrateTranslation { pub metadata: Vec, pub reachable: Vec, pub no_builtins: bool, + pub windows_subsystem: Option, pub linker_info: back::linker::LinkerInfo } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 129e4a8233803..bf6482e5b99d5 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -309,6 +309,9 @@ declare_features! ( // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions. (active, field_init_shorthand, "1.14.0", Some(37340)), + + // The #![windows_subsystem] attribute + (active, windows_subsystem, "1.14.0", Some(37499)), ); declare_features! ( @@ -713,6 +716,12 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGat "defining reflective traits is still evolving", cfg_fn!(reflect))), + ("windows_subsystem", Whitelisted, Gated(Stability::Unstable, + "windows_subsystem", + "the windows subsystem attribute \ + id currently unstable", + cfg_fn!(windows_subsystem))), + // Crate level attributes ("crate_name", CrateLevel, Ungated), ("crate_type", CrateLevel, Ungated), diff --git a/src/test/compile-fail/windows-subsystem-gated.rs b/src/test/compile-fail/windows-subsystem-gated.rs new file mode 100644 index 0000000000000..4b563e78e55c8 --- /dev/null +++ b/src/test/compile-fail/windows-subsystem-gated.rs @@ -0,0 +1,14 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![windows_subsystem = "console"] +//~^ ERROR: the windows subsystem attribute is currently unstable + +fn main() {} diff --git a/src/test/compile-fail/windows-subsystem-invalid.rs b/src/test/compile-fail/windows-subsystem-invalid.rs new file mode 100644 index 0000000000000..28c3950e76f20 --- /dev/null +++ b/src/test/compile-fail/windows-subsystem-invalid.rs @@ -0,0 +1,15 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(windows_subsystem)] +#![windows_subsystem = "wrong"] +//~^ ERROR: invalid subsystem `wrong`, only `windows` and `console` are allowed + +fn main() {} diff --git a/src/test/run-make/windows-subsystem/Makefile b/src/test/run-make/windows-subsystem/Makefile new file mode 100644 index 0000000000000..34fb5db32f95a --- /dev/null +++ b/src/test/run-make/windows-subsystem/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + $(RUSTC) windows.rs + $(RUSTC) console.rs diff --git a/src/test/run-make/windows-subsystem/console.rs b/src/test/run-make/windows-subsystem/console.rs new file mode 100644 index 0000000000000..3aedb0ecab722 --- /dev/null +++ b/src/test/run-make/windows-subsystem/console.rs @@ -0,0 +1,15 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(windows_subsystem)] +#![windows_subsystem = "console"] + +fn main() {} + diff --git a/src/test/run-make/windows-subsystem/windows.rs b/src/test/run-make/windows-subsystem/windows.rs new file mode 100644 index 0000000000000..5d875a5a1bf1f --- /dev/null +++ b/src/test/run-make/windows-subsystem/windows.rs @@ -0,0 +1,14 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(windows_subsystem)] +#![windows_subsystem = "windows"] + +fn main() {} From eba93c3a0f7cf8a0b7447ab22081ccd20824d9e6 Mon Sep 17 00:00:00 2001 From: arthurprs Date: Sat, 29 Oct 2016 23:12:12 +0200 Subject: [PATCH 15/33] Don't reuse RandomState seeds --- src/libstd/collections/hash/map.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index fb8a0c3c26554..ece51d6d82616 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -11,6 +11,7 @@ use self::Entry::*; use self::VacantEntryState::*; +use cell::Cell; use borrow::Borrow; use cmp::max; use fmt::{self, Debug}; @@ -2049,24 +2050,21 @@ impl RandomState { // many hash maps are created on a thread. To solve this performance // trap we cache the first set of randomly generated keys per-thread. // - // In doing this, however, we lose the property that all hash maps have - // nondeterministic iteration order as all of those created on the same - // thread would have the same hash keys. This property has been nice in - // the past as it allows for maximal flexibility in the implementation - // of `HashMap` itself. - // - // The constraint here (if there even is one) is just that maps created - // on the same thread have the same iteration order, and that *may* be - // relied upon even though it is not a documented guarantee at all of - // the `HashMap` type. In any case we've decided that this is reasonable - // for now, so caching keys thread-locally seems fine. - thread_local!(static KEYS: (u64, u64) = { + // Later in #36481 it was discovered that exposing a deterministic + // iteration order allows a form of DOS attack. To counter that we + // increment one of the seeds on every RandomState creation, giving + // every corresponding HashMap a different iteration order. + thread_local!(static KEYS: Cell<(u64, u64)> = { let r = rand::OsRng::new(); let mut r = r.expect("failed to create an OS RNG"); - (r.gen(), r.gen()) + Cell::new((r.gen(), r.gen())) }); - KEYS.with(|&(k0, k1)| RandomState { k0: k0, k1: k1 }) + KEYS.with(|keys| { + let (k0, k1) = keys.get(); + keys.set((k0.wrapping_add(1), k1)); + RandomState { k0: k0, k1: k1 } + }) } } From 9253e1206e91f5bd7fafd18f8488a937b0046959 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Tue, 25 Oct 2016 23:32:04 +0200 Subject: [PATCH 16/33] adapt debuginfo tests for gdb with native rust support --- src/test/debuginfo/associated-types.rs | 6 +- .../debuginfo/basic-types-globals-metadata.rs | 42 ++++-- src/test/debuginfo/basic-types-globals.rs | 45 ++++-- src/test/debuginfo/basic-types-metadata.rs | 31 ++-- src/test/debuginfo/basic-types-mut-globals.rs | 90 ++++++++---- src/test/debuginfo/basic-types.rs | 3 +- src/test/debuginfo/borrowed-basic.rs | 9 +- src/test/debuginfo/borrowed-c-style-enum.rs | 9 +- src/test/debuginfo/borrowed-enum.rs | 9 +- src/test/debuginfo/borrowed-struct.rs | 9 +- src/test/debuginfo/borrowed-tuple.rs | 9 +- src/test/debuginfo/borrowed-unique-basic.rs | 3 +- src/test/debuginfo/box.rs | 3 +- src/test/debuginfo/boxed-struct.rs | 6 +- .../by-value-non-immediate-argument.rs | 15 +- .../by-value-self-argument-in-trait-impl.rs | 6 +- .../debuginfo/c-style-enum-in-composite.rs | 22 ++- src/test/debuginfo/c-style-enum.rs | 74 ++++++---- src/test/debuginfo/cross-crate-spans.rs | 6 +- .../debuginfo/destructured-fn-argument.rs | 24 ++- .../destructured-for-loop-variable.rs | 6 +- src/test/debuginfo/destructured-local.rs | 24 ++- src/test/debuginfo/evec-in-struct.rs | 15 +- src/test/debuginfo/extern-c-fn.rs | 3 +- .../debuginfo/function-arg-initialization.rs | 8 +- ...gdb-pretty-struct-and-enums-pre-gdb-7-7.rs | 9 +- .../generic-enum-with-different-disr-sizes.rs | 31 +++- src/test/debuginfo/generic-function.rs | 14 +- .../generic-method-on-generic-struct.rs | 15 +- .../debuginfo/generic-struct-style-enum.rs | 12 +- src/test/debuginfo/generic-struct.rs | 12 +- .../debuginfo/generic-tuple-style-enum.rs | 12 +- .../lexical-scopes-in-block-expression.rs | 27 ++-- src/test/debuginfo/method-on-enum.rs | 15 +- .../debuginfo/method-on-generic-struct.rs | 15 +- src/test/debuginfo/method-on-struct.rs | 15 +- src/test/debuginfo/method-on-trait.rs | 15 +- src/test/debuginfo/method-on-tuple-struct.rs | 15 +- src/test/debuginfo/nil-enum.rs | 9 +- src/test/debuginfo/option-like-enum.rs | 24 ++- .../packed-struct-with-destructor.rs | 24 ++- src/test/debuginfo/packed-struct.rs | 12 +- src/test/debuginfo/pretty-std.rs | 3 +- src/test/debuginfo/recursive-struct.rs | 43 ++++-- src/test/debuginfo/self-in-default-method.rs | 15 +- .../self-in-generic-default-method.rs | 15 +- src/test/debuginfo/simd.rs | 56 ++++--- src/test/debuginfo/simple-struct.rs | 115 +++++++++------ src/test/debuginfo/simple-tuple.rs | 121 +++++++++------ src/test/debuginfo/struct-in-enum.rs | 9 +- src/test/debuginfo/struct-in-struct.rs | 9 +- src/test/debuginfo/struct-style-enum.rs | 12 +- src/test/debuginfo/struct-with-destructor.rs | 14 +- src/test/debuginfo/tuple-in-struct.rs | 30 ++-- src/test/debuginfo/tuple-in-tuple.rs | 21 ++- src/test/debuginfo/tuple-struct.rs | 18 ++- src/test/debuginfo/tuple-style-enum.rs | 12 +- src/test/debuginfo/type-names.rs | 138 ++++++++++++------ src/test/debuginfo/union-smoke.rs | 6 +- src/test/debuginfo/unique-enum.rs | 9 +- .../var-captured-in-nested-closure.rs | 12 +- .../var-captured-in-sendable-closure.rs | 3 +- .../var-captured-in-stack-closure.rs | 12 +- src/test/debuginfo/vec-slices.rs | 45 ++++-- src/test/debuginfo/vec.rs | 6 +- 65 files changed, 983 insertions(+), 494 deletions(-) diff --git a/src/test/debuginfo/associated-types.rs b/src/test/debuginfo/associated-types.rs index ebaad663bb4e7..ccd94022711cd 100644 --- a/src/test/debuginfo/associated-types.rs +++ b/src/test/debuginfo/associated-types.rs @@ -16,7 +16,8 @@ // gdb-command:run // gdb-command:print arg -// gdb-check:$1 = {b = -1, b1 = 0} +// gdbg-check:$1 = {b = -1, b1 = 0} +// gdbr-check:$1 = associated_types::Struct {b: -1, b1: 0} // gdb-command:continue // gdb-command:print inferred @@ -30,7 +31,8 @@ // gdb-command:continue // gdb-command:print arg -// gdb-check:$5 = {__0 = 4, __1 = 5} +// gdbg-check:$5 = {__0 = 4, __1 = 5} +// gdbr-check:$5 = (4, 5) // gdb-command:continue // gdb-command:print a diff --git a/src/test/debuginfo/basic-types-globals-metadata.rs b/src/test/debuginfo/basic-types-globals-metadata.rs index 8818063ddf4ba..fe687dabe9acb 100644 --- a/src/test/debuginfo/basic-types-globals-metadata.rs +++ b/src/test/debuginfo/basic-types-globals-metadata.rs @@ -12,33 +12,47 @@ // compile-flags:-g // gdb-command:run -// gdb-command:whatis 'basic_types_globals_metadata::B' +// gdbg-command:whatis 'basic_types_globals_metadata::B' +// gdbr-command:whatis basic_types_globals_metadata::B // gdb-check:type = bool -// gdb-command:whatis 'basic_types_globals_metadata::I' +// gdbg-command:whatis 'basic_types_globals_metadata::I' +// gdbr-command:whatis basic_types_globals_metadata::I // gdb-check:type = isize -// gdb-command:whatis 'basic_types_globals_metadata::C' +// gdbg-command:whatis 'basic_types_globals_metadata::C' +// gdbr-command:whatis basic_types_globals_metadata::C // gdb-check:type = char -// gdb-command:whatis 'basic_types_globals_metadata::I8' +// gdbg-command:whatis 'basic_types_globals_metadata::I8' +// gdbr-command:whatis basic_types_globals_metadata::I8 // gdb-check:type = i8 -// gdb-command:whatis 'basic_types_globals_metadata::I16' +// gdbg-command:whatis 'basic_types_globals_metadata::I16' +// gdbr-command:whatis basic_types_globals_metadata::I16 // gdb-check:type = i16 -// gdb-command:whatis 'basic_types_globals_metadata::I32' +// gdbg-command:whatis 'basic_types_globals_metadata::I32' +// gdbr-command:whatis basic_types_globals_metadata::I32 // gdb-check:type = i32 -// gdb-command:whatis 'basic_types_globals_metadata::I64' +// gdbg-command:whatis 'basic_types_globals_metadata::I64' +// gdbr-command:whatis basic_types_globals_metadata::I64 // gdb-check:type = i64 -// gdb-command:whatis 'basic_types_globals_metadata::U' +// gdbg-command:whatis 'basic_types_globals_metadata::U' +// gdbr-command:whatis basic_types_globals_metadata::U // gdb-check:type = usize -// gdb-command:whatis 'basic_types_globals_metadata::U8' +// gdbg-command:whatis 'basic_types_globals_metadata::U8' +// gdbr-command:whatis basic_types_globals_metadata::U8 // gdb-check:type = u8 -// gdb-command:whatis 'basic_types_globals_metadata::U16' +// gdbg-command:whatis 'basic_types_globals_metadata::U16' +// gdbr-command:whatis basic_types_globals_metadata::U16 // gdb-check:type = u16 -// gdb-command:whatis 'basic_types_globals_metadata::U32' +// gdbg-command:whatis 'basic_types_globals_metadata::U32' +// gdbr-command:whatis basic_types_globals_metadata::U32 // gdb-check:type = u32 -// gdb-command:whatis 'basic_types_globals_metadata::U64' +// gdbg-command:whatis 'basic_types_globals_metadata::U64' +// gdbr-command:whatis basic_types_globals_metadata::U64 // gdb-check:type = u64 -// gdb-command:whatis 'basic_types_globals_metadata::F32' +// gdbg-command:whatis 'basic_types_globals_metadata::F32' +// gdbr-command:whatis basic_types_globals_metadata::F32 // gdb-check:type = f32 -// gdb-command:whatis 'basic_types_globals_metadata::F64' +// gdbg-command:whatis 'basic_types_globals_metadata::F64' +// gdbr-command:whatis basic_types_globals_metadata::F64 // gdb-check:type = f64 // gdb-command:continue diff --git a/src/test/debuginfo/basic-types-globals.rs b/src/test/debuginfo/basic-types-globals.rs index ccf9508a3856c..20bc403fbbcdc 100644 --- a/src/test/debuginfo/basic-types-globals.rs +++ b/src/test/debuginfo/basic-types-globals.rs @@ -18,33 +18,48 @@ // compile-flags:-g // gdb-command:run -// gdb-command:print 'basic_types_globals::B' +// gdbg-command:print 'basic_types_globals::B' +// gdbr-command:print B // gdb-check:$1 = false -// gdb-command:print 'basic_types_globals::I' +// gdbg-command:print 'basic_types_globals::I' +// gdbr-command:print I // gdb-check:$2 = -1 -// gdb-command:print 'basic_types_globals::C' -// gdb-check:$3 = 97 -// gdb-command:print/d 'basic_types_globals::I8' +// gdbg-command:print 'basic_types_globals::C' +// gdbr-command:print C +// gdbg-check:$3 = 97 +// gdbr-check:$3 = 97 'a' +// gdbg-command:print/d 'basic_types_globals::I8' +// gdbr-command:print I8 // gdb-check:$4 = 68 -// gdb-command:print 'basic_types_globals::I16' +// gdbg-command:print 'basic_types_globals::I16' +// gdbr-command:print I16 // gdb-check:$5 = -16 -// gdb-command:print 'basic_types_globals::I32' +// gdbg-command:print 'basic_types_globals::I32' +// gdbr-command:print I32 // gdb-check:$6 = -32 -// gdb-command:print 'basic_types_globals::I64' +// gdbg-command:print 'basic_types_globals::I64' +// gdbr-command:print I64 // gdb-check:$7 = -64 -// gdb-command:print 'basic_types_globals::U' +// gdbg-command:print 'basic_types_globals::U' +// gdbr-command:print U // gdb-check:$8 = 1 -// gdb-command:print/d 'basic_types_globals::U8' +// gdbg-command:print/d 'basic_types_globals::U8' +// gdbr-command:print U8 // gdb-check:$9 = 100 -// gdb-command:print 'basic_types_globals::U16' +// gdbg-command:print 'basic_types_globals::U16' +// gdbr-command:print U16 // gdb-check:$10 = 16 -// gdb-command:print 'basic_types_globals::U32' +// gdbg-command:print 'basic_types_globals::U32' +// gdbr-command:print U32 // gdb-check:$11 = 32 -// gdb-command:print 'basic_types_globals::U64' +// gdbg-command:print 'basic_types_globals::U64' +// gdbr-command:print U64 // gdb-check:$12 = 64 -// gdb-command:print 'basic_types_globals::F32' +// gdbg-command:print 'basic_types_globals::F32' +// gdbr-command:print F32 // gdb-check:$13 = 2.5 -// gdb-command:print 'basic_types_globals::F64' +// gdbg-command:print 'basic_types_globals::F64' +// gdbr-command:print F64 // gdb-check:$14 = 3.5 // gdb-command:continue diff --git a/src/test/debuginfo/basic-types-metadata.rs b/src/test/debuginfo/basic-types-metadata.rs index 1a6b605d9d06a..8aec1a059bdc6 100644 --- a/src/test/debuginfo/basic-types-metadata.rs +++ b/src/test/debuginfo/basic-types-metadata.rs @@ -45,20 +45,29 @@ // gdb-command:whatis fnptr // gdb-check:type = [...] (*)([...]) // gdb-command:info functions _yyy -// gdb-check:[...]![...]_yyy([...]); +// gdbg-check:[...]![...]_yyy([...]); +// gdbr-check:static fn basic_types_metadata::_yyy() -> !; // gdb-command:ptype closure_0 -// gdb-check: type = struct closure { -// gdb-check: -// gdb-check: } +// gdbr-check: type = struct closure +// gdbg-check: type = struct closure { +// gdbg-check: +// gdbg-check: } // gdb-command:ptype closure_1 -// gdb-check: type = struct closure { -// gdb-check: bool *__0; -// gdb-check: } +// gdbg-check: type = struct closure { +// gdbg-check: bool *__0; +// gdbg-check: } +// gdbr-check: type = struct closure ( +// gdbr-check: bool *, +// gdbr-check: ) // gdb-command:ptype closure_2 -// gdb-check: type = struct closure { -// gdb-check: bool *__0; -// gdb-check: isize *__1; -// gdb-check: } +// gdbg-check: type = struct closure { +// gdbg-check: bool *__0; +// gdbg-check: isize *__1; +// gdbg-check: } +// gdbr-check: type = struct closure ( +// gdbr-check: bool *, +// gdbr-check: isize *, +// gdbr-check: ) // // gdb-command:continue diff --git a/src/test/debuginfo/basic-types-mut-globals.rs b/src/test/debuginfo/basic-types-mut-globals.rs index 4ebd0c9577029..62325aa53ab9f 100644 --- a/src/test/debuginfo/basic-types-mut-globals.rs +++ b/src/test/debuginfo/basic-types-mut-globals.rs @@ -21,64 +21,94 @@ // gdb-command:run // Check initializers -// gdb-command:print 'basic_types_mut_globals::B' +// gdbg-command:print 'basic_types_mut_globals::B' +// gdbr-command:print B // gdb-check:$1 = false -// gdb-command:print 'basic_types_mut_globals::I' +// gdbg-command:print 'basic_types_mut_globals::I' +// gdbr-command:print I // gdb-check:$2 = -1 -// gdb-command:print 'basic_types_mut_globals::C' -// gdb-check:$3 = 97 -// gdb-command:print/d 'basic_types_mut_globals::I8' +// gdbg-command:print/d 'basic_types_mut_globals::C' +// gdbr-command:print C +// gdbg-check:$3 = 97 +// gdbr-check:$3 = 97 'a' +// gdbg-command:print/d 'basic_types_mut_globals::I8' +// gdbr-command:print I8 // gdb-check:$4 = 68 -// gdb-command:print 'basic_types_mut_globals::I16' +// gdbg-command:print 'basic_types_mut_globals::I16' +// gdbr-command:print I16 // gdb-check:$5 = -16 -// gdb-command:print 'basic_types_mut_globals::I32' +// gdbg-command:print 'basic_types_mut_globals::I32' +// gdbr-command:print I32 // gdb-check:$6 = -32 -// gdb-command:print 'basic_types_mut_globals::I64' +// gdbg-command:print 'basic_types_mut_globals::I64' +// gdbr-command:print I64 // gdb-check:$7 = -64 -// gdb-command:print 'basic_types_mut_globals::U' +// gdbg-command:print 'basic_types_mut_globals::U' +// gdbr-command:print U // gdb-check:$8 = 1 -// gdb-command:print/d 'basic_types_mut_globals::U8' +// gdbg-command:print/d 'basic_types_mut_globals::U8' +// gdbr-command:print U8 // gdb-check:$9 = 100 -// gdb-command:print 'basic_types_mut_globals::U16' +// gdbg-command:print 'basic_types_mut_globals::U16' +// gdbr-command:print U16 // gdb-check:$10 = 16 -// gdb-command:print 'basic_types_mut_globals::U32' +// gdbg-command:print 'basic_types_mut_globals::U32' +// gdbr-command:print U32 // gdb-check:$11 = 32 -// gdb-command:print 'basic_types_mut_globals::U64' +// gdbg-command:print 'basic_types_mut_globals::U64' +// gdbr-command:print U64 // gdb-check:$12 = 64 -// gdb-command:print 'basic_types_mut_globals::F32' +// gdbg-command:print 'basic_types_mut_globals::F32' +// gdbr-command:print F32 // gdb-check:$13 = 2.5 -// gdb-command:print 'basic_types_mut_globals::F64' +// gdbg-command:print 'basic_types_mut_globals::F64' +// gdbr-command:print F64 // gdb-check:$14 = 3.5 // gdb-command:continue // Check new values -// gdb-command:print 'basic_types_mut_globals'::B +// gdbg-command:print 'basic_types_mut_globals'::B +// gdbr-command:print B // gdb-check:$15 = true -// gdb-command:print 'basic_types_mut_globals'::I +// gdbg-command:print 'basic_types_mut_globals'::I +// gdbr-command:print I // gdb-check:$16 = 2 -// gdb-command:print 'basic_types_mut_globals'::C -// gdb-check:$17 = 102 -// gdb-command:print/d 'basic_types_mut_globals'::I8 +// gdbg-command:print/d 'basic_types_mut_globals'::C +// gdbr-command:print C +// gdbg-check:$17 = 102 +// gdbr-check:$17 = 102 'f' +// gdbg-command:print/d 'basic_types_mut_globals'::I8 +// gdbr-command:print/d I8 // gdb-check:$18 = 78 -// gdb-command:print 'basic_types_mut_globals'::I16 +// gdbg-command:print 'basic_types_mut_globals'::I16 +// gdbr-command:print I16 // gdb-check:$19 = -26 -// gdb-command:print 'basic_types_mut_globals'::I32 +// gdbg-command:print 'basic_types_mut_globals'::I32 +// gdbr-command:print I32 // gdb-check:$20 = -12 -// gdb-command:print 'basic_types_mut_globals'::I64 +// gdbg-command:print 'basic_types_mut_globals'::I64 +// gdbr-command:print I64 // gdb-check:$21 = -54 -// gdb-command:print 'basic_types_mut_globals'::U +// gdbg-command:print 'basic_types_mut_globals'::U +// gdbr-command:print U // gdb-check:$22 = 5 -// gdb-command:print/d 'basic_types_mut_globals'::U8 +// gdbg-command:print/d 'basic_types_mut_globals'::U8 +// gdbr-command:print/d U8 // gdb-check:$23 = 20 -// gdb-command:print 'basic_types_mut_globals'::U16 +// gdbg-command:print 'basic_types_mut_globals'::U16 +// gdbr-command:print U16 // gdb-check:$24 = 32 -// gdb-command:print 'basic_types_mut_globals'::U32 +// gdbg-command:print 'basic_types_mut_globals'::U32 +// gdbr-command:print U32 // gdb-check:$25 = 16 -// gdb-command:print 'basic_types_mut_globals'::U64 +// gdbg-command:print 'basic_types_mut_globals'::U64 +// gdbr-command:print U64 // gdb-check:$26 = 128 -// gdb-command:print 'basic_types_mut_globals'::F32 +// gdbg-command:print 'basic_types_mut_globals'::F32 +// gdbr-command:print F32 // gdb-check:$27 = 5.75 -// gdb-command:print 'basic_types_mut_globals'::F64 +// gdbg-command:print 'basic_types_mut_globals'::F64 +// gdbr-command:print F64 // gdb-check:$28 = 9.25 #![allow(unused_variables)] diff --git a/src/test/debuginfo/basic-types.rs b/src/test/debuginfo/basic-types.rs index 998010832881b..01ce5bd31626e 100644 --- a/src/test/debuginfo/basic-types.rs +++ b/src/test/debuginfo/basic-types.rs @@ -26,7 +26,8 @@ // gdb-command:print i // gdb-check:$2 = -1 // gdb-command:print c -// gdb-check:$3 = 97 +// gdbg-check:$3 = 97 +// gdbr-check:$3 = 97 'a' // gdb-command:print/d i8 // gdb-check:$4 = 68 // gdb-command:print i16 diff --git a/src/test/debuginfo/borrowed-basic.rs b/src/test/debuginfo/borrowed-basic.rs index bada77b66293c..f6c0ff09efe93 100644 --- a/src/test/debuginfo/borrowed-basic.rs +++ b/src/test/debuginfo/borrowed-basic.rs @@ -25,10 +25,12 @@ // gdb-check:$2 = -1 // gdb-command:print *char_ref -// gdb-check:$3 = 97 +// gdbg-check:$3 = 97 +// gdbr-check:$3 = 97 'a' // gdb-command:print *i8_ref -// gdb-check:$4 = 68 'D' +// gdbg-check:$4 = 68 'D' +// gdbr-check:$4 = 68 // gdb-command:print *i16_ref // gdb-check:$5 = -16 @@ -43,7 +45,8 @@ // gdb-check:$8 = 1 // gdb-command:print *u8_ref -// gdb-check:$9 = 100 'd' +// gdbg-check:$9 = 100 'd' +// gdbr-check:$9 = 100 // gdb-command:print *u16_ref // gdb-check:$10 = 16 diff --git a/src/test/debuginfo/borrowed-c-style-enum.rs b/src/test/debuginfo/borrowed-c-style-enum.rs index c80783ef31068..d6f379634be5b 100644 --- a/src/test/debuginfo/borrowed-c-style-enum.rs +++ b/src/test/debuginfo/borrowed-c-style-enum.rs @@ -17,13 +17,16 @@ // gdb-command:run // gdb-command:print *the_a_ref -// gdb-check:$1 = TheA +// gdbg-check:$1 = TheA +// gdbr-check:$1 = borrowed_c_style_enum::ABC::TheA // gdb-command:print *the_b_ref -// gdb-check:$2 = TheB +// gdbg-check:$2 = TheB +// gdbr-check:$2 = borrowed_c_style_enum::ABC::TheB // gdb-command:print *the_c_ref -// gdb-check:$3 = TheC +// gdbg-check:$3 = TheC +// gdbr-check:$3 = borrowed_c_style_enum::ABC::TheC // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/borrowed-enum.rs b/src/test/debuginfo/borrowed-enum.rs index b21574e32866b..ddc29c6430270 100644 --- a/src/test/debuginfo/borrowed-enum.rs +++ b/src/test/debuginfo/borrowed-enum.rs @@ -18,13 +18,16 @@ // gdb-command:run // gdb-command:print *the_a_ref -// gdb-check:$1 = {{RUST$ENUM$DISR = TheA, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = TheA, __0 = 0, __1 = 2088533116, __2 = 2088533116}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = TheA, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = TheA, __0 = 0, __1 = 2088533116, __2 = 2088533116}} +// gdbr-check:$1 = borrowed_enum::ABC::TheA{x: 0, y: 8970181431921507452} // gdb-command:print *the_b_ref -// gdb-check:$2 = {{RUST$ENUM$DISR = TheB, x = 0, y = 1229782938247303441}, {RUST$ENUM$DISR = TheB, __0 = 0, __1 = 286331153, __2 = 286331153}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = TheB, x = 0, y = 1229782938247303441}, {RUST$ENUM$DISR = TheB, __0 = 0, __1 = 286331153, __2 = 286331153}} +// gdbr-check:$2 = borrowed_enum::ABC::TheB(0, 286331153, 286331153) // gdb-command:print *univariant_ref -// gdb-check:$3 = {{__0 = 4820353753753434}} +// gdbg-check:$3 = {{__0 = 4820353753753434}} +// gdbr-check:$3 = borrowed_enum::Univariant::TheOnlyCase(4820353753753434) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/borrowed-struct.rs b/src/test/debuginfo/borrowed-struct.rs index ab41185cb7391..01428e515e27f 100644 --- a/src/test/debuginfo/borrowed-struct.rs +++ b/src/test/debuginfo/borrowed-struct.rs @@ -16,7 +16,8 @@ // gdb-command:run // gdb-command:print *stack_val_ref -// gdb-check:$1 = {x = 10, y = 23.5} +// gdbg-check:$1 = {x = 10, y = 23.5} +// gdbr-check:$1 = borrowed_struct::SomeStruct {x: 10, y: 23.5} // gdb-command:print *stack_val_interior_ref_1 // gdb-check:$2 = 10 @@ -25,10 +26,12 @@ // gdb-check:$3 = 23.5 // gdb-command:print *ref_to_unnamed -// gdb-check:$4 = {x = 11, y = 24.5} +// gdbg-check:$4 = {x = 11, y = 24.5} +// gdbr-check:$4 = borrowed_struct::SomeStruct {x: 11, y: 24.5} // gdb-command:print *unique_val_ref -// gdb-check:$5 = {x = 13, y = 26.5} +// gdbg-check:$5 = {x = 13, y = 26.5} +// gdbr-check:$5 = borrowed_struct::SomeStruct {x: 13, y: 26.5} // gdb-command:print *unique_val_interior_ref_1 // gdb-check:$6 = 13 diff --git a/src/test/debuginfo/borrowed-tuple.rs b/src/test/debuginfo/borrowed-tuple.rs index e3da3934f6d69..17db88ee37f53 100644 --- a/src/test/debuginfo/borrowed-tuple.rs +++ b/src/test/debuginfo/borrowed-tuple.rs @@ -17,13 +17,16 @@ // gdb-command:run // gdb-command:print *stack_val_ref -// gdb-check:$1 = {__0 = -14, __1 = -19} +// gdbg-check:$1 = {__0 = -14, __1 = -19} +// gdbr-check:$1 = (-14, -19) // gdb-command:print *ref_to_unnamed -// gdb-check:$2 = {__0 = -15, __1 = -20} +// gdbg-check:$2 = {__0 = -15, __1 = -20} +// gdbr-check:$2 = (-15, -20) // gdb-command:print *unique_val_ref -// gdb-check:$3 = {__0 = -17, __1 = -22} +// gdbg-check:$3 = {__0 = -17, __1 = -22} +// gdbr-check:$3 = (-17, -22) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/borrowed-unique-basic.rs b/src/test/debuginfo/borrowed-unique-basic.rs index 88af94c53628c..9e95498b0c30e 100644 --- a/src/test/debuginfo/borrowed-unique-basic.rs +++ b/src/test/debuginfo/borrowed-unique-basic.rs @@ -26,7 +26,8 @@ // gdb-check:$2 = -1 // gdb-command:print *char_ref -// gdb-check:$3 = 97 +// gdbg-check:$3 = 97 +// gdbr-check:$3 = 97 'a' // gdb-command:print/d *i8_ref // gdb-check:$4 = 68 diff --git a/src/test/debuginfo/box.rs b/src/test/debuginfo/box.rs index 106d0b243eb26..98c09fe09de8f 100644 --- a/src/test/debuginfo/box.rs +++ b/src/test/debuginfo/box.rs @@ -19,7 +19,8 @@ // gdb-command:print *a // gdb-check:$1 = 1 // gdb-command:print *b -// gdb-check:$2 = {__0 = 2, __1 = 3.5} +// gdbg-check:$2 = {__0 = 2, __1 = 3.5} +// gdbr-check:$2 = (2, 3.5) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/boxed-struct.rs b/src/test/debuginfo/boxed-struct.rs index dd543405e4c27..ac091b4a533db 100644 --- a/src/test/debuginfo/boxed-struct.rs +++ b/src/test/debuginfo/boxed-struct.rs @@ -17,10 +17,12 @@ // gdb-command:run // gdb-command:print *unique -// gdb-check:$1 = {x = 99, y = 999, z = 9999, w = 99999} +// gdbg-check:$1 = {x = 99, y = 999, z = 9999, w = 99999} +// gdbr-check:$1 = boxed_struct::StructWithSomePadding {x: 99, y: 999, z: 9999, w: 99999} // gdb-command:print *unique_dtor -// gdb-check:$2 = {x = 77, y = 777, z = 7777, w = 77777} +// gdbg-check:$2 = {x = 77, y = 777, z = 7777, w = 77777} +// gdbr-check:$2 = boxed_struct::StructWithDestructor {x: 77, y: 777, z: 7777, w: 77777} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/by-value-non-immediate-argument.rs b/src/test/debuginfo/by-value-non-immediate-argument.rs index a329ef6d0e090..6d821dbc155d0 100644 --- a/src/test/debuginfo/by-value-non-immediate-argument.rs +++ b/src/test/debuginfo/by-value-non-immediate-argument.rs @@ -18,11 +18,13 @@ // gdb-command:run // gdb-command:print s -// gdb-check:$1 = {a = 1, b = 2.5} +// gdbg-check:$1 = {a = 1, b = 2.5} +// gdbr-check:$1 = by_value_non_immediate_argument::Struct {a: 1, b: 2.5} // gdb-command:continue // gdb-command:print x -// gdb-check:$2 = {a = 3, b = 4.5} +// gdbg-check:$2 = {a = 3, b = 4.5} +// gdbr-check:$2 = by_value_non_immediate_argument::Struct {a: 3, b: 4.5} // gdb-command:print y // gdb-check:$3 = 5 // gdb-command:print z @@ -30,15 +32,18 @@ // gdb-command:continue // gdb-command:print a -// gdb-check:$5 = {__0 = 7, __1 = 8, __2 = 9.5, __3 = 10.5} +// gdbg-check:$5 = {__0 = 7, __1 = 8, __2 = 9.5, __3 = 10.5} +// gdbr-check:$5 = (7, 8, 9.5, 10.5) // gdb-command:continue // gdb-command:print a -// gdb-check:$6 = {__0 = 11.5, __1 = 12.5, __2 = 13, __3 = 14} +// gdbg-check:$6 = {__0 = 11.5, __1 = 12.5, __2 = 13, __3 = 14} +// gdbr-check:$6 = by_value_non_immediate_argument::Newtype (11.5, 12.5, 13, 14) // gdb-command:continue // gdb-command:print x -// gdb-check:$7 = {{RUST$ENUM$DISR = Case1, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 2088533116, __2 = 2088533116}} +// gdbg-check:$7 = {{RUST$ENUM$DISR = Case1, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 2088533116, __2 = 2088533116}} +// gdbr-check:$7 = by_value_non_immediate_argument::Enum::Case1{x: 0, y: 8970181431921507452} // gdb-command:continue diff --git a/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs b/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs index a768bfdd16764..c14f8c7b354fc 100644 --- a/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs +++ b/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs @@ -21,11 +21,13 @@ // gdb-command:continue // gdb-command:print self -// gdb-check:$2 = {x = 2222, y = 3333} +// gdbg-check:$2 = {x = 2222, y = 3333} +// gdbr-check:$2 = by_value_self_argument_in_trait_impl::Struct {x: 2222, y: 3333} // gdb-command:continue // gdb-command:print self -// gdb-check:$3 = {__0 = 4444.5, __1 = 5555, __2 = 6666, __3 = 7777.5} +// gdbg-check:$3 = {__0 = 4444.5, __1 = 5555, __2 = 6666, __3 = 7777.5} +// gdbr-check:$3 = (4444.5, 5555, 6666, 7777.5) // gdb-command:continue diff --git a/src/test/debuginfo/c-style-enum-in-composite.rs b/src/test/debuginfo/c-style-enum-in-composite.rs index 83a22edc96fe1..004e15d1cc6c1 100644 --- a/src/test/debuginfo/c-style-enum-in-composite.rs +++ b/src/test/debuginfo/c-style-enum-in-composite.rs @@ -18,26 +18,32 @@ // gdb-command:run // gdb-command:print tuple_interior_padding -// gdb-check:$1 = {__0 = 0, __1 = OneHundred} +// gdbg-check:$1 = {__0 = 0, __1 = OneHundred} +// gdbr-check:$1 = (0, c_style_enum_in_composite::AnEnum::OneHundred) // gdb-command:print tuple_padding_at_end -// gdb-check:$2 = {__0 = {__0 = 1, __1 = OneThousand}, __1 = 2} +// gdbg-check:$2 = {__0 = {__0 = 1, __1 = OneThousand}, __1 = 2} +// gdbr-check:$2 = ((1, c_style_enum_in_composite::AnEnum::OneThousand), 2) // gdb-command:print tuple_different_enums -// gdb-check:$3 = {__0 = OneThousand, __1 = MountainView, __2 = OneMillion, __3 = Vienna} +// gdbg-check:$3 = {__0 = OneThousand, __1 = MountainView, __2 = OneMillion, __3 = Vienna} +// gdbr-check:$3 = (c_style_enum_in_composite::AnEnum::OneThousand, c_style_enum_in_composite::AnotherEnum::MountainView, c_style_enum_in_composite::AnEnum::OneMillion, c_style_enum_in_composite::AnotherEnum::Vienna) // gdb-command:print padded_struct -// gdb-check:$4 = {a = 3, b = OneMillion, c = 4, d = Toronto, e = 5} +// gdbg-check:$4 = {a = 3, b = OneMillion, c = 4, d = Toronto, e = 5} +// gdbr-check:$4 = c_style_enum_in_composite::PaddedStruct {a: 3, b: c_style_enum_in_composite::AnEnum::OneMillion, c: 4, d: c_style_enum_in_composite::AnotherEnum::Toronto, e: 5} // gdb-command:print packed_struct -// gdb-check:$5 = {a = 6, b = OneHundred, c = 7, d = Vienna, e = 8} +// gdbg-check:$5 = {a = 6, b = OneHundred, c = 7, d = Vienna, e = 8} +// gdbr-check:$5 = c_style_enum_in_composite::PackedStruct {a: 6, b: c_style_enum_in_composite::AnEnum::OneHundred, c: 7, d: c_style_enum_in_composite::AnotherEnum::Vienna, e: 8} // gdb-command:print non_padded_struct -// gdb-check:$6 = {a = OneMillion, b = MountainView, c = OneThousand, d = Toronto} +// gdbg-check:$6 = {a = OneMillion, b = MountainView, c = OneThousand, d = Toronto} +// gdbr-check:$6 = c_style_enum_in_composite::NonPaddedStruct {a: c_style_enum_in_composite::AnEnum::OneMillion, b: c_style_enum_in_composite::AnotherEnum::MountainView, c: c_style_enum_in_composite::AnEnum::OneThousand, d: c_style_enum_in_composite::AnotherEnum::Toronto} // gdb-command:print struct_with_drop -// gdb-check:$7 = {__0 = {a = OneHundred, b = Vienna}, __1 = 9} - +// gdbg-check:$7 = {__0 = {a = OneHundred, b = Vienna}, __1 = 9} +// gdbr-check:$7 = (c_style_enum_in_composite::StructWithDrop {a: c_style_enum_in_composite::AnEnum::OneHundred, b: c_style_enum_in_composite::AnotherEnum::Vienna}, 9) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/c-style-enum.rs b/src/test/debuginfo/c-style-enum.rs index dbd336d2dc688..2452c18f54347 100644 --- a/src/test/debuginfo/c-style-enum.rs +++ b/src/test/debuginfo/c-style-enum.rs @@ -16,60 +16,82 @@ // === GDB TESTS =================================================================================== // gdb-command:print 'c_style_enum::SINGLE_VARIANT' -// gdb-check:$1 = TheOnlyVariant +// gdbg-check:$1 = TheOnlyVariant +// gdbr-check:$1 = c_style_enum::SingleVariant::TheOnlyVariant // gdb-command:print 'c_style_enum::AUTO_ONE' -// gdb-check:$2 = One +// gdbg-check:$2 = One +// gdbr-check:$2 = c_style_enum::AutoDiscriminant::One // gdb-command:print 'c_style_enum::AUTO_TWO' -// gdb-check:$3 = One +// gdbg-check:$3 = One +// gdbr-check:$3 = c_style_enum::AutoDiscriminant::One // gdb-command:print 'c_style_enum::AUTO_THREE' -// gdb-check:$4 = One +// gdbg-check:$4 = One +// gdbr-check:$4 = c_style_enum::AutoDiscriminant::One // gdb-command:print 'c_style_enum::MANUAL_ONE' -// gdb-check:$5 = OneHundred +// gdbg-check:$5 = OneHundred +// gdbr-check:$5 = c_style_enum::ManualDiscriminant::OneHundred // gdb-command:print 'c_style_enum::MANUAL_TWO' -// gdb-check:$6 = OneHundred +// gdbg-check:$6 = OneHundred +// gdbr-check:$6 = c_style_enum::ManualDiscriminant::OneHundred // gdb-command:print 'c_style_enum::MANUAL_THREE' -// gdb-check:$7 = OneHundred +// gdbg-check:$7 = OneHundred +// gdbr-check:$7 = c_style_enum::ManualDiscriminant::OneHundred // gdb-command:run // gdb-command:print auto_one -// gdb-check:$8 = One +// gdbg-check:$8 = One +// gdbr-check:$8 = c_style_enum::AutoDiscriminant::One // gdb-command:print auto_two -// gdb-check:$9 = Two +// gdbg-check:$9 = Two +// gdbr-check:$9 = c_style_enum::AutoDiscriminant::Two // gdb-command:print auto_three -// gdb-check:$10 = Three +// gdbg-check:$10 = Three +// gdbr-check:$10 = c_style_enum::AutoDiscriminant::Three // gdb-command:print manual_one_hundred -// gdb-check:$11 = OneHundred +// gdbg-check:$11 = OneHundred +// gdbr-check:$11 = c_style_enum::ManualDiscriminant::OneHundred // gdb-command:print manual_one_thousand -// gdb-check:$12 = OneThousand +// gdbg-check:$12 = OneThousand +// gdbr-check:$12 = c_style_enum::ManualDiscriminant::OneThousand // gdb-command:print manual_one_million -// gdb-check:$13 = OneMillion +// gdbg-check:$13 = OneMillion +// gdbr-check:$13 = c_style_enum::ManualDiscriminant::OneMillion // gdb-command:print single_variant -// gdb-check:$14 = TheOnlyVariant - -// gdb-command:print 'c_style_enum::AUTO_TWO' -// gdb-check:$15 = Two - -// gdb-command:print 'c_style_enum::AUTO_THREE' -// gdb-check:$16 = Three - -// gdb-command:print 'c_style_enum::MANUAL_TWO' -// gdb-check:$17 = OneThousand - -// gdb-command:print 'c_style_enum::MANUAL_THREE' -// gdb-check:$18 = OneMillion +// gdbg-check:$14 = TheOnlyVariant +// gdbr-check:$14 = c_style_enum::SingleVariant::TheOnlyVariant + +// gdbg-command:print 'c_style_enum::AUTO_TWO' +// gdbr-command:print AUTO_TWO +// gdbg-check:$15 = Two +// gdbr-check:$15 = c_style_enum::AutoDiscriminant::Two + +// gdbg-command:print 'c_style_enum::AUTO_THREE' +// gdbr-command:print AUTO_THREE +// gdbg-check:$16 = Three +// gdbr-check:$16 = c_style_enum::AutoDiscriminant::Three + +// gdbg-command:print 'c_style_enum::MANUAL_TWO' +// gdbr-command:print MANUAL_TWO +// gdbg-check:$17 = OneThousand +// gdbr-check:$17 = c_style_enum::ManualDiscriminant::OneThousand + +// gdbg-command:print 'c_style_enum::MANUAL_THREE' +// gdbr-command:print MANUAL_THREE +// gdbg-check:$18 = OneMillion +// gdbr-check:$18 = c_style_enum::ManualDiscriminant::OneMillion // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/cross-crate-spans.rs b/src/test/debuginfo/cross-crate-spans.rs index 544fe2c66d5e8..28728df928051 100644 --- a/src/test/debuginfo/cross-crate-spans.rs +++ b/src/test/debuginfo/cross-crate-spans.rs @@ -25,7 +25,8 @@ extern crate cross_crate_spans; // gdb-command:run // gdb-command:print result -// gdb-check:$1 = {__0 = 17, __1 = 17} +// gdbg-check:$1 = {__0 = 17, __1 = 17} +// gdbr-check:$1 = (17, 17) // gdb-command:print a_variable // gdb-check:$2 = 123456789 // gdb-command:print another_variable @@ -33,7 +34,8 @@ extern crate cross_crate_spans; // gdb-command:continue // gdb-command:print result -// gdb-check:$4 = {__0 = 1212, __1 = 1212} +// gdbg-check:$4 = {__0 = 1212, __1 = 1212} +// gdbr-check:$4 = (1212, 1212) // gdb-command:print a_variable // gdb-check:$5 = 123456789 // gdb-command:print another_variable diff --git a/src/test/debuginfo/destructured-fn-argument.rs b/src/test/debuginfo/destructured-fn-argument.rs index 954a7abe6323c..efa9ee59b22b2 100644 --- a/src/test/debuginfo/destructured-fn-argument.rs +++ b/src/test/debuginfo/destructured-fn-argument.rs @@ -33,13 +33,15 @@ // gdb-command:print a // gdb-check:$6 = 5 // gdb-command:print b -// gdb-check:$7 = {__0 = 6, __1 = 7} +// gdbg-check:$7 = {__0 = 6, __1 = 7} +// gdbr-check:$7 = (6, 7) // gdb-command:continue // gdb-command:print h // gdb-check:$8 = 8 // gdb-command:print i -// gdb-check:$9 = {a = 9, b = 10} +// gdbg-check:$9 = {a = 9, b = 10} +// gdbr-check:$9 = destructured_fn_argument::Struct {a: 9, b: 10} // gdb-command:print j // gdb-check:$10 = 11 // gdb-command:continue @@ -65,7 +67,8 @@ // gdb-command:print q // gdb-check:$17 = 20 // gdb-command:print r -// gdb-check:$18 = {a = 21, b = 22} +// gdbg-check:$18 = {a = 21, b = 22} +// gdbr-check:$18 = destructured_fn_argument::Struct {a: 21, b: 22} // gdb-command:continue // gdb-command:print s @@ -95,11 +98,13 @@ // gdb-command:continue // gdb-command:print aa -// gdb-check:$30 = {__0 = 34, __1 = 35} +// gdbg-check:$30 = {__0 = 34, __1 = 35} +// gdbr-check:$30 = (34, 35) // gdb-command:continue // gdb-command:print bb -// gdb-check:$31 = {__0 = 36, __1 = 37} +// gdbg-check:$31 = {__0 = 36, __1 = 37} +// gdbr-check:$31 = (36, 37) // gdb-command:continue // gdb-command:print cc @@ -107,17 +112,20 @@ // gdb-command:continue // gdb-command:print dd -// gdb-check:$33 = {__0 = 40, __1 = 41, __2 = 42} +// gdbg-check:$33 = {__0 = 40, __1 = 41, __2 = 42} +// gdbr-check:$33 = (40, 41, 42) // gdb-command:continue // gdb-command:print *ee -// gdb-check:$34 = {__0 = 43, __1 = 44, __2 = 45} +// gdbg-check:$34 = {__0 = 43, __1 = 44, __2 = 45} +// gdbr-check:$34 = (43, 44, 45) // gdb-command:continue // gdb-command:print *ff // gdb-check:$35 = 46 // gdb-command:print gg -// gdb-check:$36 = {__0 = 47, __1 = 48} +// gdbg-check:$36 = {__0 = 47, __1 = 48} +// gdbr-check:$36 = (47, 48) // gdb-command:continue // gdb-command:print *hh diff --git a/src/test/debuginfo/destructured-for-loop-variable.rs b/src/test/debuginfo/destructured-for-loop-variable.rs index a34d5d6adbfcb..e973c22fd4a85 100644 --- a/src/test/debuginfo/destructured-for-loop-variable.rs +++ b/src/test/debuginfo/destructured-for-loop-variable.rs @@ -73,11 +73,13 @@ // gdb-command:continue // gdb-command:print simple_struct_ident -// gdb-check:$23 = {x = 3537, y = 35437.5, z = true} +// gdbg-check:$23 = {x = 3537, y = 35437.5, z = true} +// gdbr-check:$23 = destructured_for_loop_variable::Struct {x: 3537, y: 35437.5, z: true} // gdb-command:continue // gdb-command:print simple_tuple_ident -// gdb-check:$24 = {__0 = 34903493, __1 = 232323} +// gdbg-check:$24 = {__0 = 34903493, __1 = 232323} +// gdbr-check:$24 = (34903493, 232323) // gdb-command:continue // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/destructured-local.rs b/src/test/debuginfo/destructured-local.rs index a43e4546d4f8f..1f18b77ab8f6f 100644 --- a/src/test/debuginfo/destructured-local.rs +++ b/src/test/debuginfo/destructured-local.rs @@ -31,12 +31,14 @@ // gdb-command:print f // gdb-check:$6 = 5 // gdb-command:print g -// gdb-check:$7 = {__0 = 6, __1 = 7} +// gdbg-check:$7 = {__0 = 6, __1 = 7} +// gdbr-check:$7 = (6, 7) // gdb-command:print h // gdb-check:$8 = 8 // gdb-command:print i -// gdb-check:$9 = {a = 9, b = 10} +// gdbg-check:$9 = {a = 9, b = 10} +// gdbr-check:$9 = destructured_local::Struct {a: 9, b: 10} // gdb-command:print j // gdb-check:$10 = 11 @@ -58,7 +60,8 @@ // gdb-command:print q // gdb-check:$17 = 20 // gdb-command:print r -// gdb-check:$18 = {a = 21, b = 22} +// gdbg-check:$18 = {a = 21, b = 22} +// gdbr-check:$18 = destructured_local::Struct {a: 21, b: 22} // gdb-command:print s // gdb-check:$19 = 24 @@ -85,25 +88,30 @@ // gdb-check:$29 = 33 // gdb-command:print aa -// gdb-check:$30 = {__0 = 34, __1 = 35} +// gdbg-check:$30 = {__0 = 34, __1 = 35} +// gdbr-check:$30 = (34, 35) // gdb-command:print bb -// gdb-check:$31 = {__0 = 36, __1 = 37} +// gdbg-check:$31 = {__0 = 36, __1 = 37} +// gdbr-check:$31 = (36, 37) // gdb-command:print cc // gdb-check:$32 = 38 // gdb-command:print dd -// gdb-check:$33 = {__0 = 40, __1 = 41, __2 = 42} +// gdbg-check:$33 = {__0 = 40, __1 = 41, __2 = 42} +// gdbr-check:$33 = (40, 41, 42) // gdb-command:print *ee -// gdb-check:$34 = {__0 = 43, __1 = 44, __2 = 45} +// gdbg-check:$34 = {__0 = 43, __1 = 44, __2 = 45} +// gdbr-check:$34 = (43, 44, 45) // gdb-command:print *ff // gdb-check:$35 = 46 // gdb-command:print gg -// gdb-check:$36 = {__0 = 47, __1 = 48} +// gdbg-check:$36 = {__0 = 47, __1 = 48} +// gdbr-check:$36 = (47, 48) // gdb-command:print *hh // gdb-check:$37 = 50 diff --git a/src/test/debuginfo/evec-in-struct.rs b/src/test/debuginfo/evec-in-struct.rs index 8624a0cba0256..2e151577590b3 100644 --- a/src/test/debuginfo/evec-in-struct.rs +++ b/src/test/debuginfo/evec-in-struct.rs @@ -17,18 +17,23 @@ // gdb-command:run // gdb-command:print no_padding1 -// gdb-check:$1 = {x = {0, 1, 2}, y = -3, z = {4.5, 5.5}} +// gdbg-check:$1 = {x = {0, 1, 2}, y = -3, z = {4.5, 5.5}} +// gdbr-check:$1 = evec_in_struct::NoPadding1 {x: [0, 1, 2], y: -3, z: [4.5, 5.5]} // gdb-command:print no_padding2 -// gdb-check:$2 = {x = {6, 7, 8}, y = {{9, 10}, {11, 12}}} +// gdbg-check:$2 = {x = {6, 7, 8}, y = {{9, 10}, {11, 12}}} +// gdbr-check:$2 = evec_in_struct::NoPadding2 {x: [6, 7, 8], y: [[9, 10], [11, 12]]} // gdb-command:print struct_internal_padding -// gdb-check:$3 = {x = {13, 14}, y = {15, 16}} +// gdbg-check:$3 = {x = {13, 14}, y = {15, 16}} +// gdbr-check:$3 = evec_in_struct::StructInternalPadding {x: [13, 14], y: [15, 16]} // gdb-command:print single_vec -// gdb-check:$4 = {x = {17, 18, 19, 20, 21}} +// gdbg-check:$4 = {x = {17, 18, 19, 20, 21}} +// gdbr-check:$4 = evec_in_struct::SingleVec {x: [17, 18, 19, 20, 21]} // gdb-command:print struct_padded_at_end -// gdb-check:$5 = {x = {22, 23}, y = {24, 25}} +// gdbg-check:$5 = {x = {22, 23}, y = {24, 25}} +// gdbr-check:$5 = evec_in_struct::StructPaddedAtEnd {x: [22, 23], y: [24, 25]} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/extern-c-fn.rs b/src/test/debuginfo/extern-c-fn.rs index c93db41dc55bf..01901b2c42b8e 100644 --- a/src/test/debuginfo/extern-c-fn.rs +++ b/src/test/debuginfo/extern-c-fn.rs @@ -16,7 +16,8 @@ // gdb-command:run // gdb-command:print s -// gdb-check:$1 = [...]"abcd" +// gdbg-check:$1 = [...]"abcd" +// gdbr-check:$1 = [...]"abcd\000" // gdb-command:print len // gdb-check:$2 = 20 // gdb-command:print local0 diff --git a/src/test/debuginfo/function-arg-initialization.rs b/src/test/debuginfo/function-arg-initialization.rs index 57654acaf73d8..21fdc4e5e88a6 100644 --- a/src/test/debuginfo/function-arg-initialization.rs +++ b/src/test/debuginfo/function-arg-initialization.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-linelength + // min-lldb-version: 310 // This test case checks if function arguments already have the correct value @@ -34,9 +36,11 @@ // NON IMMEDIATE ARGS // gdb-command:print a -// gdb-check:$4 = {a = 3, b = 4, c = 5, d = 6, e = 7, f = 8, g = 9, h = 10} +// gdbg-check:$4 = {a = 3, b = 4, c = 5, d = 6, e = 7, f = 8, g = 9, h = 10} +// gdbt-check:$4 = function_arg_initialization::BigStruct {a: 3, b: 4, c: 5, d: 6, e: 7, f: 8, g: 9, h: 10} // gdb-command:print b -// gdb-check:$5 = {a = 11, b = 12, c = 13, d = 14, e = 15, f = 16, g = 17, h = 18} +// gdbg-check:$5 = {a = 11, b = 12, c = 13, d = 14, e = 15, f = 16, g = 17, h = 18} +// gdbt-check:$5 = function_arg_initialization::BigStruct {a: 11, b: 12, c: 13, d: 14, e: 15, f: 16, g: 17, h: 18} // gdb-command:continue // BINDING diff --git a/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs b/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs index 81743a367e40f..158a1f17fc03d 100644 --- a/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs +++ b/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs @@ -26,13 +26,16 @@ // gdb-check:$2 = EmptyStruct // gdb-command: print c_style_enum1 -// gdb-check:$3 = CStyleEnumVar1 +// gdbg-check:$3 = CStyleEnumVar1 +// gdbr-check:$3 = gdb_pretty_struct_and_enums_pre_gdb_7_7::CStyleEnum::CStyleEnumVar1 // gdb-command: print c_style_enum2 -// gdb-check:$4 = CStyleEnumVar2 +// gdbg-check:$4 = CStyleEnumVar2 +// gdbr-check:$4 = gdb_pretty_struct_and_enums_pre_gdb_7_7::CStyleEnum::CStyleEnumVar2 // gdb-command: print c_style_enum3 -// gdb-check:$5 = CStyleEnumVar3 +// gdbg-check:$5 = CStyleEnumVar3 +// gdbr-check:$5 = gdb_pretty_struct_and_enums_pre_gdb_7_7::CStyleEnum::CStyleEnumVar3 #![allow(dead_code, unused_variables)] diff --git a/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs b/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs index 3115b3f7e761c..1fc05b3752f04 100644 --- a/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs +++ b/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs @@ -18,22 +18,37 @@ // gdb-command:run // gdb-command:print eight_bytes1 -// gdb-check:$1 = {{RUST$ENUM$DISR = Variant1, __0 = 100}, {RUST$ENUM$DISR = Variant1, __0 = 100}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = Variant1, __0 = 100}, {RUST$ENUM$DISR = Variant1, __0 = 100}} +// gdbr-check:$1 = generic_enum_with_different_disr_sizes::Enum::Variant1(100) + // gdb-command:print four_bytes1 -// gdb-check:$2 = {{RUST$ENUM$DISR = Variant1, __0 = 101}, {RUST$ENUM$DISR = Variant1, __0 = 101}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = Variant1, __0 = 101}, {RUST$ENUM$DISR = Variant1, __0 = 101}} +// gdbr-check:$2 = generic_enum_with_different_disr_sizes::Enum::Variant1(101) + // gdb-command:print two_bytes1 -// gdb-check:$3 = {{RUST$ENUM$DISR = Variant1, __0 = 102}, {RUST$ENUM$DISR = Variant1, __0 = 102}} +// gdbg-check:$3 = {{RUST$ENUM$DISR = Variant1, __0 = 102}, {RUST$ENUM$DISR = Variant1, __0 = 102}} +// gdbr-check:$3 = generic_enum_with_different_disr_sizes::Enum::Variant1(102) + // gdb-command:print one_byte1 -// gdb-check:$4 = {{RUST$ENUM$DISR = Variant1, __0 = 65 'A'}, {RUST$ENUM$DISR = Variant1, __0 = 65 'A'}} +// gdbg-check:$4 = {{RUST$ENUM$DISR = Variant1, __0 = 65 'A'}, {RUST$ENUM$DISR = Variant1, __0 = 65 'A'}} +// gdbr-check:$4 = generic_enum_with_different_disr_sizes::Enum::Variant1(65) + // gdb-command:print eight_bytes2 -// gdb-check:$5 = {{RUST$ENUM$DISR = Variant2, __0 = 100}, {RUST$ENUM$DISR = Variant2, __0 = 100}} +// gdbg-check:$5 = {{RUST$ENUM$DISR = Variant2, __0 = 100}, {RUST$ENUM$DISR = Variant2, __0 = 100}} +// gdbr-check:$5 = generic_enum_with_different_disr_sizes::Enum::Variant2(100) + // gdb-command:print four_bytes2 -// gdb-check:$6 = {{RUST$ENUM$DISR = Variant2, __0 = 101}, {RUST$ENUM$DISR = Variant2, __0 = 101}} +// gdbg-check:$6 = {{RUST$ENUM$DISR = Variant2, __0 = 101}, {RUST$ENUM$DISR = Variant2, __0 = 101}} +// gdbr-check:$6 = generic_enum_with_different_disr_sizes::Enum::Variant2(101) + // gdb-command:print two_bytes2 -// gdb-check:$7 = {{RUST$ENUM$DISR = Variant2, __0 = 102}, {RUST$ENUM$DISR = Variant2, __0 = 102}} +// gdbg-check:$7 = {{RUST$ENUM$DISR = Variant2, __0 = 102}, {RUST$ENUM$DISR = Variant2, __0 = 102}} +// gdbr-check:$7 = generic_enum_with_different_disr_sizes::Enum::Variant2(102) + // gdb-command:print one_byte2 -// gdb-check:$8 = {{RUST$ENUM$DISR = Variant2, __0 = 65 'A'}, {RUST$ENUM$DISR = Variant2, __0 = 65 'A'}} +// gdbg-check:$8 = {{RUST$ENUM$DISR = Variant2, __0 = 65 'A'}, {RUST$ENUM$DISR = Variant2, __0 = 65 'A'}} +// gdbr-check:$8 = generic_enum_with_different_disr_sizes::Enum::Variant2(65) // gdb-command:continue diff --git a/src/test/debuginfo/generic-function.rs b/src/test/debuginfo/generic-function.rs index 415dd36212a44..f1bfc08915edd 100644 --- a/src/test/debuginfo/generic-function.rs +++ b/src/test/debuginfo/generic-function.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-linelength + // min-lldb-version: 310 // compile-flags:-g @@ -21,7 +23,8 @@ // gdb-command:print *t1 // gdb-check:$2 = 2.5 // gdb-command:print ret -// gdb-check:$3 = {__0 = {__0 = 1, __1 = 2.5}, __1 = {__0 = 2.5, __1 = 1}} +// gdbg-check:$3 = {__0 = {__0 = 1, __1 = 2.5}, __1 = {__0 = 2.5, __1 = 1}} +// gdbr-check:$3 = ((1, 2.5), (2.5, 1)) // gdb-command:continue // gdb-command:print *t0 @@ -29,15 +32,18 @@ // gdb-command:print *t1 // gdb-check:$5 = 4 // gdb-command:print ret -// gdb-check:$6 = {__0 = {__0 = 3.5, __1 = 4}, __1 = {__0 = 4, __1 = 3.5}} +// gdbg-check:$6 = {__0 = {__0 = 3.5, __1 = 4}, __1 = {__0 = 4, __1 = 3.5}} +// gdbr-check:$6 = ((3.5, 4), (4, 3.5)) // gdb-command:continue // gdb-command:print *t0 // gdb-check:$7 = 5 // gdb-command:print *t1 -// gdb-check:$8 = {a = 6, b = 7.5} +// gdbg-check:$8 = {a = 6, b = 7.5} +// gdbr-check:$8 = generic_function::Struct {a: 6, b: 7.5} // gdb-command:print ret -// gdb-check:$9 = {__0 = {__0 = 5, __1 = {a = 6, b = 7.5}}, __1 = {__0 = {a = 6, b = 7.5}, __1 = 5}} +// gdbg-check:$9 = {__0 = {__0 = 5, __1 = {a = 6, b = 7.5}}, __1 = {__0 = {a = 6, b = 7.5}, __1 = 5}} +// gdbr-check:$9 = ((5, generic_function::Struct {a: 6, b: 7.5}), (generic_function::Struct {a: 6, b: 7.5}, 5)) // gdb-command:continue diff --git a/src/test/debuginfo/generic-method-on-generic-struct.rs b/src/test/debuginfo/generic-method-on-generic-struct.rs index 968cb2e159716..4f3f6dfc821ee 100644 --- a/src/test/debuginfo/generic-method-on-generic-struct.rs +++ b/src/test/debuginfo/generic-method-on-generic-struct.rs @@ -18,7 +18,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {x = {__0 = 8888, __1 = -8888}} +// gdbg-check:$1 = {x = {__0 = 8888, __1 = -8888}} +// gdbr-check:$1 = generic_method_on_generic_struct::Struct<(u32, i32)> {x: (8888, -8888)} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -27,7 +28,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {x = {__0 = 8888, __1 = -8888}} +// gdbg-check:$4 = {x = {__0 = 8888, __1 = -8888}} +// gdbr-check:$4 = generic_method_on_generic_struct::Struct<(u32, i32)> {x: (8888, -8888)} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -36,7 +38,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {x = 1234.5} +// gdbg-check:$7 = {x = 1234.5} +// gdbr-check:$7 = generic_method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -45,7 +48,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {x = 1234.5} +// gdbg-check:$10 = {x = 1234.5} +// gdbr-check:$10 = generic_method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -54,7 +58,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {x = 1234.5} +// gdbg-check:$13 = {x = 1234.5} +// gdbr-check:$13 = generic_method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/generic-struct-style-enum.rs b/src/test/debuginfo/generic-struct-style-enum.rs index 991404f56eff9..dba9422721a96 100644 --- a/src/test/debuginfo/generic-struct-style-enum.rs +++ b/src/test/debuginfo/generic-struct-style-enum.rs @@ -17,16 +17,20 @@ // gdb-command:run // gdb-command:print case1 -// gdb-check:$1 = {{RUST$ENUM$DISR = Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {RUST$ENUM$DISR = Case1, a = 0, b = 2088533116, c = 2088533116}, {RUST$ENUM$DISR = Case1, a = 0, b = 8970181431921507452}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {RUST$ENUM$DISR = Case1, a = 0, b = 2088533116, c = 2088533116}, {RUST$ENUM$DISR = Case1, a = 0, b = 8970181431921507452}} +// gdbr-check:$1 = generic_struct_style_enum::Regular::Case1{a: 0, b: 31868, c: 31868, d: 31868, e: 31868} // gdb-command:print case2 -// gdb-check:$2 = {{RUST$ENUM$DISR = Case2, a = 0, b = 4369, c = 4369, d = 4369, e = 4369}, {RUST$ENUM$DISR = Case2, a = 0, b = 286331153, c = 286331153}, {RUST$ENUM$DISR = Case2, a = 0, b = 1229782938247303441}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, a = 0, b = 4369, c = 4369, d = 4369, e = 4369}, {RUST$ENUM$DISR = Case2, a = 0, b = 286331153, c = 286331153}, {RUST$ENUM$DISR = Case2, a = 0, b = 1229782938247303441}} +// gdbr-check:$2 = generic_struct_style_enum::Regular::Case2{a: 0, b: 286331153, c: 286331153} // gdb-command:print case3 -// gdb-check:$3 = {{RUST$ENUM$DISR = Case3, a = 0, b = 22873, c = 22873, d = 22873, e = 22873}, {RUST$ENUM$DISR = Case3, a = 0, b = 1499027801, c = 1499027801}, {RUST$ENUM$DISR = Case3, a = 0, b = 6438275382588823897}} +// gdbg-check:$3 = {{RUST$ENUM$DISR = Case3, a = 0, b = 22873, c = 22873, d = 22873, e = 22873}, {RUST$ENUM$DISR = Case3, a = 0, b = 1499027801, c = 1499027801}, {RUST$ENUM$DISR = Case3, a = 0, b = 6438275382588823897}} +// gdbr-check:$3 = generic_struct_style_enum::Regular::Case3{a: 0, b: 6438275382588823897} // gdb-command:print univariant -// gdb-check:$4 = {{a = -1}} +// gdbg-check:$4 = {{a = -1}} +// gdbr-check:$4 = generic_struct_style_enum::Univariant::TheOnlyCase{a: -1} #![feature(omit_gdb_pretty_printer_section)] diff --git a/src/test/debuginfo/generic-struct.rs b/src/test/debuginfo/generic-struct.rs index 92a67a2344d1c..35f00ce78717b 100644 --- a/src/test/debuginfo/generic-struct.rs +++ b/src/test/debuginfo/generic-struct.rs @@ -18,13 +18,17 @@ // gdb-command:run // gdb-command:print int_int -// gdb-check:$1 = {key = 0, value = 1} +// gdbg-check:$1 = {key = 0, value = 1} +// gdbr-check:$1 = generic_struct::AGenericStruct {key: 0, value: 1} // gdb-command:print int_float -// gdb-check:$2 = {key = 2, value = 3.5} +// gdbg-check:$2 = {key = 2, value = 3.5} +// gdbr-check:$2 = generic_struct::AGenericStruct {key: 2, value: 3.5} // gdb-command:print float_int -// gdb-check:$3 = {key = 4.5, value = 5} +// gdbg-check:$3 = {key = 4.5, value = 5} +// gdbr-check:$3 = generic_struct::AGenericStruct {key: 4.5, value: 5} // gdb-command:print float_int_float -// gdb-check:$4 = {key = 6.5, value = {key = 7, value = 8.5}} +// gdbg-check:$4 = {key = 6.5, value = {key = 7, value = 8.5}} +// gdbr-check:$4 = generic_struct::AGenericStruct> {key: 6.5, value: generic_struct::AGenericStruct {key: 7, value: 8.5}} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/generic-tuple-style-enum.rs b/src/test/debuginfo/generic-tuple-style-enum.rs index e2727fbe7df4a..01d2ff4e33439 100644 --- a/src/test/debuginfo/generic-tuple-style-enum.rs +++ b/src/test/debuginfo/generic-tuple-style-enum.rs @@ -19,16 +19,20 @@ // gdb-command:run // gdb-command:print case1 -// gdb-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = 31868, __2 = 31868, __3 = 31868, __4 = 31868}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 2088533116, __2 = 2088533116}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 8970181431921507452}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = 31868, __2 = 31868, __3 = 31868, __4 = 31868}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 2088533116, __2 = 2088533116}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 8970181431921507452}} +// gdbr-check:$1 = generic_tuple_style_enum::Regular::Case1(0, 31868, 31868, 31868, 31868) // gdb-command:print case2 -// gdb-check:$2 = {{RUST$ENUM$DISR = Case2, __0 = 0, __1 = 4369, __2 = 4369, __3 = 4369, __4 = 4369}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 286331153, __2 = 286331153}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 1229782938247303441}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, __0 = 0, __1 = 4369, __2 = 4369, __3 = 4369, __4 = 4369}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 286331153, __2 = 286331153}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 1229782938247303441}} +// gdbr-check:$2 = generic_tuple_style_enum::Regular::Case2(0, 286331153, 286331153) // gdb-command:print case3 -// gdb-check:$3 = {{RUST$ENUM$DISR = Case3, __0 = 0, __1 = 22873, __2 = 22873, __3 = 22873, __4 = 22873}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 1499027801, __2 = 1499027801}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 6438275382588823897}} +// gdbg-check:$3 = {{RUST$ENUM$DISR = Case3, __0 = 0, __1 = 22873, __2 = 22873, __3 = 22873, __4 = 22873}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 1499027801, __2 = 1499027801}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 6438275382588823897}} +// gdbr-check:$3 = generic_tuple_style_enum::Regular::Case3(0, 6438275382588823897) // gdb-command:print univariant -// gdb-check:$4 = {{__0 = -1}} +// gdbg-check:$4 = {{__0 = -1}} +// gdbr-check:$4 = generic_tuple_style_enum::Univariant::TheOnlyCase(-1) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/lexical-scopes-in-block-expression.rs b/src/test/debuginfo/lexical-scopes-in-block-expression.rs index 841786f930daf..8e8a194e37841 100644 --- a/src/test/debuginfo/lexical-scopes-in-block-expression.rs +++ b/src/test/debuginfo/lexical-scopes-in-block-expression.rs @@ -16,7 +16,8 @@ // gdb-command:run -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$1 = 0 // STRUCT EXPRESSION @@ -28,7 +29,8 @@ // gdb-command:print val // gdb-check:$4 = 11 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$5 = 1 // gdb-command:print ten // gdb-check:$6 = 10 @@ -49,7 +51,8 @@ // gdb-command:print val // gdb-check:$11 = 12 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$12 = 2 // gdb-command:print ten // gdb-check:$13 = 10 @@ -70,7 +73,8 @@ // gdb-command:print val // gdb-check:$18 = 13 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$19 = 3 // gdb-command:print ten // gdb-check:$20 = 10 @@ -91,7 +95,8 @@ // gdb-command:print val // gdb-check:$25 = 14 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$26 = 4 // gdb-command:print ten // gdb-check:$27 = 10 @@ -112,7 +117,8 @@ // gdb-command:print val // gdb-check:$32 = 15 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$33 = 5 // gdb-command:print ten // gdb-check:$34 = 10 @@ -133,7 +139,8 @@ // gdb-command:print val // gdb-check:$39 = 16 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$40 = 6 // gdb-command:print ten // gdb-check:$41 = 10 @@ -155,7 +162,8 @@ // gdb-command:print val // gdb-check:$46 = 17 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$47 = 7 // gdb-command:print ten // gdb-check:$48 = 10 @@ -176,7 +184,8 @@ // gdb-command:print val // gdb-check:$53 = 18 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$54 = 8 // gdb-command:print ten // gdb-check:$55 = 10 diff --git a/src/test/debuginfo/method-on-enum.rs b/src/test/debuginfo/method-on-enum.rs index 6437b3bb900f8..7dbc0d3c5130d 100644 --- a/src/test/debuginfo/method-on-enum.rs +++ b/src/test/debuginfo/method-on-enum.rs @@ -19,7 +19,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {{RUST$ENUM$DISR = Variant2, [...]}, {RUST$ENUM$DISR = Variant2, __0 = 117901063}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = Variant2, [...]}, {RUST$ENUM$DISR = Variant2, __0 = 117901063}} +// gdbr-check:$1 = method_on_enum::Enum::Variant2(117901063) // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -28,7 +29,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {{RUST$ENUM$DISR = Variant2, [...]}, {RUST$ENUM$DISR = Variant2, __0 = 117901063}} +// gdbg-check:$4 = {{RUST$ENUM$DISR = Variant2, [...]}, {RUST$ENUM$DISR = Variant2, __0 = 117901063}} +// gdbr-check:$4 = method_on_enum::Enum::Variant2(117901063) // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -37,7 +39,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {{RUST$ENUM$DISR = Variant1, x = 1799, y = 1799}, {RUST$ENUM$DISR = Variant1, [...]}} +// gdbg-check:$7 = {{RUST$ENUM$DISR = Variant1, x = 1799, y = 1799}, {RUST$ENUM$DISR = Variant1, [...]}} +// gdbr-check:$7 = method_on_enum::Enum::Variant1{x: 1799, y: 1799} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -46,7 +49,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {{RUST$ENUM$DISR = Variant1, x = 1799, y = 1799}, {RUST$ENUM$DISR = Variant1, [...]}} +// gdbg-check:$10 = {{RUST$ENUM$DISR = Variant1, x = 1799, y = 1799}, {RUST$ENUM$DISR = Variant1, [...]}} +// gdbr-check:$10 = method_on_enum::Enum::Variant1{x: 1799, y: 1799} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -55,7 +59,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {{RUST$ENUM$DISR = Variant1, x = 1799, y = 1799}, {RUST$ENUM$DISR = Variant1, [...]}} +// gdbg-check:$13 = {{RUST$ENUM$DISR = Variant1, x = 1799, y = 1799}, {RUST$ENUM$DISR = Variant1, [...]}} +// gdbr-check:$13 = method_on_enum::Enum::Variant1{x: 1799, y: 1799} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/method-on-generic-struct.rs b/src/test/debuginfo/method-on-generic-struct.rs index 5b697f859d4ed..20d419b4ac088 100644 --- a/src/test/debuginfo/method-on-generic-struct.rs +++ b/src/test/debuginfo/method-on-generic-struct.rs @@ -18,7 +18,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {x = {__0 = 8888, __1 = -8888}} +// gdbg-check:$1 = {x = {__0 = 8888, __1 = -8888}} +// gdbr-check:$1 = method_on_generic_struct::Struct<(u32, i32)> {x: (8888, -8888)} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -27,7 +28,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {x = {__0 = 8888, __1 = -8888}} +// gdbg-check:$4 = {x = {__0 = 8888, __1 = -8888}} +// gdbr-check:$4 = method_on_generic_struct::Struct<(u32, i32)> {x: (8888, -8888)} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -36,7 +38,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {x = 1234.5} +// gdbg-check:$7 = {x = 1234.5} +// gdbr-check:$7 = method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -45,7 +48,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {x = 1234.5} +// gdbg-check:$10 = {x = 1234.5} +// gdbr-check:$10 = method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -54,7 +58,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {x = 1234.5} +// gdbg-check:$13 = {x = 1234.5} +// gdbr-check:$13 = method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/method-on-struct.rs b/src/test/debuginfo/method-on-struct.rs index 3bf2e775e7791..c7546fe2221ff 100644 --- a/src/test/debuginfo/method-on-struct.rs +++ b/src/test/debuginfo/method-on-struct.rs @@ -18,7 +18,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {x = 100} +// gdbg-check:$1 = {x = 100} +// gdbr-check:$1 = method_on_struct::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -27,7 +28,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {x = 100} +// gdbg-check:$4 = {x = 100} +// gdbr-check:$4 = method_on_struct::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -36,7 +38,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {x = 200} +// gdbg-check:$7 = {x = 200} +// gdbr-check:$7 = method_on_struct::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -45,7 +48,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {x = 200} +// gdbg-check:$10 = {x = 200} +// gdbr-check:$10 = method_on_struct::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -54,7 +58,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {x = 200} +// gdbg-check:$13 = {x = 200} +// gdbr-check:$13 = method_on_struct::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/method-on-trait.rs b/src/test/debuginfo/method-on-trait.rs index 5ce4a7905a1d0..1dc37bb06ac40 100644 --- a/src/test/debuginfo/method-on-trait.rs +++ b/src/test/debuginfo/method-on-trait.rs @@ -18,7 +18,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {x = 100} +// gdbg-check:$1 = {x = 100} +// gdbr-check:$1 = method_on_trait::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -27,7 +28,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {x = 100} +// gdbg-check:$4 = {x = 100} +// gdbr-check:$4 = method_on_trait::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -36,7 +38,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {x = 200} +// gdbg-check:$7 = {x = 200} +// gdbr-check:$7 = method_on_trait::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -45,7 +48,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {x = 200} +// gdbg-check:$10 = {x = 200} +// gdbr-check:$10 = method_on_trait::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -54,7 +58,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {x = 200} +// gdbg-check:$13 = {x = 200} +// gdbr-check:$13 = method_on_trait::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/method-on-tuple-struct.rs b/src/test/debuginfo/method-on-tuple-struct.rs index d8644a3934f10..dac762ae0c35b 100644 --- a/src/test/debuginfo/method-on-tuple-struct.rs +++ b/src/test/debuginfo/method-on-tuple-struct.rs @@ -18,7 +18,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {__0 = 100, __1 = -100.5} +// gdbg-check:$1 = {__0 = 100, __1 = -100.5} +// gdbr-check:$1 = method_on_tuple_struct::TupleStruct (100, -100.5) // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -27,7 +28,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {__0 = 100, __1 = -100.5} +// gdbg-check:$4 = {__0 = 100, __1 = -100.5} +// gdbr-check:$4 = method_on_tuple_struct::TupleStruct (100, -100.5) // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -36,7 +38,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {__0 = 200, __1 = -200.5} +// gdbg-check:$7 = {__0 = 200, __1 = -200.5} +// gdbr-check:$7 = method_on_tuple_struct::TupleStruct (200, -200.5) // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -45,7 +48,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {__0 = 200, __1 = -200.5} +// gdbg-check:$10 = {__0 = 200, __1 = -200.5} +// gdbr-check:$10 = method_on_tuple_struct::TupleStruct (200, -200.5) // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -54,7 +58,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {__0 = 200, __1 = -200.5} +// gdbg-check:$13 = {__0 = 200, __1 = -200.5} +// gdbr-check:$13 = method_on_tuple_struct::TupleStruct (200, -200.5) // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/nil-enum.rs b/src/test/debuginfo/nil-enum.rs index 81399ec590b14..94377421c0b0c 100644 --- a/src/test/debuginfo/nil-enum.rs +++ b/src/test/debuginfo/nil-enum.rs @@ -16,10 +16,12 @@ // gdb-command:run // gdb-command:print first -// gdb-check:$1 = {} +// gdbg-check:$1 = {} +// gdbr-check:$1 = // gdb-command:print second -// gdb-check:$2 = {} +// gdbg-check:$2 = {} +// gdbr-check:$2 = #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] @@ -28,8 +30,9 @@ enum ANilEnum {} enum AnotherNilEnum {} -// This test relies on gdb printing the string "{}" for empty +// This test relies on gdbg printing the string "{}" for empty // structs (which may change some time) +// The error from gdbr is expected since nil enums are not supposed to exist. fn main() { unsafe { let first: ANilEnum = ::std::mem::zeroed(); diff --git a/src/test/debuginfo/option-like-enum.rs b/src/test/debuginfo/option-like-enum.rs index f103294a94a07..39e6a4e4facf9 100644 --- a/src/test/debuginfo/option-like-enum.rs +++ b/src/test/debuginfo/option-like-enum.rs @@ -18,28 +18,36 @@ // gdb-command:run // gdb-command:print some -// gdb-check:$1 = {RUST$ENCODED$ENUM$0$None = {__0 = 0x12345678}} +// gdbg-check:$1 = {RUST$ENCODED$ENUM$0$None = {__0 = 0x12345678}} +// gdbr-check:$1 = core::option::Option<&u32>::Some(0x12345678) // gdb-command:print none -// gdb-check:$2 = {RUST$ENCODED$ENUM$0$None = {__0 = 0x0}} +// gdbg-check:$2 = {RUST$ENCODED$ENUM$0$None = {__0 = 0x0}} +// gdbr-check:$2 = core::option::Option<&u32>::None // gdb-command:print full -// gdb-check:$3 = {RUST$ENCODED$ENUM$1$Empty = {__0 = 454545, __1 = 0x87654321, __2 = 9988}} +// gdbg-check:$3 = {RUST$ENCODED$ENUM$1$Empty = {__0 = 454545, __1 = 0x87654321, __2 = 9988}} +// gdbr-check:$3 = option_like_enum::MoreFields::Full(454545, 0x87654321, 9988) -// gdb-command:print empty_gdb->discr +// gdbg-command:print empty_gdb->discr +// gdbr-command:print empty_gdb.discr // gdb-check:$4 = (isize *) 0x0 // gdb-command:print droid -// gdb-check:$5 = {RUST$ENCODED$ENUM$2$Void = {id = 675675, range = 10000001, internals = 0x43218765}} +// gdbg-check:$5 = {RUST$ENCODED$ENUM$2$Void = {id = 675675, range = 10000001, internals = 0x43218765}} +// gdbr-check:$5 = option_like_enum::NamedFields::Droid{id: 675675, range: 10000001, internals: 0x43218765} -// gdb-command:print void_droid_gdb->internals +// gdbg-command:print void_droid_gdb->internals +// gdbr-command:print void_droid_gdb.internals // gdb-check:$6 = (isize *) 0x0 // gdb-command:print nested_non_zero_yep -// gdb-check:$7 = {RUST$ENCODED$ENUM$1$2$Nope = {__0 = 10.5, __1 = {a = 10, b = 20, c = [...]}}} +// gdbg-check:$7 = {RUST$ENCODED$ENUM$1$2$Nope = {__0 = 10.5, __1 = {a = 10, b = 20, c = [...]}}} +// gdbr-check:$7 = option_like_enum::NestedNonZero::Yep(10.5, option_like_enum::NestedNonZeroField {a: 10, b: 20, c: 0x[...] "x[...]"}) // gdb-command:print nested_non_zero_nope -// gdb-check:$8 = {RUST$ENCODED$ENUM$1$2$Nope = {__0 = [...], __1 = {a = [...], b = [...], c = 0x0}}} +// gdbg-check:$8 = {RUST$ENCODED$ENUM$1$2$Nope = {__0 = [...], __1 = {a = [...], b = [...], c = 0x0}}} +// gdbr-check:$8 = option_like_enum::NestedNonZero::Nope // gdb-command:continue diff --git a/src/test/debuginfo/packed-struct-with-destructor.rs b/src/test/debuginfo/packed-struct-with-destructor.rs index 9d37cb3012b7d..50bd857d46076 100644 --- a/src/test/debuginfo/packed-struct-with-destructor.rs +++ b/src/test/debuginfo/packed-struct-with-destructor.rs @@ -18,29 +18,37 @@ // gdb-command:run // gdb-command:print packed -// gdb-check:$1 = {x = 123, y = 234, z = 345} +// gdbg-check:$1 = {x = 123, y = 234, z = 345} +// gdbr-check:$1 = packed_struct_with_destructor::Packed {x: 123, y: 234, z: 345} // gdb-command:print packedInPacked -// gdb-check:$2 = {a = 1111, b = {x = 2222, y = 3333, z = 4444}, c = 5555, d = {x = 6666, y = 7777, z = 8888}} +// gdbg-check:$2 = {a = 1111, b = {x = 2222, y = 3333, z = 4444}, c = 5555, d = {x = 6666, y = 7777, z = 8888}} +// gdbr-check:$2 = packed_struct_with_destructor::PackedInPacked {a: 1111, b: packed_struct_with_destructor::Packed {x: 2222, y: 3333, z: 4444}, c: 5555, d: packed_struct_with_destructor::Packed {x: 6666, y: 7777, z: 8888}} // gdb-command:print packedInUnpacked -// gdb-check:$3 = {a = -1111, b = {x = -2222, y = -3333, z = -4444}, c = -5555, d = {x = -6666, y = -7777, z = -8888}} +// gdbg-check:$3 = {a = -1111, b = {x = -2222, y = -3333, z = -4444}, c = -5555, d = {x = -6666, y = -7777, z = -8888}} +// gdbr-check:$3 = packed_struct_with_destructor::PackedInUnpacked {a: -1111, b: packed_struct_with_destructor::Packed {x: -2222, y: -3333, z: -4444}, c: -5555, d: packed_struct_with_destructor::Packed {x: -6666, y: -7777, z: -8888}} // gdb-command:print unpackedInPacked -// gdb-check:$4 = {a = 987, b = {x = 876, y = 765, z = 654}, c = {x = 543, y = 432, z = 321}, d = 210} +// gdbg-check:$4 = {a = 987, b = {x = 876, y = 765, z = 654}, c = {x = 543, y = 432, z = 321}, d = 210} +// gdbr-check:$4 = packed_struct_with_destructor::UnpackedInPacked {a: 987, b: packed_struct_with_destructor::Unpacked {x: 876, y: 765, z: 654}, c: packed_struct_with_destructor::Unpacked {x: 543, y: 432, z: 321}, d: 210} // gdb-command:print packedInPackedWithDrop -// gdb-check:$5 = {a = 11, b = {x = 22, y = 33, z = 44}, c = 55, d = {x = 66, y = 77, z = 88}} +// gdbg-check:$5 = {a = 11, b = {x = 22, y = 33, z = 44}, c = 55, d = {x = 66, y = 77, z = 88}} +// gdbr-check:$5 = packed_struct_with_destructor::PackedInPackedWithDrop {a: 11, b: packed_struct_with_destructor::Packed {x: 22, y: 33, z: 44}, c: 55, d: packed_struct_with_destructor::Packed {x: 66, y: 77, z: 88}} // gdb-command:print packedInUnpackedWithDrop -// gdb-check:$6 = {a = -11, b = {x = -22, y = -33, z = -44}, c = -55, d = {x = -66, y = -77, z = -88}} +// gdbg-check:$6 = {a = -11, b = {x = -22, y = -33, z = -44}, c = -55, d = {x = -66, y = -77, z = -88}} +// gdbr-check:$6 = packed_struct_with_destructor::PackedInUnpackedWithDrop {a: -11, b: packed_struct_with_destructor::Packed {x: -22, y: -33, z: -44}, c: -55, d: packed_struct_with_destructor::Packed {x: -66, y: -77, z: -88}} // gdb-command:print unpackedInPackedWithDrop -// gdb-check:$7 = {a = 98, b = {x = 87, y = 76, z = 65}, c = {x = 54, y = 43, z = 32}, d = 21} +// gdbg-check:$7 = {a = 98, b = {x = 87, y = 76, z = 65}, c = {x = 54, y = 43, z = 32}, d = 21} +// gdbr-check:$7 = packed_struct_with_destructor::UnpackedInPackedWithDrop {a: 98, b: packed_struct_with_destructor::Unpacked {x: 87, y: 76, z: 65}, c: packed_struct_with_destructor::Unpacked {x: 54, y: 43, z: 32}, d: 21} // gdb-command:print deeplyNested -// gdb-check:$8 = {a = {a = 1, b = {x = 2, y = 3, z = 4}, c = 5, d = {x = 6, y = 7, z = 8}}, b = {a = 9, b = {x = 10, y = 11, z = 12}, c = {x = 13, y = 14, z = 15}, d = 16}, c = {a = 17, b = {x = 18, y = 19, z = 20}, c = 21, d = {x = 22, y = 23, z = 24}}, d = {a = 25, b = {x = 26, y = 27, z = 28}, c = 29, d = {x = 30, y = 31, z = 32}}, e = {a = 33, b = {x = 34, y = 35, z = 36}, c = {x = 37, y = 38, z = 39}, d = 40}, f = {a = 41, b = {x = 42, y = 43, z = 44}, c = 45, d = {x = 46, y = 47, z = 48}}} +// gdbg-check:$8 = {a = {a = 1, b = {x = 2, y = 3, z = 4}, c = 5, d = {x = 6, y = 7, z = 8}}, b = {a = 9, b = {x = 10, y = 11, z = 12}, c = {x = 13, y = 14, z = 15}, d = 16}, c = {a = 17, b = {x = 18, y = 19, z = 20}, c = 21, d = {x = 22, y = 23, z = 24}}, d = {a = 25, b = {x = 26, y = 27, z = 28}, c = 29, d = {x = 30, y = 31, z = 32}}, e = {a = 33, b = {x = 34, y = 35, z = 36}, c = {x = 37, y = 38, z = 39}, d = 40}, f = {a = 41, b = {x = 42, y = 43, z = 44}, c = 45, d = {x = 46, y = 47, z = 48}}} +// gdbr-check:$8 = packed_struct_with_destructor::DeeplyNested {a: packed_struct_with_destructor::PackedInPacked {a: 1, b: packed_struct_with_destructor::Packed {x: 2, y: 3, z: 4}, c: 5, d: packed_struct_with_destructor::Packed {x: 6, y: 7, z: 8}}, b: packed_struct_with_destructor::UnpackedInPackedWithDrop {a: 9, b: packed_struct_with_destructor::Unpacked {x: 10, y: 11, z: 12}, c: packed_struct_with_destructor::Unpacked {x: 13, y: 14, z: 15}, d: 16}, c: packed_struct_with_destructor::PackedInUnpacked {a: 17, b: packed_struct_with_destructor::Packed {x: 18, y: 19, z: 20}, c: 21, d: packed_struct_with_destructor::Packed {x: 22, y: 23, z: 24}}, d: packed_struct_with_destructor::PackedInUnpackedWithDrop {a: 25, b: packed_struct_with_destructor::Packed {x: 26, y: 27, z: 28}, c: 29, d: packed_struct_with_destructor::Packed {x: 30, y: 31, z: 32}}, e: packed_struct_with_destructor::UnpackedInPacked {a: 33, b: packed_struct_with_destructor::Unpacked {x: 34, y: 35, z: 36}, c: packed_struct_with_destructor::Unpacked {x: 37, y: 38, z: 39}, d: 40}, f: packed_struct_with_destructor::PackedInPackedWithDrop {a: 41, b: packed_struct_with_destructor::Packed {x: 42, y: 43, z: 44}, c: 45, d: packed_struct_with_destructor::Packed {x: 46, y: 47, z: 48}}} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/packed-struct.rs b/src/test/debuginfo/packed-struct.rs index e86e963f38cdd..b84161c36a557 100644 --- a/src/test/debuginfo/packed-struct.rs +++ b/src/test/debuginfo/packed-struct.rs @@ -18,16 +18,20 @@ // gdb-command:run // gdb-command:print packed -// gdb-check:$1 = {x = 123, y = 234, z = 345} +// gdbg-check:$1 = {x = 123, y = 234, z = 345} +// gdbr-check:$1 = packed_struct::Packed {x: 123, y: 234, z: 345} // gdb-command:print packedInPacked -// gdb-check:$2 = {a = 1111, b = {x = 2222, y = 3333, z = 4444}, c = 5555, d = {x = 6666, y = 7777, z = 8888}} +// gdbg-check:$2 = {a = 1111, b = {x = 2222, y = 3333, z = 4444}, c = 5555, d = {x = 6666, y = 7777, z = 8888}} +// gdbr-check:$2 = packed_struct::PackedInPacked {a: 1111, b: packed_struct::Packed {x: 2222, y: 3333, z: 4444}, c: 5555, d: packed_struct::Packed {x: 6666, y: 7777, z: 8888}} // gdb-command:print packedInUnpacked -// gdb-check:$3 = {a = -1111, b = {x = -2222, y = -3333, z = -4444}, c = -5555, d = {x = -6666, y = -7777, z = -8888}} +// gdbg-check:$3 = {a = -1111, b = {x = -2222, y = -3333, z = -4444}, c = -5555, d = {x = -6666, y = -7777, z = -8888}} +// gdbr-check:$3 = packed_struct::PackedInUnpacked {a: -1111, b: packed_struct::Packed {x: -2222, y: -3333, z: -4444}, c: -5555, d: packed_struct::Packed {x: -6666, y: -7777, z: -8888}} // gdb-command:print unpackedInPacked -// gdb-check:$4 = {a = 987, b = {x = 876, y = 765, z = 654, w = 543}, c = {x = 432, y = 321, z = 210, w = 109}, d = -98} +// gdbg-check:$4 = {a = 987, b = {x = 876, y = 765, z = 654, w = 543}, c = {x = 432, y = 321, z = 210, w = 109}, d = -98} +// gdbr-check:$4 = packed_struct::UnpackedInPacked {a: 987, b: packed_struct::Unpacked {x: 876, y: 765, z: 654, w: 543}, c: packed_struct::Unpacked {x: 432, y: 321, z: 210, w: 109}, d: -98} // gdb-command:print sizeof(packed) // gdb-check:$5 = 14 diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs index 576621737e6b6..153f0c8271fc4 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -35,7 +35,8 @@ // gdb-check:$5 = Some = {8} // gdb-command: print none -// gdb-check:$6 = None +// gdbg-check:$6 = None +// gdbr-check:$6 = core::option::Option::None // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/recursive-struct.rs b/src/test/debuginfo/recursive-struct.rs index ea067d5bffbec..80147b14174da 100644 --- a/src/test/debuginfo/recursive-struct.rs +++ b/src/test/debuginfo/recursive-struct.rs @@ -12,57 +12,72 @@ // ignore-lldb // compile-flags:-g + // gdb-command:run // gdb-command:print stack_unique.value // gdb-check:$1 = 0 -// gdb-command:print stack_unique.next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbg-command:print stack_unique.next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbr-command:print stack_unique.next.val.value // gdb-check:$2 = 1 -// gdb-command:print unique_unique->value +// gdbg-command:print unique_unique->value +// gdbr-command:print unique_unique.value // gdb-check:$3 = 2 -// gdb-command:print unique_unique->next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbg-command:print unique_unique->next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbr-command:print unique_unique.next.val.value // gdb-check:$4 = 3 // gdb-command:print vec_unique[0].value // gdb-check:$5 = 6.5 -// gdb-command:print vec_unique[0].next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbg-command:print vec_unique[0].next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbr-command:print vec_unique[0].next.val.value // gdb-check:$6 = 7.5 -// gdb-command:print borrowed_unique->value +// gdbg-command:print borrowed_unique->value +// gdbr-command:print borrowed_unique.value // gdb-check:$7 = 8.5 -// gdb-command:print borrowed_unique->next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbg-command:print borrowed_unique->next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbr-command:print borrowed_unique.next.val.value // gdb-check:$8 = 9.5 // LONG CYCLE // gdb-command:print long_cycle1.value // gdb-check:$9 = 20 -// gdb-command:print long_cycle1.next->value +// gdbg-command:print long_cycle1.next->value +// gdbr-command:print long_cycle1.next.value // gdb-check:$10 = 21 -// gdb-command:print long_cycle1.next->next->value +// gdbg-command:print long_cycle1.next->next->value +// gdbr-command:print long_cycle1.next.next.value // gdb-check:$11 = 22 -// gdb-command:print long_cycle1.next->next->next->value +// gdbg-command:print long_cycle1.next->next->next->value +// gdbr-command:print long_cycle1.next.next.next.value // gdb-check:$12 = 23 // gdb-command:print long_cycle2.value // gdb-check:$13 = 24 -// gdb-command:print long_cycle2.next->value +// gdbg-command:print long_cycle2.next->value +// gdbr-command:print long_cycle2.next.value // gdb-check:$14 = 25 -// gdb-command:print long_cycle2.next->next->value +// gdbg-command:print long_cycle2.next->next->value +// gdbr-command:print long_cycle2.next.next.value // gdb-check:$15 = 26 // gdb-command:print long_cycle3.value // gdb-check:$16 = 27 -// gdb-command:print long_cycle3.next->value +// gdbg-command:print long_cycle3.next->value +// gdbr-command:print long_cycle3.next.value // gdb-check:$17 = 28 // gdb-command:print long_cycle4.value // gdb-check:$18 = 29.5 -// gdb-command:print (*****long_cycle_w_anonymous_types).value +// gdbg-command:print (*****long_cycle_w_anonymous_types).value +// gdbr-command:print long_cycle_w_anonymous_types.value // gdb-check:$19 = 30 -// gdb-command:print (*****((*****long_cycle_w_anonymous_types).next.RUST$ENCODED$ENUM$0$Empty.val)).value +// gdbg-command:print (*****((*****long_cycle_w_anonymous_types).next.RUST$ENCODED$ENUM$0$Empty.val)).value +// gdbr-command:print long_cycle_w_anonymous_types.next.val.value // gdb-check:$20 = 31 // gdb-command:continue diff --git a/src/test/debuginfo/self-in-default-method.rs b/src/test/debuginfo/self-in-default-method.rs index 6d3f93c5d5014..796d122cd66ba 100644 --- a/src/test/debuginfo/self-in-default-method.rs +++ b/src/test/debuginfo/self-in-default-method.rs @@ -18,7 +18,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {x = 100} +// gdbg-check:$1 = {x = 100} +// gdbr-check:$1 = self_in_default_method::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -27,7 +28,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {x = 100} +// gdbg-check:$4 = {x = 100} +// gdbr-check:$4 = self_in_default_method::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -36,7 +38,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {x = 200} +// gdbg-check:$7 = {x = 200} +// gdbr-check:$7 = self_in_default_method::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -45,7 +48,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {x = 200} +// gdbg-check:$10 = {x = 200} +// gdbr-check:$10 = self_in_default_method::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -54,7 +58,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {x = 200} +// gdbg-check:$13 = {x = 200} +// gdbr-check:$13 = self_in_default_method::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/self-in-generic-default-method.rs b/src/test/debuginfo/self-in-generic-default-method.rs index aea3bae4bfc1b..b07d7ca5fb7b7 100644 --- a/src/test/debuginfo/self-in-generic-default-method.rs +++ b/src/test/debuginfo/self-in-generic-default-method.rs @@ -18,7 +18,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {x = 987} +// gdbg-check:$1 = {x = 987} +// gdbr-check:$1 = self_in_generic_default_method::Struct {x: 987} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -27,7 +28,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {x = 987} +// gdbg-check:$4 = {x = 987} +// gdbr-check:$4 = self_in_generic_default_method::Struct {x: 987} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -36,7 +38,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {x = 879} +// gdbg-check:$7 = {x = 879} +// gdbr-check:$7 = self_in_generic_default_method::Struct {x: 879} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -45,7 +48,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {x = 879} +// gdbg-check:$10 = {x = 879} +// gdbr-check:$10 = self_in_generic_default_method::Struct {x: 879} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -54,7 +58,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {x = 879} +// gdbg-check:$13 = {x = 879} +// gdbr-check:$13 = self_in_generic_default_method::Struct {x: 879} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/simd.rs b/src/test/debuginfo/simd.rs index 80ac901b60fd3..75e68f7efedef 100644 --- a/src/test/debuginfo/simd.rs +++ b/src/test/debuginfo/simd.rs @@ -20,28 +20,46 @@ // compile-flags:-g // gdb-command:run -// gdb-command:print/d vi8x16 -// gdb-check:$1 = {__0 = 0, __1 = 1, __2 = 2, __3 = 3, __4 = 4, __5 = 5, __6 = 6, __7 = 7, __8 = 8, __9 = 9, __10 = 10, __11 = 11, __12 = 12, __13 = 13, __14 = 14, __15 = 15} -// gdb-command:print/d vi16x8 -// gdb-check:$2 = {__0 = 16, __1 = 17, __2 = 18, __3 = 19, __4 = 20, __5 = 21, __6 = 22, __7 = 23} -// gdb-command:print/d vi32x4 -// gdb-check:$3 = {__0 = 24, __1 = 25, __2 = 26, __3 = 27} -// gdb-command:print/d vi64x2 -// gdb-check:$4 = {__0 = 28, __1 = 29} - -// gdb-command:print/d vu8x16 -// gdb-check:$5 = {__0 = 30, __1 = 31, __2 = 32, __3 = 33, __4 = 34, __5 = 35, __6 = 36, __7 = 37, __8 = 38, __9 = 39, __10 = 40, __11 = 41, __12 = 42, __13 = 43, __14 = 44, __15 = 45} -// gdb-command:print/d vu16x8 -// gdb-check:$6 = {__0 = 46, __1 = 47, __2 = 48, __3 = 49, __4 = 50, __5 = 51, __6 = 52, __7 = 53} -// gdb-command:print/d vu32x4 -// gdb-check:$7 = {__0 = 54, __1 = 55, __2 = 56, __3 = 57} -// gdb-command:print/d vu64x2 -// gdb-check:$8 = {__0 = 58, __1 = 59} +// gdbg-command:print/d vi8x16 +// gdbr-command:print vi8x16 +// gdbg-check:$1 = {__0 = 0, __1 = 1, __2 = 2, __3 = 3, __4 = 4, __5 = 5, __6 = 6, __7 = 7, __8 = 8, __9 = 9, __10 = 10, __11 = 11, __12 = 12, __13 = 13, __14 = 14, __15 = 15} +// gdbr-check:$1 = simd::i8x16 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) +// gdbg-command:print/d vi16x8 +// gdbr-command:print vi16x8 +// gdbg-check:$2 = {__0 = 16, __1 = 17, __2 = 18, __3 = 19, __4 = 20, __5 = 21, __6 = 22, __7 = 23} +// gdbr-check:$2 = simd::i16x8 (16, 17, 18, 19, 20, 21, 22, 23) +// gdbg-command:print/d vi32x4 +// gdbr-command:print vi32x4 +// gdbg-check:$3 = {__0 = 24, __1 = 25, __2 = 26, __3 = 27} +// gdbr-check:$3 = simd::i32x4 (24, 25, 26, 27) +// gdbg-command:print/d vi64x2 +// gdbr-command:print vi64x2 +// gdbg-check:$4 = {__0 = 28, __1 = 29} +// gdbr-check:$4 = simd::i64x2 (28, 29) + +// gdbg-command:print/d vu8x16 +// gdbr-command:print vu8x16 +// gdbg-check:$5 = {__0 = 30, __1 = 31, __2 = 32, __3 = 33, __4 = 34, __5 = 35, __6 = 36, __7 = 37, __8 = 38, __9 = 39, __10 = 40, __11 = 41, __12 = 42, __13 = 43, __14 = 44, __15 = 45} +// gdbr-check:$5 = simd::u8x16 (30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45) +// gdbg-command:print/d vu16x8 +// gdbr-command:print vu16x8 +// gdbg-check:$6 = {__0 = 46, __1 = 47, __2 = 48, __3 = 49, __4 = 50, __5 = 51, __6 = 52, __7 = 53} +// gdbr-check:$6 = simd::u16x8 (46, 47, 48, 49, 50, 51, 52, 53) +// gdbg-command:print/d vu32x4 +// gdbr-command:print vu32x4 +// gdbg-check:$7 = {__0 = 54, __1 = 55, __2 = 56, __3 = 57} +// gdbr-check:$7 = simd::u32x4 (54, 55, 56, 57) +// gdbg-command:print/d vu64x2 +// gdbr-command:print vu64x2 +// gdbg-check:$8 = {__0 = 58, __1 = 59} +// gdbr-check:$8 = simd::u64x2 (58, 59) // gdb-command:print vf32x4 -// gdb-check:$9 = {__0 = 60.5, __1 = 61.5, __2 = 62.5, __3 = 63.5} +// gdbg-check:$9 = {__0 = 60.5, __1 = 61.5, __2 = 62.5, __3 = 63.5} +// gdbr-check:$9 = simd::f32x4 (60.5, 61.5, 62.5, 63.5) // gdb-command:print vf64x2 -// gdb-check:$10 = {__0 = 64.5, __1 = 65.5} +// gdbg-check:$10 = {__0 = 64.5, __1 = 65.5} +// gdbr-check:$10 = simd::f64x2 (64.5, 65.5) // gdb-command:continue diff --git a/src/test/debuginfo/simple-struct.rs b/src/test/debuginfo/simple-struct.rs index d25cd4d7c047f..4956313ad2214 100644 --- a/src/test/debuginfo/simple-struct.rs +++ b/src/test/debuginfo/simple-struct.rs @@ -14,61 +14,94 @@ // === GDB TESTS =================================================================================== -// gdb-command:print 'simple_struct::NO_PADDING_16' -// gdb-check:$1 = {x = 1000, y = -1001} - -// gdb-command:print 'simple_struct::NO_PADDING_32' -// gdb-check:$2 = {x = 1, y = 2, z = 3} - -// gdb-command:print 'simple_struct::NO_PADDING_64' -// gdb-check:$3 = {x = 4, y = 5, z = 6} - -// gdb-command:print 'simple_struct::NO_PADDING_163264' -// gdb-check:$4 = {a = 7, b = 8, c = 9, d = 10} - -// gdb-command:print 'simple_struct::INTERNAL_PADDING' -// gdb-check:$5 = {x = 11, y = 12} - -// gdb-command:print 'simple_struct::PADDING_AT_END' -// gdb-check:$6 = {x = 13, y = 14} +// there's no frame yet for gdb to reliably detect the language, set it explicitly +// gdbr-command:set language rust + +// gdbg-command:print 'simple_struct::NO_PADDING_16' +// gdbr-command:print simple_struct::NO_PADDING_16 +// gdbg-check:$1 = {x = 1000, y = -1001} +// gdbr-check:$1 = simple_struct::NoPadding16 {x: 1000, y: -1001} + +// gdbg-command:print 'simple_struct::NO_PADDING_32' +// gdbr-command:print simple_struct::NO_PADDING_32 +// gdbg-check:$2 = {x = 1, y = 2, z = 3} +// gdbr-check:$2 = simple_struct::NoPadding32 {x: 1, y: 2, z: 3} + +// gdbg-command:print 'simple_struct::NO_PADDING_64' +// gdbr-command:print simple_struct::NO_PADDING_64 +// gdbg-check:$3 = {x = 4, y = 5, z = 6} +// gdbr-check:$3 = simple_struct::NoPadding64 {x: 4, y: 5, z: 6} + +// gdbg-command:print 'simple_struct::NO_PADDING_163264' +// gdbr-command:print simple_struct::NO_PADDING_163264 +// gdbg-check:$4 = {a = 7, b = 8, c = 9, d = 10} +// gdbr-check:$4 = simple_struct::NoPadding163264 {a: 7, b: 8, c: 9, d: 10} + +// gdbg-command:print 'simple_struct::INTERNAL_PADDING' +// gdbr-command:print simple_struct::INTERNAL_PADDING +// gdbg-check:$5 = {x = 11, y = 12} +// gdbr-check:$5 = simple_struct::InternalPadding {x: 11, y: 12} + +// gdbg-command:print 'simple_struct::PADDING_AT_END' +// gdbr-command:print simple_struct::PADDING_AT_END +// gdbg-check:$6 = {x = 13, y = 14} +// gdbr-check:$6 = simple_struct::PaddingAtEnd {x: 13, y: 14} // gdb-command:run // gdb-command:print no_padding16 -// gdb-check:$7 = {x = 10000, y = -10001} +// gdbg-check:$7 = {x = 10000, y = -10001} +// gdbr-check:$7 = simple_struct::NoPadding16 {x: 10000, y: -10001} // gdb-command:print no_padding32 -// gdb-check:$8 = {x = -10002, y = -10003.5, z = 10004} +// gdbg-check:$8 = {x = -10002, y = -10003.5, z = 10004} +// gdbr-check:$8 = simple_struct::NoPadding32 {x: -10002, y: -10003.5, z: 10004} // gdb-command:print no_padding64 -// gdb-check:$9 = {x = -10005.5, y = 10006, z = 10007} +// gdbg-check:$9 = {x = -10005.5, y = 10006, z = 10007} +// gdbr-check:$9 = simple_struct::NoPadding64 {x: -10005.5, y: 10006, z: 10007} // gdb-command:print no_padding163264 -// gdb-check:$10 = {a = -10008, b = 10009, c = 10010, d = 10011} +// gdbg-check:$10 = {a = -10008, b = 10009, c = 10010, d = 10011} +// gdbr-check:$10 = simple_struct::NoPadding163264 {a: -10008, b: 10009, c: 10010, d: 10011} // gdb-command:print internal_padding -// gdb-check:$11 = {x = 10012, y = -10013} +// gdbg-check:$11 = {x = 10012, y = -10013} +// gdbr-check:$11 = simple_struct::InternalPadding {x: 10012, y: -10013} // gdb-command:print padding_at_end -// gdb-check:$12 = {x = -10014, y = 10015} - -// gdb-command:print 'simple_struct::NO_PADDING_16' -// gdb-check:$13 = {x = 100, y = -101} - -// gdb-command:print 'simple_struct::NO_PADDING_32' -// gdb-check:$14 = {x = -15, y = -16, z = 17} - -// gdb-command:print 'simple_struct::NO_PADDING_64' -// gdb-check:$15 = {x = -18, y = 19, z = 20} - -// gdb-command:print 'simple_struct::NO_PADDING_163264' -// gdb-check:$16 = {a = -21, b = 22, c = 23, d = 24} - -// gdb-command:print 'simple_struct::INTERNAL_PADDING' -// gdb-check:$17 = {x = 25, y = -26} - -// gdb-command:print 'simple_struct::PADDING_AT_END' -// gdb-check:$18 = {x = -27, y = 28} +// gdbg-check:$12 = {x = -10014, y = 10015} +// gdbr-check:$12 = simple_struct::PaddingAtEnd {x: -10014, y: 10015} + +// gdbg-command:print 'simple_struct::NO_PADDING_16' +// gdbr-command:print simple_struct::NO_PADDING_16 +// gdbg-check:$13 = {x = 100, y = -101} +// gdbr-check:$13 = simple_struct::NoPadding16 {x: 100, y: -101} + +// gdbg-command:print 'simple_struct::NO_PADDING_32' +// gdbr-command:print simple_struct::NO_PADDING_32 +// gdbg-check:$14 = {x = -15, y = -16, z = 17} +// gdbr-check:$14 = simple_struct::NoPadding32 {x: -15, y: -16, z: 17} + +// gdbg-command:print 'simple_struct::NO_PADDING_64' +// gdbr-command:print simple_struct::NO_PADDING_64 +// gdbg-check:$15 = {x = -18, y = 19, z = 20} +// gdbr-check:$15 = simple_struct::NoPadding64 {x: -18, y: 19, z: 20} + +// gdbg-command:print 'simple_struct::NO_PADDING_163264' +// gdbr-command:print simple_struct::NO_PADDING_163264 +// gdbg-check:$16 = {a = -21, b = 22, c = 23, d = 24} +// gdbr-check:$16 = simple_struct::NoPadding163264 {a: -21, b: 22, c: 23, d: 24} + +// gdbg-command:print 'simple_struct::INTERNAL_PADDING' +// gdbr-command:print simple_struct::INTERNAL_PADDING +// gdbg-check:$17 = {x = 25, y = -26} +// gdbr-check:$17 = simple_struct::InternalPadding {x: 25, y: -26} + +// gdbg-command:print 'simple_struct::PADDING_AT_END' +// gdbr-command:print simple_struct::PADDING_AT_END +// gdbg-check:$18 = {x = -27, y = 28} +// gdbr-check:$18 = simple_struct::PaddingAtEnd {x: -27, y: 28} // gdb-command:continue diff --git a/src/test/debuginfo/simple-tuple.rs b/src/test/debuginfo/simple-tuple.rs index 1b85ecc537a34..354a2c26cb36d 100644 --- a/src/test/debuginfo/simple-tuple.rs +++ b/src/test/debuginfo/simple-tuple.rs @@ -14,58 +14,97 @@ // === GDB TESTS =================================================================================== -// gdb-command:print/d 'simple_tuple::NO_PADDING_8' -// gdb-check:$1 = {__0 = -50, __1 = 50} -// gdb-command:print 'simple_tuple::NO_PADDING_16' -// gdb-check:$2 = {__0 = -1, __1 = 2, __2 = 3} -// gdb-command:print 'simple_tuple::NO_PADDING_32' -// gdb-check:$3 = {__0 = 4, __1 = 5, __2 = 6} -// gdb-command:print 'simple_tuple::NO_PADDING_64' -// gdb-check:$4 = {__0 = 7, __1 = 8, __2 = 9} - -// gdb-command:print 'simple_tuple::INTERNAL_PADDING_1' -// gdb-check:$5 = {__0 = 10, __1 = 11} -// gdb-command:print 'simple_tuple::INTERNAL_PADDING_2' -// gdb-check:$6 = {__0 = 12, __1 = 13, __2 = 14, __3 = 15} - -// gdb-command:print 'simple_tuple::PADDING_AT_END' -// gdb-check:$7 = {__0 = 16, __1 = 17} +// there's no frame yet for gdb to reliably detect the language, set it explicitly +// gdbr-command:set language rust + +// gdbg-command:print/d 'simple_tuple::NO_PADDING_8' +// gdbr-command:print simple_tuple::NO_PADDING_8 +// gdbg-check:$1 = {__0 = -50, __1 = 50} +// gdbr-check:$1 = (-50, 50) +// gdbg-command:print 'simple_tuple::NO_PADDING_16' +// gdbr-command:print simple_tuple::NO_PADDING_16 +// gdbg-check:$2 = {__0 = -1, __1 = 2, __2 = 3} +// gdbr-check:$2 = (-1, 2, 3) +// gdbg-command:print 'simple_tuple::NO_PADDING_32' +// gdbr-command:print simple_tuple::NO_PADDING_32 +// gdbg-check:$3 = {__0 = 4, __1 = 5, __2 = 6} +// gdbr-check:$3 = (4, 5, 6) +// gdbg-command:print 'simple_tuple::NO_PADDING_64' +// gdbr-command:print simple_tuple::NO_PADDING_64 +// gdbg-check:$4 = {__0 = 7, __1 = 8, __2 = 9} +// gdbr-check:$4 = (7, 8, 9) + +// gdbg-command:print 'simple_tuple::INTERNAL_PADDING_1' +// gdbr-command:print simple_tuple::INTERNAL_PADDING_1 +// gdbg-check:$5 = {__0 = 10, __1 = 11} +// gdbr-check:$5 = (10, 11) +// gdbg-command:print 'simple_tuple::INTERNAL_PADDING_2' +// gdbr-command:print simple_tuple::INTERNAL_PADDING_2 +// gdbg-check:$6 = {__0 = 12, __1 = 13, __2 = 14, __3 = 15} +// gdbr-check:$6 = (12, 13, 14, 15) + +// gdbg-command:print 'simple_tuple::PADDING_AT_END' +// gdbr-command:print simple_tuple::PADDING_AT_END +// gdbg-check:$7 = {__0 = 16, __1 = 17} +// gdbr-check:$7 = (16, 17) // gdb-command:run -// gdb-command:print/d noPadding8 -// gdb-check:$8 = {__0 = -100, __1 = 100} +// gdbg-command:print/d noPadding8 +// gdbr-command:print noPadding8 +// gdbg-check:$8 = {__0 = -100, __1 = 100} +// gdbr-check:$8 = (-100, 100) // gdb-command:print noPadding16 -// gdb-check:$9 = {__0 = 0, __1 = 1, __2 = 2} +// gdbg-check:$9 = {__0 = 0, __1 = 1, __2 = 2} +// gdbr-check:$9 = (0, 1, 2) // gdb-command:print noPadding32 -// gdb-check:$10 = {__0 = 3, __1 = 4.5, __2 = 5} +// gdbg-check:$10 = {__0 = 3, __1 = 4.5, __2 = 5} +// gdbr-check:$10 = (3, 4.5, 5) // gdb-command:print noPadding64 -// gdb-check:$11 = {__0 = 6, __1 = 7.5, __2 = 8} +// gdbg-check:$11 = {__0 = 6, __1 = 7.5, __2 = 8} +// gdbr-check:$11 = (6, 7.5, 8) // gdb-command:print internalPadding1 -// gdb-check:$12 = {__0 = 9, __1 = 10} +// gdbg-check:$12 = {__0 = 9, __1 = 10} +// gdbr-check:$12 = (9, 10) // gdb-command:print internalPadding2 -// gdb-check:$13 = {__0 = 11, __1 = 12, __2 = 13, __3 = 14} +// gdbg-check:$13 = {__0 = 11, __1 = 12, __2 = 13, __3 = 14} +// gdbr-check:$13 = (11, 12, 13, 14) // gdb-command:print paddingAtEnd -// gdb-check:$14 = {__0 = 15, __1 = 16} - -// gdb-command:print/d 'simple_tuple::NO_PADDING_8' -// gdb-check:$15 = {__0 = -127, __1 = 127} -// gdb-command:print 'simple_tuple::NO_PADDING_16' -// gdb-check:$16 = {__0 = -10, __1 = 10, __2 = 9} -// gdb-command:print 'simple_tuple::NO_PADDING_32' -// gdb-check:$17 = {__0 = 14, __1 = 15, __2 = 16} -// gdb-command:print 'simple_tuple::NO_PADDING_64' -// gdb-check:$18 = {__0 = 17, __1 = 18, __2 = 19} - -// gdb-command:print 'simple_tuple::INTERNAL_PADDING_1' -// gdb-check:$19 = {__0 = 110, __1 = 111} -// gdb-command:print 'simple_tuple::INTERNAL_PADDING_2' -// gdb-check:$20 = {__0 = 112, __1 = 113, __2 = 114, __3 = 115} - -// gdb-command:print 'simple_tuple::PADDING_AT_END' -// gdb-check:$21 = {__0 = 116, __1 = 117} +// gdbg-check:$14 = {__0 = 15, __1 = 16} +// gdbr-check:$14 = (15, 16) + +// gdbg-command:print/d 'simple_tuple::NO_PADDING_8' +// gdbr-command:print simple_tuple::NO_PADDING_8 +// gdbg-check:$15 = {__0 = -127, __1 = 127} +// gdbr-check:$15 = (-127, 127) +// gdbg-command:print 'simple_tuple::NO_PADDING_16' +// gdbr-command:print simple_tuple::NO_PADDING_16 +// gdbg-check:$16 = {__0 = -10, __1 = 10, __2 = 9} +// gdbr-check:$16 = (-10, 10, 9) +// gdbg-command:print 'simple_tuple::NO_PADDING_32' +// gdbr-command:print simple_tuple::NO_PADDING_32 +// gdbg-check:$17 = {__0 = 14, __1 = 15, __2 = 16} +// gdbr-check:$17 = (14, 15, 16) +// gdbg-command:print 'simple_tuple::NO_PADDING_64' +// gdbr-command:print simple_tuple::NO_PADDING_64 +// gdbg-check:$18 = {__0 = 17, __1 = 18, __2 = 19} +// gdbr-check:$18 = (17, 18, 19) + +// gdbg-command:print 'simple_tuple::INTERNAL_PADDING_1' +// gdbr-command:print simple_tuple::INTERNAL_PADDING_1 +// gdbg-check:$19 = {__0 = 110, __1 = 111} +// gdbr-check:$19 = (110, 111) +// gdbg-command:print 'simple_tuple::INTERNAL_PADDING_2' +// gdbr-command:print simple_tuple::INTERNAL_PADDING_2 +// gdbg-check:$20 = {__0 = 112, __1 = 113, __2 = 114, __3 = 115} +// gdbr-check:$20 = (112, 113, 114, 115) + +// gdbg-command:print 'simple_tuple::PADDING_AT_END' +// gdbr-command:print simple_tuple::PADDING_AT_END +// gdbg-check:$21 = {__0 = 116, __1 = 117} +// gdbr-check:$21 = (116, 117) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/struct-in-enum.rs b/src/test/debuginfo/struct-in-enum.rs index 98b90de600516..d0aceaa4f3f9c 100644 --- a/src/test/debuginfo/struct-in-enum.rs +++ b/src/test/debuginfo/struct-in-enum.rs @@ -19,13 +19,16 @@ // gdb-command:run // gdb-command:print case1 -// gdb-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = {x = 2088533116, y = 2088533116, z = 31868}}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 8970181431921507452, __2 = 31868}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = {x = 2088533116, y = 2088533116, z = 31868}}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 8970181431921507452, __2 = 31868}} +// gdbr-check:$1 = struct_in_enum::Regular::Case1(0, struct_in_enum::Struct {x: 2088533116, y: 2088533116, z: 31868}) // gdb-command:print case2 -// gdb-check:$2 = {{RUST$ENUM$DISR = Case2, __0 = 0, __1 = {x = 286331153, y = 286331153, z = 4369}}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 1229782938247303441, __2 = 4369}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, __0 = 0, __1 = {x = 286331153, y = 286331153, z = 4369}}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 1229782938247303441, __2 = 4369}} +// gdbr-check:$2 = struct_in_enum::Regular::Case2(0, 1229782938247303441, 4369) // gdb-command:print univariant -// gdb-check:$3 = {{__0 = {x = 123, y = 456, z = 789}}} +// gdbg-check:$3 = {{__0 = {x = 123, y = 456, z = 789}}} +// gdbr-check:$3 = struct_in_enum::Univariant::TheOnlyCase(struct_in_enum::Struct {x: 123, y: 456, z: 789}) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/struct-in-struct.rs b/src/test/debuginfo/struct-in-struct.rs index 76a1613c23146..46524cf1d029a 100644 --- a/src/test/debuginfo/struct-in-struct.rs +++ b/src/test/debuginfo/struct-in-struct.rs @@ -18,13 +18,16 @@ // gdb-command:run // gdb-command:print three_simple_structs -// gdb-check:$1 = {x = {x = 1}, y = {x = 2}, z = {x = 3}} +// gdbg-check:$1 = {x = {x = 1}, y = {x = 2}, z = {x = 3}} +// gdbr-check:$1 = struct_in_struct::ThreeSimpleStructs {x: struct_in_struct::Simple {x: 1}, y: struct_in_struct::Simple {x: 2}, z: struct_in_struct::Simple {x: 3}} // gdb-command:print internal_padding_parent -// gdb-check:$2 = {x = {x = 4, y = 5}, y = {x = 6, y = 7}, z = {x = 8, y = 9}} +// gdbg-check:$2 = {x = {x = 4, y = 5}, y = {x = 6, y = 7}, z = {x = 8, y = 9}} +// gdbr-check:$2 = struct_in_struct::InternalPaddingParent {x: struct_in_struct::InternalPadding {x: 4, y: 5}, y: struct_in_struct::InternalPadding {x: 6, y: 7}, z: struct_in_struct::InternalPadding {x: 8, y: 9}} // gdb-command:print padding_at_end_parent -// gdb-check:$3 = {x = {x = 10, y = 11}, y = {x = 12, y = 13}, z = {x = 14, y = 15}} +// gdbg-check:$3 = {x = {x = 10, y = 11}, y = {x = 12, y = 13}, z = {x = 14, y = 15}} +// gdbr-check:$3 = struct_in_struct::PaddingAtEndParent {x: struct_in_struct::PaddingAtEnd {x: 10, y: 11}, y: struct_in_struct::PaddingAtEnd {x: 12, y: 13}, z: struct_in_struct::PaddingAtEnd {x: 14, y: 15}} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/struct-style-enum.rs b/src/test/debuginfo/struct-style-enum.rs index 3376fc9bbd450..8abc139eb1172 100644 --- a/src/test/debuginfo/struct-style-enum.rs +++ b/src/test/debuginfo/struct-style-enum.rs @@ -19,16 +19,20 @@ // gdb-command:run // gdb-command:print case1 -// gdb-check:$1 = {{RUST$ENUM$DISR = Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {RUST$ENUM$DISR = Case1, a = 0, b = 2088533116, c = 2088533116}, {RUST$ENUM$DISR = Case1, a = 0, b = 8970181431921507452}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {RUST$ENUM$DISR = Case1, a = 0, b = 2088533116, c = 2088533116}, {RUST$ENUM$DISR = Case1, a = 0, b = 8970181431921507452}} +// gdbr-check:$1 = struct_style_enum::Regular::Case1{a: 0, b: 31868, c: 31868, d: 31868, e: 31868} // gdb-command:print case2 -// gdb-check:$2 = {{RUST$ENUM$DISR = Case2, a = 0, b = 4369, c = 4369, d = 4369, e = 4369}, {RUST$ENUM$DISR = Case2, a = 0, b = 286331153, c = 286331153}, {RUST$ENUM$DISR = Case2, a = 0, b = 1229782938247303441}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, a = 0, b = 4369, c = 4369, d = 4369, e = 4369}, {RUST$ENUM$DISR = Case2, a = 0, b = 286331153, c = 286331153}, {RUST$ENUM$DISR = Case2, a = 0, b = 1229782938247303441}} +// gdbr-check:$2 = struct_style_enum::Regular::Case2{a: 0, b: 286331153, c: 286331153} // gdb-command:print case3 -// gdb-check:$3 = {{RUST$ENUM$DISR = Case3, a = 0, b = 22873, c = 22873, d = 22873, e = 22873}, {RUST$ENUM$DISR = Case3, a = 0, b = 1499027801, c = 1499027801}, {RUST$ENUM$DISR = Case3, a = 0, b = 6438275382588823897}} +// gdbg-check:$3 = {{RUST$ENUM$DISR = Case3, a = 0, b = 22873, c = 22873, d = 22873, e = 22873}, {RUST$ENUM$DISR = Case3, a = 0, b = 1499027801, c = 1499027801}, {RUST$ENUM$DISR = Case3, a = 0, b = 6438275382588823897}} +// gdbr-check:$3 = struct_style_enum::Regular::Case3{a: 0, b: 6438275382588823897} // gdb-command:print univariant -// gdb-check:$4 = {{a = -1}} +// gdbg-check:$4 = {{a = -1}} +// gdbr-check:$4 = struct_style_enum::Univariant::TheOnlyCase{a: -1} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/struct-with-destructor.rs b/src/test/debuginfo/struct-with-destructor.rs index ad8731997abd7..af70b4a63fd27 100644 --- a/src/test/debuginfo/struct-with-destructor.rs +++ b/src/test/debuginfo/struct-with-destructor.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-linelength + // min-lldb-version: 310 // compile-flags:-g @@ -16,16 +18,20 @@ // gdb-command:run // gdb-command:print simple -// gdb-check:$1 = {x = 10, y = 20} +// gdbg-check:$1 = {x = 10, y = 20} +// gdbr-check:$1 = struct_with_destructor::WithDestructor {x: 10, y: 20} // gdb-command:print noDestructor -// gdb-check:$2 = {a = {x = 10, y = 20}, guard = -1} +// gdbg-check:$2 = {a = {x = 10, y = 20}, guard = -1} +// gdbr-check:$2 = struct_with_destructor::NoDestructorGuarded {a: struct_with_destructor::NoDestructor {x: 10, y: 20}, guard: -1} // gdb-command:print withDestructor -// gdb-check:$3 = {a = {x = 10, y = 20}, guard = -1} +// gdbg-check:$3 = {a = {x = 10, y = 20}, guard = -1} +// gdbr-check:$3 = struct_with_destructor::WithDestructorGuarded {a: struct_with_destructor::WithDestructor {x: 10, y: 20}, guard: -1} // gdb-command:print nested -// gdb-check:$4 = {a = {a = {x = 7890, y = 9870}}} +// gdbg-check:$4 = {a = {a = {x = 7890, y = 9870}}} +// gdbr-check:$4 = struct_with_destructor::NestedOuter {a: struct_with_destructor::NestedInner {a: struct_with_destructor::WithDestructor {x: 7890, y: 9870}}} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/tuple-in-struct.rs b/src/test/debuginfo/tuple-in-struct.rs index 1a7fde766f0d8..dae1f5da542f5 100644 --- a/src/test/debuginfo/tuple-in-struct.rs +++ b/src/test/debuginfo/tuple-in-struct.rs @@ -17,29 +17,39 @@ // gdb-command:run // gdb-command:print no_padding1 -// gdb-check:$1 = {x = {__0 = 0, __1 = 1}, y = 2, z = {__0 = 3, __1 = 4, __2 = 5}} +// gdbg-check:$1 = {x = {__0 = 0, __1 = 1}, y = 2, z = {__0 = 3, __1 = 4, __2 = 5}} +// gdbr-check:$1 = tuple_in_struct::NoPadding1 {x: (0, 1), y: 2, z: (3, 4, 5)} // gdb-command:print no_padding2 -// gdb-check:$2 = {x = {__0 = 6, __1 = 7}, y = {__0 = {__0 = 8, __1 = 9}, __1 = 10}} +// gdbg-check:$2 = {x = {__0 = 6, __1 = 7}, y = {__0 = {__0 = 8, __1 = 9}, __1 = 10}} +// gdbr-check:$2 = tuple_in_struct::NoPadding2 {x: (6, 7), y: ((8, 9), 10)} // gdb-command:print tuple_internal_padding -// gdb-check:$3 = {x = {__0 = 11, __1 = 12}, y = {__0 = 13, __1 = 14}} +// gdbg-check:$3 = {x = {__0 = 11, __1 = 12}, y = {__0 = 13, __1 = 14}} +// gdbr-check:$3 = tuple_in_struct::TupleInternalPadding {x: (11, 12), y: (13, 14)} // gdb-command:print struct_internal_padding -// gdb-check:$4 = {x = {__0 = 15, __1 = 16}, y = {__0 = 17, __1 = 18}} +// gdbg-check:$4 = {x = {__0 = 15, __1 = 16}, y = {__0 = 17, __1 = 18}} +// gdbr-check:$4 = tuple_in_struct::StructInternalPadding {x: (15, 16), y: (17, 18)} // gdb-command:print both_internally_padded -// gdb-check:$5 = {x = {__0 = 19, __1 = 20, __2 = 21}, y = {__0 = 22, __1 = 23}} +// gdbg-check:$5 = {x = {__0 = 19, __1 = 20, __2 = 21}, y = {__0 = 22, __1 = 23}} +// gdbr-check:$5 = tuple_in_struct::BothInternallyPadded {x: (19, 20, 21), y: (22, 23)} // gdb-command:print single_tuple -// gdb-check:$6 = {x = {__0 = 24, __1 = 25, __2 = 26}} +// gdbg-check:$6 = {x = {__0 = 24, __1 = 25, __2 = 26}} +// gdbr-check:$6 = tuple_in_struct::SingleTuple {x: (24, 25, 26)} // gdb-command:print tuple_padded_at_end -// gdb-check:$7 = {x = {__0 = 27, __1 = 28}, y = {__0 = 29, __1 = 30}} +// gdbg-check:$7 = {x = {__0 = 27, __1 = 28}, y = {__0 = 29, __1 = 30}} +// gdbr-check:$7 = tuple_in_struct::TuplePaddedAtEnd {x: (27, 28), y: (29, 30)} // gdb-command:print struct_padded_at_end -// gdb-check:$8 = {x = {__0 = 31, __1 = 32}, y = {__0 = 33, __1 = 34}} +// gdbg-check:$8 = {x = {__0 = 31, __1 = 32}, y = {__0 = 33, __1 = 34}} +// gdbr-check:$8 = tuple_in_struct::StructPaddedAtEnd {x: (31, 32), y: (33, 34)} // gdb-command:print both_padded_at_end -// gdb-check:$9 = {x = {__0 = 35, __1 = 36, __2 = 37}, y = {__0 = 38, __1 = 39}} +// gdbg-check:$9 = {x = {__0 = 35, __1 = 36, __2 = 37}, y = {__0 = 38, __1 = 39}} +// gdbr-check:$9 = tuple_in_struct::BothPaddedAtEnd {x: (35, 36, 37), y: (38, 39)} // gdb-command:print mixed_padding -// gdb-check:$10 = {x = {__0 = {__0 = 40, __1 = 41, __2 = 42}, __1 = {__0 = 43, __1 = 44}}, y = {__0 = 45, __1 = 46, __2 = 47, __3 = 48}} +// gdbg-check:$10 = {x = {__0 = {__0 = 40, __1 = 41, __2 = 42}, __1 = {__0 = 43, __1 = 44}}, y = {__0 = 45, __1 = 46, __2 = 47, __3 = 48}} +// gdbr-check:$10 = tuple_in_struct::MixedPadding {x: ((40, 41, 42), (43, 44)), y: (45, 46, 47, 48)} #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/src/test/debuginfo/tuple-in-tuple.rs b/src/test/debuginfo/tuple-in-tuple.rs index a514b69a2d31d..4ebc740b9c0f7 100644 --- a/src/test/debuginfo/tuple-in-tuple.rs +++ b/src/test/debuginfo/tuple-in-tuple.rs @@ -17,21 +17,28 @@ // gdb-command:run // gdb-command:print no_padding1 -// gdb-check:$1 = {__0 = {__0 = 0, __1 = 1}, __1 = 2, __2 = 3} +// gdbg-check:$1 = {__0 = {__0 = 0, __1 = 1}, __1 = 2, __2 = 3} +// gdbr-check:$1 = ((0, 1), 2, 3) // gdb-command:print no_padding2 -// gdb-check:$2 = {__0 = 4, __1 = {__0 = 5, __1 = 6}, __2 = 7} +// gdbg-check:$2 = {__0 = 4, __1 = {__0 = 5, __1 = 6}, __2 = 7} +// gdbr-check:$2 = (4, (5, 6), 7) // gdb-command:print no_padding3 -// gdb-check:$3 = {__0 = 8, __1 = 9, __2 = {__0 = 10, __1 = 11}} +// gdbg-check:$3 = {__0 = 8, __1 = 9, __2 = {__0 = 10, __1 = 11}} +// gdbr-check:$3 = (8, 9, (10, 11)) // gdb-command:print internal_padding1 -// gdb-check:$4 = {__0 = 12, __1 = {__0 = 13, __1 = 14}} +// gdbg-check:$4 = {__0 = 12, __1 = {__0 = 13, __1 = 14}} +// gdbr-check:$4 = (12, (13, 14)) // gdb-command:print internal_padding2 -// gdb-check:$5 = {__0 = 15, __1 = {__0 = 16, __1 = 17}} +// gdbg-check:$5 = {__0 = 15, __1 = {__0 = 16, __1 = 17}} +// gdbr-check:$5 = (15, (16, 17)) // gdb-command:print padding_at_end1 -// gdb-check:$6 = {__0 = 18, __1 = {__0 = 19, __1 = 20}} +// gdbg-check:$6 = {__0 = 18, __1 = {__0 = 19, __1 = 20}} +// gdbr-check:$6 = (18, (19, 20)) // gdb-command:print padding_at_end2 -// gdb-check:$7 = {__0 = {__0 = 21, __1 = 22}, __1 = 23} +// gdbg-check:$7 = {__0 = {__0 = 21, __1 = 22}, __1 = 23} +// gdbr-check:$7 = ((21, 22), 23) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/tuple-struct.rs b/src/test/debuginfo/tuple-struct.rs index a2ca8c2237b42..aa644d8419b54 100644 --- a/src/test/debuginfo/tuple-struct.rs +++ b/src/test/debuginfo/tuple-struct.rs @@ -17,22 +17,28 @@ // gdb-command:run // gdb-command:print no_padding16 -// gdb-check:$1 = {__0 = 10000, __1 = -10001} +// gdbg-check:$1 = {__0 = 10000, __1 = -10001} +// gdbr-check:$1 = tuple_struct::NoPadding16 (10000, -10001) // gdb-command:print no_padding32 -// gdb-check:$2 = {__0 = -10002, __1 = -10003.5, __2 = 10004} +// gdbg-check:$2 = {__0 = -10002, __1 = -10003.5, __2 = 10004} +// gdbr-check:$2 = tuple_struct::NoPadding32 (-10002, -10003.5, 10004) // gdb-command:print no_padding64 -// gdb-check:$3 = {__0 = -10005.5, __1 = 10006, __2 = 10007} +// gdbg-check:$3 = {__0 = -10005.5, __1 = 10006, __2 = 10007} +// gdbr-check:$3 = tuple_struct::NoPadding64 (-10005.5, 10006, 10007) // gdb-command:print no_padding163264 -// gdb-check:$4 = {__0 = -10008, __1 = 10009, __2 = 10010, __3 = 10011} +// gdbg-check:$4 = {__0 = -10008, __1 = 10009, __2 = 10010, __3 = 10011} +// gdbr-check:$4 = tuple_struct::NoPadding163264 (-10008, 10009, 10010, 10011) // gdb-command:print internal_padding -// gdb-check:$5 = {__0 = 10012, __1 = -10013} +// gdbg-check:$5 = {__0 = 10012, __1 = -10013} +// gdbr-check:$5 = tuple_struct::InternalPadding (10012, -10013) // gdb-command:print padding_at_end -// gdb-check:$6 = {__0 = -10014, __1 = 10015} +// gdbg-check:$6 = {__0 = -10014, __1 = 10015} +// gdbr-check:$6 = tuple_struct::PaddingAtEnd (-10014, 10015) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/tuple-style-enum.rs b/src/test/debuginfo/tuple-style-enum.rs index 52f171434b037..d05edec3e737d 100644 --- a/src/test/debuginfo/tuple-style-enum.rs +++ b/src/test/debuginfo/tuple-style-enum.rs @@ -19,16 +19,20 @@ // gdb-command:run // gdb-command:print case1 -// gdb-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = 31868, __2 = 31868, __3 = 31868, __4 = 31868}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 2088533116, __2 = 2088533116}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 8970181431921507452}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = 31868, __2 = 31868, __3 = 31868, __4 = 31868}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 2088533116, __2 = 2088533116}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 8970181431921507452}} +// gdbr-check:$1 = tuple_style_enum::Regular::Case1(0, 31868, 31868, 31868, 31868) // gdb-command:print case2 -// gdb-check:$2 = {{RUST$ENUM$DISR = Case2, __0 = 0, __1 = 4369, __2 = 4369, __3 = 4369, __4 = 4369}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 286331153, __2 = 286331153}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 1229782938247303441}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, __0 = 0, __1 = 4369, __2 = 4369, __3 = 4369, __4 = 4369}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 286331153, __2 = 286331153}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 1229782938247303441}} +// gdbr-check:$2 = tuple_style_enum::Regular::Case2(0, 286331153, 286331153) // gdb-command:print case3 -// gdb-check:$3 = {{RUST$ENUM$DISR = Case3, __0 = 0, __1 = 22873, __2 = 22873, __3 = 22873, __4 = 22873}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 1499027801, __2 = 1499027801}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 6438275382588823897}} +// gdbg-check:$3 = {{RUST$ENUM$DISR = Case3, __0 = 0, __1 = 22873, __2 = 22873, __3 = 22873, __4 = 22873}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 1499027801, __2 = 1499027801}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 6438275382588823897}} +// gdbr-check:$3 = tuple_style_enum::Regular::Case3(0, 6438275382588823897) // gdb-command:print univariant -// gdb-check:$4 = {{__0 = -1}} +// gdbg-check:$4 = {{__0 = -1}} +// gdbr-check:$4 = tuple_style_enum::Univariant::TheOnlyCase(-1) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs index 2419625cbd374..438a78743bb1e 100644 --- a/src/test/debuginfo/type-names.rs +++ b/src/test/debuginfo/type-names.rs @@ -20,160 +20,206 @@ // STRUCTS // gdb-command:whatis simple_struct -// gdb-check:type = struct Struct1 +// gdbg-check:type = struct Struct1 +// gdbr-check:type = type_names::Struct1 // gdb-command:whatis generic_struct1 -// gdb-check:type = struct GenericStruct +// gdbg-check:type = struct GenericStruct +// gdbr-check:type = type_names::GenericStruct // gdb-command:whatis generic_struct2 -// gdb-check:type = struct GenericStruct usize> +// gdbg-check:type = struct GenericStruct usize> +// gdbr-check:type = type_names::GenericStruct usize> // gdb-command:whatis mod_struct -// gdb-check:type = struct Struct2 +// gdbg-check:type = struct Struct2 +// gdbr-check:type = type_names::mod1::Struct2 // ENUMS // gdb-command:whatis simple_enum_1 -// gdb-check:type = union Enum1 +// gdbg-check:type = union Enum1 +// gdbr-check:type = type_names::Enum1 // gdb-command:whatis simple_enum_2 -// gdb-check:type = union Enum1 +// gdbg-check:type = union Enum1 +// gdbr-check:type = type_names::Enum1 // gdb-command:whatis simple_enum_3 -// gdb-check:type = union Enum2 +// gdbg-check:type = union Enum2 +// gdbr-check:type = type_names::mod1::Enum2 // gdb-command:whatis generic_enum_1 -// gdb-check:type = union Enum3 +// gdbg-check:type = union Enum3 +// gdbr-check:type = type_names::mod1::mod2::Enum3 // gdb-command:whatis generic_enum_2 -// gdb-check:type = union Enum3 +// gdbg-check:type = union Enum3 +// gdbr-check:type = type_names::mod1::mod2::Enum3 // TUPLES // gdb-command:whatis tuple1 -// gdb-check:type = struct (u32, type_names::Struct1, type_names::mod1::mod2::Enum3) +// gdbg-check:type = struct (u32, type_names::Struct1, type_names::mod1::mod2::Enum3) +// gdbr-check:type = (u32, type_names::Struct1, type_names::mod1::mod2::Enum3) // gdb-command:whatis tuple2 -// gdb-check:type = struct ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char) +// gdbg-check:type = struct ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char) +// gdbr-check:type = ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char) // BOX // gdb-command:whatis box1 -// gdb-check:type = struct (Box, i32) +// gdbg-check:type = struct (Box, i32) +// gdbr-check:type = (Box, i32) // gdb-command:whatis box2 -// gdb-check:type = struct (Box>, i32) +// gdbg-check:type = struct (Box>, i32) +// gdbr-check:type = (Box>, i32) // REFERENCES // gdb-command:whatis ref1 -// gdb-check:type = struct (&type_names::Struct1, i32) +// gdbg-check:type = struct (&type_names::Struct1, i32) +// gdbr-check:type = (&type_names::Struct1, i32) // gdb-command:whatis ref2 -// gdb-check:type = struct (&type_names::GenericStruct, i32) +// gdbg-check:type = struct (&type_names::GenericStruct, i32) +// gdbr-check:type = (&type_names::GenericStruct, i32) // gdb-command:whatis mut_ref1 -// gdb-check:type = struct (&mut type_names::Struct1, i32) +// gdbg-check:type = struct (&mut type_names::Struct1, i32) +// gdbr-check:type = (&mut type_names::Struct1, i32) // gdb-command:whatis mut_ref2 -// gdb-check:type = struct (&mut type_names::GenericStruct, i32) +// gdbg-check:type = struct (&mut type_names::GenericStruct, i32) +// gdbr-check:type = (&mut type_names::GenericStruct, i32) // RAW POINTERS // gdb-command:whatis mut_ptr1 -// gdb-check:type = struct (*mut type_names::Struct1, isize) +// gdbg-check:type = struct (*mut type_names::Struct1, isize) +// gdbr-check:type = (*mut type_names::Struct1, isize) // gdb-command:whatis mut_ptr2 -// gdb-check:type = struct (*mut isize, isize) +// gdbg-check:type = struct (*mut isize, isize) +// gdbr-check:type = (*mut isize, isize) // gdb-command:whatis mut_ptr3 -// gdb-check:type = struct (*mut type_names::mod1::mod2::Enum3, isize) +// gdbg-check:type = struct (*mut type_names::mod1::mod2::Enum3, isize) +// gdbr-check:type = (*mut type_names::mod1::mod2::Enum3, isize) // gdb-command:whatis const_ptr1 -// gdb-check:type = struct (*const type_names::Struct1, isize) +// gdbg-check:type = struct (*const type_names::Struct1, isize) +// gdbr-check:type = (*const type_names::Struct1, isize) // gdb-command:whatis const_ptr2 -// gdb-check:type = struct (*const isize, isize) +// gdbg-check:type = struct (*const isize, isize) +// gdbr-check:type = (*const isize, isize) // gdb-command:whatis const_ptr3 -// gdb-check:type = struct (*const type_names::mod1::mod2::Enum3, isize) +// gdbg-check:type = struct (*const type_names::mod1::mod2::Enum3, isize) +// gdbr-check:type = (*const type_names::mod1::mod2::Enum3, isize) // VECTORS // gdb-command:whatis fixed_size_vec1 -// gdb-check:type = struct ([type_names::Struct1; 3], i16) +// gdbg-check:type = struct ([type_names::Struct1; 3], i16) +// gdbr-check:type = ([type_names::Struct1; 3], i16) // gdb-command:whatis fixed_size_vec2 -// gdb-check:type = struct ([usize; 3], i16) +// gdbg-check:type = struct ([usize; 3], i16) +// gdbr-check:type = ([usize; 3], i16) // gdb-command:whatis slice1 -// gdb-check:type = struct &[usize] +// gdbg-check:type = struct &[usize] +// gdbr-check:type = &[usize] // gdb-command:whatis slice2 -// gdb-check:type = struct &[type_names::mod1::Enum2] +// gdbg-check:type = struct &[type_names::mod1::Enum2] +// gdbr-check:type = &[type_names::mod1::Enum2] // TRAITS // gdb-command:whatis box_trait -// gdb-check:type = struct Box +// gdbg-check:type = struct Box +// gdbr-check:type = type_names::Box // gdb-command:whatis ref_trait -// gdb-check:type = struct &Trait1 +// gdbg-check:type = struct &Trait1 +// gdbr-check:type = type_names::&Trait1 // gdb-command:whatis mut_ref_trait -// gdb-check:type = struct &mut Trait1 +// gdbg-check:type = struct &mut Trait1 +// gdbr-check:type = type_names::&mut Trait1 // gdb-command:whatis generic_box_trait -// gdb-check:type = struct Box> +// gdbg-check:type = struct Box> +// gdbr-check:type = type_names::Box> // gdb-command:whatis generic_ref_trait -// gdb-check:type = struct &Trait2 +// gdbg-check:type = struct &Trait2 +// gdbr-check:type = type_names::&Trait2 // gdb-command:whatis generic_mut_ref_trait -// gdb-check:type = struct &mut Trait2> +// gdbg-check:type = struct &mut Trait2> +// gdbr-check:type = type_names::&mut Trait2> // BARE FUNCTIONS // gdb-command:whatis rust_fn -// gdb-check:type = struct (fn(core::option::Option, core::option::Option<&type_names::mod1::Struct2>), usize) +// gdbg-check:type = struct (fn(core::option::Option, core::option::Option<&type_names::mod1::Struct2>), usize) +// gdbr-check:type = (fn(core::option::Option, core::option::Option<&type_names::mod1::Struct2>), usize) // gdb-command:whatis extern_c_fn -// gdb-check:type = struct (extern "C" fn(isize), usize) +// gdbg-check:type = struct (extern "C" fn(isize), usize) +// gdbr-check:type = (extern "C" fn(isize), usize) // gdb-command:whatis unsafe_fn -// gdb-check:type = struct (unsafe fn(core::result::Result), usize) +// gdbg-check:type = struct (unsafe fn(core::result::Result), usize) +// gdbr-check:type = (unsafe fn(core::result::Result), usize) // gdb-command:whatis extern_stdcall_fn -// gdb-check:type = struct (extern "stdcall" fn(), usize) +// gdbg-check:type = struct (extern "stdcall" fn(), usize) +// gdbr-check:type = (extern "stdcall" fn(), usize) // gdb-command:whatis rust_fn_with_return_value -// gdb-check:type = struct (fn(f64) -> usize, usize) +// gdbg-check:type = struct (fn(f64) -> usize, usize) +// gdbr-check:type = (fn(f64) -> usize, usize) // gdb-command:whatis extern_c_fn_with_return_value -// gdb-check:type = struct (extern "C" fn() -> type_names::Struct1, usize) +// gdbg-check:type = struct (extern "C" fn() -> type_names::Struct1, usize) +// gdbr-check:type = (extern "C" fn() -> type_names::Struct1, usize) // gdb-command:whatis unsafe_fn_with_return_value -// gdb-check:type = struct (unsafe fn(type_names::GenericStruct) -> type_names::mod1::Struct2, usize) +// gdbg-check:type = struct (unsafe fn(type_names::GenericStruct) -> type_names::mod1::Struct2, usize) +// gdbr-check:type = (unsafe fn(type_names::GenericStruct) -> type_names::mod1::Struct2, usize) // gdb-command:whatis extern_stdcall_fn_with_return_value -// gdb-check:type = struct (extern "stdcall" fn(Box) -> usize, usize) +// gdbg-check:type = struct (extern "stdcall" fn(Box) -> usize, usize) +// gdbr-check:type = (extern "stdcall" fn(Box) -> usize, usize) // gdb-command:whatis generic_function_int -// gdb-check:type = struct (fn(isize) -> isize, usize) +// gdbg-check:type = struct (fn(isize) -> isize, usize) +// gdbr-check:type = (fn(isize) -> isize, usize) // gdb-command:whatis generic_function_struct3 -// gdb-check:type = struct (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize) +// gdbg-check:type = struct (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize) +// gdbr-check:type = (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize) // gdb-command:whatis variadic_function -// gdb-check:type = struct (unsafe extern "C" fn(*const u8, ...) -> isize, usize) +// gdbg-check:type = struct (unsafe extern "C" fn(*const u8, ...) -> isize, usize) +// gdbr-check:type = (unsafe extern "C" fn(*const u8, ...) -> isize, usize) // CLOSURES // gdb-command:whatis closure1 -// gdb-check:type = struct (closure, usize) +// gdbg-check:type = struct (closure, usize) +// gdbr-check:type = (closure, usize) // gdb-command:whatis closure2 -// gdb-check:type = struct (closure, usize) +// gdbg-check:type = struct (closure, usize) +// gdbr-check:type = (closure, usize) #![feature(box_syntax)] #![allow(unused_variables)] diff --git a/src/test/debuginfo/union-smoke.rs b/src/test/debuginfo/union-smoke.rs index 319927c979bf8..26e73a08ea137 100644 --- a/src/test/debuginfo/union-smoke.rs +++ b/src/test/debuginfo/union-smoke.rs @@ -16,9 +16,11 @@ // gdb-command:run // gdb-command:print u -// gdb-check:$1 = {a = {__0 = 2 '\002', __1 = 2 '\002'}, b = 514} +// gdbg-check:$1 = {a = {__0 = 2 '\002', __1 = 2 '\002'}, b = 514} +// gdbr-check:$1 = union_smoke::U {a: (2, 2), b: 514} // gdb-command:print union_smoke::SU -// gdb-check:$2 = {a = {__0 = 1 '\001', __1 = 1 '\001'}, b = 257} +// gdbg-check:$2 = {a = {__0 = 1 '\001', __1 = 1 '\001'}, b = 257} +// gdbr-check:$2 = union_smoke::U {a: (1, 1), b: 257} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/unique-enum.rs b/src/test/debuginfo/unique-enum.rs index bbf13ec756ad8..e882544b802bd 100644 --- a/src/test/debuginfo/unique-enum.rs +++ b/src/test/debuginfo/unique-enum.rs @@ -18,13 +18,16 @@ // gdb-command:run // gdb-command:print *the_a -// gdb-check:$1 = {{RUST$ENUM$DISR = TheA, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = TheA, __0 = 0, __1 = 2088533116, __2 = 2088533116}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = TheA, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = TheA, __0 = 0, __1 = 2088533116, __2 = 2088533116}} +// gdbr-check:$1 = unique_enum::ABC::TheA{x: 0, y: 8970181431921507452} // gdb-command:print *the_b -// gdb-check:$2 = {{RUST$ENUM$DISR = TheB, x = 0, y = 1229782938247303441}, {RUST$ENUM$DISR = TheB, __0 = 0, __1 = 286331153, __2 = 286331153}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = TheB, x = 0, y = 1229782938247303441}, {RUST$ENUM$DISR = TheB, __0 = 0, __1 = 286331153, __2 = 286331153}} +// gdbr-check:$2 = unique_enum::ABC::TheB(0, 286331153, 286331153) // gdb-command:print *univariant -// gdb-check:$3 = {{__0 = 123234}} +// gdbg-check:$3 = {{__0 = 123234}} +// gdbr-check:$3 = unique_enum::Univariant::TheOnlyCase(123234) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/var-captured-in-nested-closure.rs b/src/test/debuginfo/var-captured-in-nested-closure.rs index 7090377e5db1b..b9a1d73b6d869 100644 --- a/src/test/debuginfo/var-captured-in-nested-closure.rs +++ b/src/test/debuginfo/var-captured-in-nested-closure.rs @@ -21,9 +21,11 @@ // gdb-command:print constant // gdb-check:$2 = 2 // gdb-command:print a_struct -// gdb-check:$3 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$3 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$3 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *struct_ref -// gdb-check:$4 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$4 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$4 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *owned // gdb-check:$5 = 6 // gdb-command:print closure_local @@ -35,9 +37,11 @@ // gdb-command:print constant // gdb-check:$8 = 2 // gdb-command:print a_struct -// gdb-check:$9 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$9 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$9 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *struct_ref -// gdb-check:$10 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$10 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$10 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *owned // gdb-check:$11 = 6 // gdb-command:print closure_local diff --git a/src/test/debuginfo/var-captured-in-sendable-closure.rs b/src/test/debuginfo/var-captured-in-sendable-closure.rs index b415546faeac7..120bbdd7ba902 100644 --- a/src/test/debuginfo/var-captured-in-sendable-closure.rs +++ b/src/test/debuginfo/var-captured-in-sendable-closure.rs @@ -19,7 +19,8 @@ // gdb-command:print constant // gdb-check:$1 = 1 // gdb-command:print a_struct -// gdb-check:$2 = {a = -2, b = 3.5, c = 4} +// gdbg-check:$2 = {a = -2, b = 3.5, c = 4} +// gdbr-check:$2 = var_captured_in_sendable_closure::Struct {a: -2, b: 3.5, c: 4} // gdb-command:print *owned // gdb-check:$3 = 5 // gdb-command:continue diff --git a/src/test/debuginfo/var-captured-in-stack-closure.rs b/src/test/debuginfo/var-captured-in-stack-closure.rs index e60f964dd095e..c795a095b9769 100644 --- a/src/test/debuginfo/var-captured-in-stack-closure.rs +++ b/src/test/debuginfo/var-captured-in-stack-closure.rs @@ -21,9 +21,11 @@ // gdb-command:print constant // gdb-check:$2 = 2 // gdb-command:print a_struct -// gdb-check:$3 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$3 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$3 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *struct_ref -// gdb-check:$4 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$4 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$4 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *owned // gdb-check:$5 = 6 @@ -34,9 +36,11 @@ // gdb-command:print constant // gdb-check:$7 = 2 // gdb-command:print a_struct -// gdb-check:$8 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$8 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$8 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *struct_ref -// gdb-check:$9 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$9 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$9 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *owned // gdb-check:$10 = 6 diff --git a/src/test/debuginfo/vec-slices.rs b/src/test/debuginfo/vec-slices.rs index cdb5bc4ecfb6e..5553f8427e90f 100644 --- a/src/test/debuginfo/vec-slices.rs +++ b/src/test/debuginfo/vec-slices.rs @@ -21,42 +21,57 @@ // gdb-command:print singleton.length // gdb-check:$2 = 1 -// gdb-command:print *((int64_t[1]*)(singleton.data_ptr)) -// gdb-check:$3 = {1} +// gdbg-command:print *((int64_t[1]*)(singleton.data_ptr)) +// gdbr-command:print *(singleton.data_ptr as &[i64; 1]) +// gdbg-check:$3 = {1} +// gdbr-check:$3 = [1] // gdb-command:print multiple.length // gdb-check:$4 = 4 -// gdb-command:print *((int64_t[4]*)(multiple.data_ptr)) -// gdb-check:$5 = {2, 3, 4, 5} +// gdbg-command:print *((int64_t[4]*)(multiple.data_ptr)) +// gdbr-command:print *(multiple.data_ptr as &[i64; 4]) +// gdbg-check:$5 = {2, 3, 4, 5} +// gdbr-check:$5 = [2, 3, 4, 5] // gdb-command:print slice_of_slice.length // gdb-check:$6 = 2 -// gdb-command:print *((int64_t[2]*)(slice_of_slice.data_ptr)) -// gdb-check:$7 = {3, 4} +// gdbg-command:print *((int64_t[2]*)(slice_of_slice.data_ptr)) +// gdbr-command:print *(slice_of_slice.data_ptr as &[i64; 2]) +// gdbg-check:$7 = {3, 4} +// gdbr-check:$7 = [3, 4] // gdb-command:print padded_tuple.length // gdb-check:$8 = 2 // gdb-command:print padded_tuple.data_ptr[0] -// gdb-check:$9 = {__0 = 6, __1 = 7} +// gdbg-check:$9 = {__0 = 6, __1 = 7} +// gdbr-check:$9 = (6, 7) // gdb-command:print padded_tuple.data_ptr[1] -// gdb-check:$10 = {__0 = 8, __1 = 9} +// gdbg-check:$10 = {__0 = 8, __1 = 9} +// gdbr-check:$10 = (8, 9) // gdb-command:print padded_struct.length // gdb-check:$11 = 2 // gdb-command:print padded_struct.data_ptr[0] -// gdb-check:$12 = {x = 10, y = 11, z = 12} +// gdbg-check:$12 = {x = 10, y = 11, z = 12} +// gdbr-check:$12 = vec_slices::AStruct {x: 10, y: 11, z: 12} // gdb-command:print padded_struct.data_ptr[1] -// gdb-check:$13 = {x = 13, y = 14, z = 15} +// gdbg-check:$13 = {x = 13, y = 14, z = 15} +// gdbr-check:$13 = vec_slices::AStruct {x: 13, y: 14, z: 15} -// gdb-command:print 'vec_slices::MUT_VECT_SLICE'.length +// gdbg-command:print 'vec_slices::MUT_VECT_SLICE'.length +// gdbr-command:print MUT_VECT_SLICE.length // gdb-check:$14 = 2 -// gdb-command:print *((int64_t[2]*)('vec_slices::MUT_VECT_SLICE'.data_ptr)) -// gdb-check:$15 = {64, 65} +// gdbg-command:print *((int64_t[2]*)('vec_slices::MUT_VECT_SLICE'.data_ptr)) +// gdbr-command:print *(MUT_VECT_SLICE.data_ptr as &[i64; 2]) +// gdbg-check:$15 = {64, 65} +// gdbr-check:$15 = [64, 65] //gdb-command:print mut_slice.length //gdb-check:$16 = 5 -//gdb-command:print *((int64_t[5]*)(mut_slice.data_ptr)) -//gdb-check:$17 = {1, 2, 3, 4, 5} +//gdbg-command:print *((int64_t[5]*)(mut_slice.data_ptr)) +//gdbr-command:print *(mut_slice.data_ptr as &[i64; 5]) +//gdbg-check:$17 = {1, 2, 3, 4, 5} +//gdbr-check:$17 = [1, 2, 3, 4, 5] // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/vec.rs b/src/test/debuginfo/vec.rs index c9827a02fc759..fbb33b94d9577 100644 --- a/src/test/debuginfo/vec.rs +++ b/src/test/debuginfo/vec.rs @@ -16,9 +16,11 @@ // gdb-command:run // gdb-command:print a -// gdb-check:$1 = {1, 2, 3} +// gdbg-check:$1 = {1, 2, 3} +// gdbr-check:$1 = [1, 2, 3] // gdb-command:print vec::VECT -// gdb-check:$2 = {4, 5, 6} +// gdbg-check:$2 = {4, 5, 6} +// gdbr-check:$2 = [4, 5, 6] // === LLDB TESTS ================================================================================== From 6554fb0d8d5d794db7a7532a5edd16eb28777a48 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Sat, 29 Oct 2016 14:29:18 +0200 Subject: [PATCH 17/33] add gdb_native_rust config to compiletest --- src/tools/compiletest/src/common.rs | 3 ++ src/tools/compiletest/src/main.rs | 1 + src/tools/compiletest/src/runtest.rs | 48 ++++++++++++++++++---------- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 81cb927f26b02..b6b98d796e241 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -149,6 +149,9 @@ pub struct Config { // Version of GDB pub gdb_version: Option, + // Whether GDB has native rust support + pub gdb_native_rust: bool, + // Version of LLDB pub lldb_version: Option, diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index e6efd45cad186..c0557d8ff107d 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -172,6 +172,7 @@ pub fn parse_config(args: Vec ) -> Config { target: opt_str2(matches.opt_str("target")), host: opt_str2(matches.opt_str("host")), gdb_version: extract_gdb_version(matches.opt_str("gdb-version")), + gdb_native_rust: false, lldb_version: extract_lldb_version(matches.opt_str("lldb-version")), llvm_version: matches.opt_str("llvm-version"), android_cross_path: opt_path(matches, "android-cross-path"), diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index e10420bf291e7..f6cd56423fbc7 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -430,11 +430,23 @@ actual:\n\ } fn run_debuginfo_gdb_test_no_opt(&self) { + let prefixes = if self.config.gdb_native_rust { + // GDB with Rust + static PREFIXES: &'static [&'static str] = &["gdb", "gdbr"]; + println!("NOTE: compiletest thinks it is using GDB with native rust support"); + PREFIXES + } else { + // Generic GDB + static PREFIXES: &'static [&'static str] = &["gdb", "gdbg"]; + println!("NOTE: compiletest thinks it is using GDB without native rust support"); + PREFIXES + }; + let DebuggerCommands { commands, check_lines, breakpoint_lines - } = self.parse_debugger_commands("gdb"); + } = self.parse_debugger_commands(prefixes); let mut cmds = commands.join("\n"); // compile test file (it should have 'compile-flags:-g' in the header) @@ -731,7 +743,7 @@ actual:\n\ check_lines, breakpoint_lines, .. - } = self.parse_debugger_commands("lldb"); + } = self.parse_debugger_commands(&["lldb"]); // Write debugger script: // We don't want to hang when calling `quit` while the process is still running @@ -826,9 +838,11 @@ actual:\n\ } } - fn parse_debugger_commands(&self, debugger_prefix: &str) -> DebuggerCommands { - let command_directive = format!("{}-command", debugger_prefix); - let check_directive = format!("{}-check", debugger_prefix); + fn parse_debugger_commands(&self, debugger_prefixes: &[&str]) -> DebuggerCommands { + let directives = debugger_prefixes.iter().map(|prefix| ( + format!("{}-command", prefix), + format!("{}-check", prefix), + )).collect::>(); let mut breakpoint_lines = vec!(); let mut commands = vec!(); @@ -842,17 +856,19 @@ actual:\n\ breakpoint_lines.push(counter); } - header::parse_name_value_directive( - &line, - &command_directive).map(|cmd| { - commands.push(cmd) - }); - - header::parse_name_value_directive( - &line, - &check_directive).map(|cmd| { - check_lines.push(cmd) - }); + for &(ref command_directive, ref check_directive) in &directives { + header::parse_name_value_directive( + &line, + &command_directive).map(|cmd| { + commands.push(cmd) + }); + + header::parse_name_value_directive( + &line, + &check_directive).map(|cmd| { + check_lines.push(cmd) + }); + } } Err(e) => { self.fatal(&format!("Error while parsing debugger commands: {}", e)) From dce460028e9c21ebadb28f6744d4b10bf0e8d501 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Sat, 29 Oct 2016 20:11:53 +0200 Subject: [PATCH 18/33] detect gdb version & rust support in compiletest --- configure | 7 -- mk/tests.mk | 2 +- src/bootstrap/check.rs | 4 +- src/bootstrap/config.rs | 6 + src/bootstrap/config.toml.example | 3 + src/bootstrap/lib.rs | 2 - src/bootstrap/sanity.rs | 7 +- src/tools/compiletest/src/common.rs | 7 +- src/tools/compiletest/src/header.rs | 23 +--- src/tools/compiletest/src/main.rs | 176 +++++++++++++++++++++------ src/tools/compiletest/src/runtest.rs | 32 ++--- 11 files changed, 180 insertions(+), 89 deletions(-) diff --git a/configure b/configure index 2bc8c72e3ea1c..dab44c4a82992 100755 --- a/configure +++ b/configure @@ -862,13 +862,6 @@ then fi fi -if [ -n "$CFG_GDB" ] -then - # Store GDB's version - CFG_GDB_VERSION=$($CFG_GDB --version 2>/dev/null | head -1) - putvar CFG_GDB_VERSION -fi - if [ -n "$CFG_LLDB" ] then # Store LLDB's version diff --git a/mk/tests.mk b/mk/tests.mk index 1957c989eb0d4..f3d8f0387bbd6 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -648,7 +648,7 @@ CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3) = \ --host $(3) \ --docck-python $$(CFG_PYTHON) \ --lldb-python $$(CFG_LLDB_PYTHON) \ - --gdb-version="$(CFG_GDB_VERSION)" \ + --gdb="$(CFG_GDB)" \ --lldb-version="$(CFG_LLDB_VERSION)" \ --llvm-version="$$(LLVM_VERSION_$(3))" \ --android-cross-path=$(CFG_ARM_LINUX_ANDROIDEABI_NDK) \ diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index af76a49fed045..50a2337b30783 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -168,8 +168,8 @@ pub fn compiletest(build: &Build, cmd.arg("--lldb-python").arg(python_default); } - if let Some(ref vers) = build.gdb_version { - cmd.arg("--gdb-version").arg(vers); + if let Some(ref gdb) = build.config.gdb { + cmd.arg("--gdb").arg(gdb); } if let Some(ref vers) = build.lldb_version { cmd.arg("--lldb-version").arg(vers); diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 8c0ad1ccf825f..0948a7c130e5f 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -85,6 +85,7 @@ pub struct Config { pub mandir: Option, pub codegen_tests: bool, pub nodejs: Option, + pub gdb: Option, } /// Per-target configuration stored in the global configuration structure. @@ -122,6 +123,7 @@ struct Build { compiler_docs: Option, docs: Option, submodules: Option, + gdb: Option, } /// TOML representation of how the LLVM build is configured. @@ -226,6 +228,7 @@ impl Config { } config.rustc = build.rustc.map(PathBuf::from); config.cargo = build.cargo.map(PathBuf::from); + config.gdb = build.gdb.map(PathBuf::from); set(&mut config.compiler_docs, build.compiler_docs); set(&mut config.docs, build.docs); set(&mut config.submodules, build.submodules); @@ -392,6 +395,9 @@ impl Config { "CFG_DEFAULT_LINKER" if value.len() > 0 => { self.rustc_default_linker = Some(value.to_string()); } + "CFG_GDB" if value.len() > 0 => { + self.gdb = Some(PathBuf::from(value)); + } "CFG_RELEASE_CHANNEL" => { self.channel = value.to_string(); } diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example index b4730c003d646..1289cdba59577 100644 --- a/src/bootstrap/config.toml.example +++ b/src/bootstrap/config.toml.example @@ -79,6 +79,9 @@ # Indicate whether submodules are managed and updated automatically. #submodules = true +# The path to (or name of) the GDB executable to use +#gdb = "gdb" + # ============================================================================= # Options for compiling Rust code itself # ============================================================================= diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 7c5a0c7373f88..e99e088bffe36 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -123,7 +123,6 @@ pub struct Build { bootstrap_key_stage0: String, // Probed tools at runtime - gdb_version: Option, lldb_version: Option, lldb_python_dir: Option, @@ -196,7 +195,6 @@ impl Build { package_vers: String::new(), cc: HashMap::new(), cxx: HashMap::new(), - gdb_version: None, lldb_version: None, lldb_python_dir: None, } diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 969cd70fd57eb..cc1b7136d475f 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -92,6 +92,12 @@ pub fn check(build: &mut Build) { need_cmd(s.as_ref()); } + if let Some(ref gdb) = build.config.gdb { + need_cmd(gdb.as_ref()); + } else { + build.config.gdb = have_cmd("gdb".as_ref()); + } + // We're gonna build some custom C code here and there, host triples // also build some C++ shims for LLVM so we need a C++ compiler. for target in build.config.target.iter() { @@ -198,7 +204,6 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake .to_string() }) }; - build.gdb_version = run(Command::new("gdb").arg("--version")).ok(); build.lldb_version = run(Command::new("lldb").arg("--version")).ok(); if build.lldb_version.is_some() { build.lldb_python_dir = run(Command::new("lldb").arg("-P")).ok(); diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index b6b98d796e241..34f3837d8bbb0 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -146,8 +146,11 @@ pub struct Config { // Host triple for the compiler being invoked pub host: String, - // Version of GDB - pub gdb_version: Option, + // Path to / name of the GDB executable + pub gdb: Option, + + // Version of GDB, encoded as ((major * 1000) + minor) * 1000 + patch + pub gdb_version: Option, // Whether GDB has native rust support pub gdb_native_rust: bool, diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 503a851676925..e57c9949b1c57 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -18,6 +18,8 @@ use common::Config; use common; use util; +use extract_gdb_version; + /// Properties which must be known very early, before actually running /// the test. pub struct EarlyProps { @@ -75,7 +77,7 @@ impl EarlyProps { return true; } - if let Some(ref actual_version) = config.gdb_version { + if let Some(actual_version) = config.gdb_version { if line.contains("min-gdb-version") { let min_version = line.trim() .split(' ') @@ -83,7 +85,7 @@ impl EarlyProps { .expect("Malformed GDB version directive"); // Ignore if actual version is smaller the minimum required // version - gdb_version_to_int(actual_version) < gdb_version_to_int(min_version) + actual_version < extract_gdb_version(min_version).unwrap() } else { false } @@ -464,23 +466,6 @@ pub fn parse_name_value_directive(line: &str, directive: &str) -> Option } } -pub fn gdb_version_to_int(version_string: &str) -> isize { - let error_string = format!("Encountered GDB version string with unexpected format: {}", - version_string); - let error_string = error_string; - - let components: Vec<&str> = version_string.trim().split('.').collect(); - - if components.len() != 2 { - panic!("{}", error_string); - } - - let major: isize = components[0].parse().ok().expect(&error_string); - let minor: isize = components[1].parse().ok().expect(&error_string); - - return major * 1000 + minor; -} - pub fn lldb_version_to_int(version_string: &str) -> isize { let error_string = format!("Encountered LLDB version string with unexpected format: {}", version_string); diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index c0557d8ff107d..d6e64cc1752a9 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -12,6 +12,7 @@ #![feature(box_syntax)] #![feature(rustc_private)] +#![feature(static_in_const)] #![feature(test)] #![feature(libc)] @@ -35,6 +36,7 @@ use std::ffi::OsString; use std::fs; use std::io; use std::path::{Path, PathBuf}; +use std::process::Command; use getopts::{optopt, optflag, reqopt}; use common::Config; use common::{Pretty, DebugInfoGdb, DebugInfoLldb, Mode}; @@ -98,7 +100,7 @@ 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("", "gdb-version", "the version of GDB used", "VERSION STRING"), + optopt("", "gdb", "path to GDB to use for GDB debuginfo tests", "PATH"), optopt("", "lldb-version", "the version of LLDB used", "VERSION STRING"), optopt("", "llvm-version", "the version of LLVM used", "VERSION STRING"), optopt("", "android-cross-path", "Android NDK standalone path", "PATH"), @@ -149,6 +151,8 @@ pub fn parse_config(args: Vec ) -> Config { } } + let (gdb, gdb_version, gdb_native_rust) = analyze_gdb(matches.opt_str("gdb")); + Config { compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")), run_lib_path: make_absolute(opt_path(matches, "run-lib-path")), @@ -171,8 +175,9 @@ pub fn parse_config(args: Vec ) -> Config { target_rustcflags: matches.opt_str("target-rustcflags"), target: opt_str2(matches.opt_str("target")), host: opt_str2(matches.opt_str("host")), - gdb_version: extract_gdb_version(matches.opt_str("gdb-version")), - gdb_native_rust: false, + gdb: gdb, + gdb_version: gdb_version, + gdb_native_rust: gdb_native_rust, lldb_version: extract_lldb_version(matches.opt_str("lldb-version")), llvm_version: matches.opt_str("llvm-version"), android_cross_path: opt_path(matches, "android-cross-path"), @@ -471,44 +476,96 @@ pub fn make_test_closure(config: &Config, testpaths: &TestPaths) -> test::TestFn })) } -fn extract_gdb_version(full_version_line: Option) -> Option { - match full_version_line { - Some(ref full_version_line) - if !full_version_line.trim().is_empty() => { - let full_version_line = full_version_line.trim(); +/// Returns (Path to GDB, GDB Version, GDB has Rust Support) +fn analyze_gdb(gdb: Option) -> (Option, Option, bool) { + #[cfg(not(windows))] + const GDB_FALLBACK: &str = "gdb"; + #[cfg(windows)] + const GDB_FALLBACK: &str = "gdb.exe"; - // used to be a regex "(^|[^0-9])([0-9]\.[0-9]+)" - for (pos, c) in full_version_line.char_indices() { - if !c.is_digit(10) { - continue - } - if pos + 2 >= full_version_line.len() { - continue - } - if full_version_line[pos + 1..].chars().next().unwrap() != '.' { - continue - } - if !full_version_line[pos + 2..].chars().next().unwrap().is_digit(10) { - continue - } - if pos > 0 && full_version_line[..pos].chars().next_back() - .unwrap().is_digit(10) { - continue - } - let mut end = pos + 3; - while end < full_version_line.len() && - full_version_line[end..].chars().next() - .unwrap().is_digit(10) { - end += 1; - } - return Some(full_version_line[pos..end].to_owned()); - } - println!("Could not extract GDB version from line '{}'", - full_version_line); - None - }, - _ => None + const MIN_GDB_WITH_RUST: u32 = 7011010; + + let gdb = match gdb { + None => GDB_FALLBACK, + Some(ref s) if s.is_empty() => GDB_FALLBACK, // may be empty if configure found no gdb + Some(ref s) => s, + }; + + let version_line = Command::new(gdb).arg("--version").output().map(|output| { + String::from_utf8_lossy(&output.stdout).lines().next().unwrap().to_string() + }).ok(); + + let version = match version_line { + Some(line) => extract_gdb_version(&line), + None => return (None, None, false), + }; + + let gdb_native_rust = version.map_or(false, |v| v >= MIN_GDB_WITH_RUST); + + return (Some(gdb.to_owned()), version, gdb_native_rust); +} + +fn extract_gdb_version(full_version_line: &str) -> Option { + let full_version_line = full_version_line.trim(); + + // GDB versions look like this: "major.minor.patch?.yyyymmdd?", with both + // of the ? sections being optional + + // We will parse up to 3 digits for minor and patch, ignoring the date + // We limit major to 1 digit, otherwise, on openSUSE, we parse the openSUSE version + + // don't start parsing in the middle of a number + let mut prev_was_digit = false; + for (pos, c) in full_version_line.char_indices() { + if prev_was_digit || !c.is_digit(10) { + prev_was_digit = c.is_digit(10); + continue + } + + prev_was_digit = true; + + let line = &full_version_line[pos..]; + + let next_split = match line.find(|c: char| !c.is_digit(10)) { + Some(idx) => idx, + None => continue, // no minor version + }; + + if line.as_bytes()[next_split] != b'.' { + continue; // no minor version + } + + let major = &line[..next_split]; + let line = &line[next_split + 1..]; + + let (minor, patch) = match line.find(|c: char| !c.is_digit(10)) { + Some(idx) => if line.as_bytes()[idx] == b'.' { + let patch = &line[idx + 1..]; + + let patch_len = patch.find(|c: char| !c.is_digit(10)).unwrap_or(patch.len()); + let patch = &patch[..patch_len]; + let patch = if patch_len > 3 || patch_len == 0 { None } else { Some(patch) }; + + (&line[..idx], patch) + } else { + (&line[..idx], None) + }, + None => (line, None), + }; + + if major.len() != 1 || minor.is_empty() { + continue; + } + + let major: u32 = major.parse().unwrap(); + let minor: u32 = minor.parse().unwrap(); + let patch: u32 = patch.unwrap_or("0").parse().unwrap(); + + return Some(((major * 1000) + minor) * 1000 + patch); } + + println!("Could not extract GDB version from line '{}'", full_version_line); + None } fn extract_lldb_version(full_version_line: Option) -> Option { @@ -554,3 +611,44 @@ fn extract_lldb_version(full_version_line: Option) -> Option { fn is_blacklisted_lldb_version(version: &str) -> bool { version == "350" } + +#[test] +fn test_extract_gdb_version() { + macro_rules! test { ($($expectation:tt: $input:tt,)*) => {{$( + assert_eq!(extract_gdb_version($input), Some($expectation)); + )*}}} + + test! { + 7000001: "GNU gdb (GDB) CentOS (7.0.1-45.el5.centos)", + + 7002000: "GNU gdb (GDB) Red Hat Enterprise Linux (7.2-90.el6)", + + 7004000: "GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04", + 7004001: "GNU gdb (GDB) 7.4.1-debian", + + 7006001: "GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-80.el7", + + 7007001: "GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1", + 7007001: "GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1", + 7007001: "GNU gdb (GDB) Fedora 7.7.1-21.fc20", + + 7008000: "GNU gdb (GDB; openSUSE 13.2) 7.8", + 7009001: "GNU gdb (GDB) Fedora 7.9.1-20.fc22", + 7010001: "GNU gdb (GDB) Fedora 7.10.1-31.fc23", + + 7011000: "GNU gdb (Ubuntu 7.11-0ubuntu1) 7.11", + 7011001: "GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1", + 7011001: "GNU gdb (Debian 7.11.1-2) 7.11.1", + 7011001: "GNU gdb (GDB) Fedora 7.11.1-86.fc24", + 7011001: "GNU gdb (GDB; openSUSE Leap 42.1) 7.11.1", + 7011001: "GNU gdb (GDB; openSUSE Tumbleweed) 7.11.1", + + 7011090: "7.11.90", + 7011090: "GNU gdb (Ubuntu 7.11.90.20161005-0ubuntu1) 7.11.90.20161005-git", + + 7012000: "7.12", + 7012000: "GNU gdb (GDB) 7.12", + 7012000: "GNU gdb (GDB) 7.12.20161027-git", + 7012050: "GNU gdb (GDB) 7.12.50.20161027-git", + } +} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index f6cd56423fbc7..3c6903ac21d51 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -32,6 +32,8 @@ use std::path::{Path, PathBuf}; use std::process::{Command, Output, ExitStatus}; use std::str; +use extract_gdb_version; + pub fn run(config: Config, testpaths: &TestPaths) { match &*config.target { @@ -44,6 +46,10 @@ pub fn run(config: Config, testpaths: &TestPaths) { _=> { } } + if config.mode == DebugInfoGdb && config.gdb.is_none() { + panic!("gdb not available but debuginfo gdb debuginfo test requested"); + } + if config.verbose { // We're going to be dumping a lot of info. Start on a new line. print!("\n\n"); @@ -598,19 +604,18 @@ actual:\n\ script_str.push_str("show version\n"); match self.config.gdb_version { - Some(ref version) => { + Some(version) => { println!("NOTE: compiletest thinks it is using GDB version {}", version); - if header::gdb_version_to_int(version) > - header::gdb_version_to_int("7.4") { - // Add the directory containing the pretty printers to - // GDB's script auto loading safe path - script_str.push_str( - &format!("add-auto-load-safe-path {}\n", - rust_pp_module_abs_path.replace(r"\", r"\\")) - ); - } + if version > extract_gdb_version("7.4").unwrap() { + // Add the directory containing the pretty printers to + // GDB's script auto loading safe path + script_str.push_str( + &format!("add-auto-load-safe-path {}\n", + rust_pp_module_abs_path.replace(r"\", r"\\")) + ); + } } _ => { println!("NOTE: compiletest does not know which version of \ @@ -645,11 +650,6 @@ actual:\n\ debug!("script_str = {}", script_str); self.dump_output_file(&script_str, "debugger.script"); - // run debugger script with gdb - fn debugger() -> &'static str { - if cfg!(windows) {"gdb.exe"} else {"gdb"} - } - let debugger_script = self.make_out_name("debugger.script"); // FIXME (#9639): This needs to handle non-utf8 paths @@ -660,7 +660,7 @@ actual:\n\ format!("-command={}", debugger_script.to_str().unwrap())); let proc_args = ProcArgs { - prog: debugger().to_owned(), + prog: self.config.gdb.as_ref().unwrap().to_owned(), args: debugger_opts, }; From 5cb5c85152e2a8b7f3480a46f4619b572f162056 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Mon, 31 Oct 2016 21:00:32 +0100 Subject: [PATCH 19/33] rustbuild+configure: improve bin/exe joining --- src/bootstrap/config.rs | 8 +++++--- src/bootstrap/util.rs | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 0948a7c130e5f..9f6e91c85661c 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -23,6 +23,7 @@ use std::process; use num_cpus; use rustc_serialize::Decodable; use toml::{Parser, Decoder, Value}; +use util::push_exe_path; /// Global configuration for the entire build and/or bootstrap. /// @@ -417,7 +418,7 @@ impl Config { let target = self.target_config.entry(self.build.clone()) .or_insert(Target::default()); let root = PathBuf::from(value); - target.llvm_config = Some(root.join("bin/llvm-config")); + target.llvm_config = Some(push_exe_path(root, &["bin", "llvm-config"])); } "CFG_JEMALLOC_ROOT" if value.len() > 0 => { let target = self.target_config.entry(self.build.clone()) @@ -449,8 +450,9 @@ impl Config { target.ndk = Some(PathBuf::from(value)); } "CFG_LOCAL_RUST_ROOT" if value.len() > 0 => { - self.rustc = Some(PathBuf::from(value).join("bin/rustc")); - self.cargo = Some(PathBuf::from(value).join("bin/cargo")); + let path = PathBuf::from(value); + self.rustc = Some(push_exe_path(path.clone(), &["bin", "rustc"])); + self.cargo = Some(push_exe_path(path, &["bin", "cargo"])); } _ => {} } diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 6c0a32a54d919..84ba03b2502e2 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -172,3 +172,21 @@ pub fn dylib_path() -> Vec { env::split_paths(&env::var_os(dylib_path_var()).unwrap_or(OsString::new())) .collect() } + +/// `push` all components to `buf`. On windows, append `.exe` to the last component. +pub fn push_exe_path(mut buf: PathBuf, components: &[&str]) -> PathBuf { + let (&file, components) = components.split_last().expect("at least one component required"); + let mut file = file.to_owned(); + + if cfg!(windows) { + file.push_str(".exe"); + } + + for c in components { + buf.push(c); + } + + buf.push(file); + + buf +} From f7107f32c2fabef7a5b33c514d9f0310c96492d0 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Mon, 31 Oct 2016 21:06:27 +0100 Subject: [PATCH 20/33] rustbuild+configure: convert unix style paths on windows --- src/bootstrap/config.rs | 51 ++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 9f6e91c85661c..2b1d8e67dd8f2 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -358,37 +358,37 @@ impl Config { .collect(); } "CFG_MUSL_ROOT" if value.len() > 0 => { - self.musl_root = Some(PathBuf::from(value)); + self.musl_root = Some(parse_configure_path(value)); } "CFG_MUSL_ROOT_X86_64" if value.len() > 0 => { let target = "x86_64-unknown-linux-musl".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.musl_root = Some(PathBuf::from(value)); + target.musl_root = Some(parse_configure_path(value)); } "CFG_MUSL_ROOT_I686" if value.len() > 0 => { let target = "i686-unknown-linux-musl".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.musl_root = Some(PathBuf::from(value)); + target.musl_root = Some(parse_configure_path(value)); } "CFG_MUSL_ROOT_ARM" if value.len() > 0 => { let target = "arm-unknown-linux-musleabi".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.musl_root = Some(PathBuf::from(value)); + target.musl_root = Some(parse_configure_path(value)); } "CFG_MUSL_ROOT_ARMHF" if value.len() > 0 => { let target = "arm-unknown-linux-musleabihf".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.musl_root = Some(PathBuf::from(value)); + target.musl_root = Some(parse_configure_path(value)); } "CFG_MUSL_ROOT_ARMV7" if value.len() > 0 => { let target = "armv7-unknown-linux-musleabihf".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.musl_root = Some(PathBuf::from(value)); + target.musl_root = Some(parse_configure_path(value)); } "CFG_DEFAULT_AR" if value.len() > 0 => { self.rustc_default_ar = Some(value.to_string()); @@ -397,7 +397,7 @@ impl Config { self.rustc_default_linker = Some(value.to_string()); } "CFG_GDB" if value.len() > 0 => { - self.gdb = Some(PathBuf::from(value)); + self.gdb = Some(parse_configure_path(value)); } "CFG_RELEASE_CHANNEL" => { self.channel = value.to_string(); @@ -417,40 +417,40 @@ impl Config { "CFG_LLVM_ROOT" if value.len() > 0 => { let target = self.target_config.entry(self.build.clone()) .or_insert(Target::default()); - let root = PathBuf::from(value); + let root = parse_configure_path(value); target.llvm_config = Some(push_exe_path(root, &["bin", "llvm-config"])); } "CFG_JEMALLOC_ROOT" if value.len() > 0 => { let target = self.target_config.entry(self.build.clone()) .or_insert(Target::default()); - target.jemalloc = Some(PathBuf::from(value)); + target.jemalloc = Some(parse_configure_path(value)); } "CFG_ARM_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => { let target = "arm-linux-androideabi".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.ndk = Some(PathBuf::from(value)); + target.ndk = Some(parse_configure_path(value)); } "CFG_ARMV7_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => { let target = "armv7-linux-androideabi".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.ndk = Some(PathBuf::from(value)); + target.ndk = Some(parse_configure_path(value)); } "CFG_I686_LINUX_ANDROID_NDK" if value.len() > 0 => { let target = "i686-linux-android".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.ndk = Some(PathBuf::from(value)); + target.ndk = Some(parse_configure_path(value)); } "CFG_AARCH64_LINUX_ANDROID_NDK" if value.len() > 0 => { let target = "aarch64-linux-android".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.ndk = Some(PathBuf::from(value)); + target.ndk = Some(parse_configure_path(value)); } "CFG_LOCAL_RUST_ROOT" if value.len() > 0 => { - let path = PathBuf::from(value); + let path = parse_configure_path(value); self.rustc = Some(push_exe_path(path.clone(), &["bin", "rustc"])); self.cargo = Some(push_exe_path(path, &["bin", "cargo"])); } @@ -460,6 +460,29 @@ impl Config { } } +#[cfg(not(windows))] +fn parse_configure_path(path: &str) -> PathBuf { + path.into() +} + +#[cfg(windows)] +fn parse_configure_path(path: &str) -> PathBuf { + // on windows, configure produces unix style paths e.g. /c/some/path but we + // only want real windows paths + + use build_helper; + + // '/' is invalid in windows paths, so we can detect unix paths by the presence of it + if !path.contains('/') { + return path.into(); + } + + let win_path = build_helper::output(Command::new("cygpath").arg("-w").arg(path)); + let win_path = win_path.trim(); + + win_path.into() +} + fn set(field: &mut T, val: Option) { if let Some(v) = val { *field = v; From c8578dbb53e195d5a87dd4724b7d56395728dd65 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Sat, 29 Oct 2016 01:27:12 +0300 Subject: [PATCH 21/33] rustc: unify and simplify managing associated items. --- src/librustc/dep_graph/dep_node.rs | 12 +- src/librustc/middle/cstore.rs | 14 +- src/librustc/middle/dead.rs | 5 +- src/librustc/middle/expr_use_visitor.rs | 4 +- src/librustc/middle/stability.rs | 20 +- src/librustc/traits/error_reporting.rs | 14 +- src/librustc/traits/mod.rs | 20 +- src/librustc/traits/object_safety.rs | 48 +-- src/librustc/traits/project.rs | 26 +- src/librustc/traits/specialize/mod.rs | 3 +- .../traits/specialize/specialization_graph.rs | 142 +------ src/librustc/traits/util.rs | 16 +- src/librustc/ty/context.rs | 22 +- src/librustc/ty/maps.rs | 8 +- src/librustc/ty/mod.rs | 396 +++++++----------- src/librustc/util/ppaux.rs | 26 -- src/librustc_const_eval/eval.rs | 9 +- src/librustc_lint/bad_style.rs | 4 +- src/librustc_lint/builtin.rs | 12 +- src/librustc_metadata/cstore_impl.rs | 12 +- src/librustc_metadata/decoder.rs | 45 +- src/librustc_metadata/encoder.rs | 84 ++-- src/librustc_metadata/schema.rs | 10 +- src/librustc_mir/hair/cx/mod.rs | 22 +- src/librustc_passes/consts.rs | 4 +- src/librustc_privacy/lib.rs | 2 +- src/librustc_resolve/build_reduced_graph.rs | 2 +- src/librustc_save_analysis/dump_visitor.rs | 24 +- src/librustc_save_analysis/lib.rs | 57 +-- src/librustc_trans/collector.rs | 21 +- src/librustc_trans/mir/constant.rs | 9 +- src/librustc_typeck/astconv.rs | 234 +++++------ src/librustc_typeck/check/compare_method.rs | 136 +++--- src/librustc_typeck/check/dropck.rs | 6 +- src/librustc_typeck/check/method/confirm.rs | 90 ++-- src/librustc_typeck/check/method/mod.rs | 135 +++--- src/librustc_typeck/check/method/probe.rs | 109 ++--- src/librustc_typeck/check/method/suggest.rs | 31 +- src/librustc_typeck/check/mod.rs | 148 ++----- src/librustc_typeck/check/wfcheck.rs | 113 ++--- src/librustc_typeck/coherence/mod.rs | 24 +- src/librustc_typeck/coherence/overlap.rs | 30 +- src/librustc_typeck/collect.rs | 237 +++-------- src/librustdoc/clean/inline.rs | 51 +-- src/librustdoc/clean/mod.rs | 224 +++++----- 45 files changed, 995 insertions(+), 1666 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index e99ffa95ed63c..351feaba0346a 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -103,11 +103,11 @@ pub enum DepNode { // nodes. Often we map multiple tables to the same node if there // is no point in distinguishing them (e.g., both the type and // predicates for an item wind up in `ItemSignature`). - ImplOrTraitItems(D), + AssociatedItems(D), ItemSignature(D), FieldTy(D), SizedConstraint(D), - ImplOrTraitItemDefIds(D), + AssociatedItemDefIds(D), InherentImpls(D), // The set of impls for a given trait. Ultimately, it would be @@ -153,10 +153,10 @@ impl DepNode { TransCrateItem, TypeckItemType, TypeckItemBody, - ImplOrTraitItems, + AssociatedItems, ItemSignature, FieldTy, - ImplOrTraitItemDefIds, + AssociatedItemDefIds, InherentImpls, TraitImpls, ReprHints, @@ -219,11 +219,11 @@ impl DepNode { RvalueCheck(ref d) => op(d).map(RvalueCheck), TransCrateItem(ref d) => op(d).map(TransCrateItem), TransInlinedItem(ref d) => op(d).map(TransInlinedItem), - ImplOrTraitItems(ref d) => op(d).map(ImplOrTraitItems), + AssociatedItems(ref d) => op(d).map(AssociatedItems), ItemSignature(ref d) => op(d).map(ItemSignature), FieldTy(ref d) => op(d).map(FieldTy), SizedConstraint(ref d) => op(d).map(SizedConstraint), - ImplOrTraitItemDefIds(ref d) => op(d).map(ImplOrTraitItemDefIds), + AssociatedItemDefIds(ref d) => op(d).map(AssociatedItemDefIds), InherentImpls(ref d) => op(d).map(InherentImpls), TraitImpls(ref d) => op(d).map(TraitImpls), TraitItems(ref d) => op(d).map(TraitItems), diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 59a5147ed1c16..a1f226ab11d80 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -147,7 +147,7 @@ pub trait CrateStore<'tcx> { fn implementations_of_trait(&self, filter: Option) -> Vec; // impl info - fn impl_or_trait_items(&self, def_id: DefId) -> Vec; + fn associated_item_def_ids(&self, def_id: DefId) -> Vec; fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Option>; fn impl_polarity(&self, def: DefId) -> hir::ImplPolarity; @@ -157,8 +157,8 @@ pub trait CrateStore<'tcx> { // trait/impl-item info fn trait_of_item(&self, def_id: DefId) -> Option; - fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Option>; + fn associated_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) + -> Option; // flags fn is_const_fn(&self, did: DefId) -> bool; @@ -311,8 +311,8 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { } // impl info - fn impl_or_trait_items(&self, def_id: DefId) -> Vec - { bug!("impl_or_trait_items") } + fn associated_item_def_ids(&self, def_id: DefId) -> Vec + { bug!("associated_items") } fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Option> { bug!("impl_trait_ref") } fn impl_polarity(&self, def: DefId) -> hir::ImplPolarity { bug!("impl_polarity") } @@ -323,8 +323,8 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { // trait/impl-item info fn trait_of_item(&self, def_id: DefId) -> Option { bug!("trait_of_item") } - fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Option> { bug!("impl_or_trait_item") } + fn associated_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) + -> Option { bug!("associated_item") } // flags fn is_const_fn(&self, did: DefId) -> bool { bug!("is_const_fn") } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index dc634b08784a4..5d88561ed0859 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -471,11 +471,10 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> { // This is done to handle the case where, for example, the static // method of a private type is used, but the type itself is never // called directly. - let impl_items = self.tcx.impl_or_trait_item_def_ids.borrow(); if let Some(impl_list) = self.tcx.inherent_impls.borrow().get(&self.tcx.map.local_def_id(id)) { - for impl_did in impl_list.iter() { - for &item_did in &impl_items[impl_did][..] { + for &impl_did in impl_list.iter() { + for &item_did in &self.tcx.associated_item_def_ids(impl_did)[..] { if let Some(item_node_id) = self.tcx.map.as_local_node_id(item_did) { if self.live_symbols.contains(&item_node_id) { return true; diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index c37b6df369dfc..b7fa32a7f5e45 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -227,8 +227,8 @@ impl OverloadedCallType { } fn from_method_id(tcx: TyCtxt, method_id: DefId) -> OverloadedCallType { - let method = tcx.impl_or_trait_item(method_id); - OverloadedCallType::from_trait_id(tcx, method.container().id()) + let method = tcx.associated_item(method_id); + OverloadedCallType::from_trait_id(tcx, method.container.id()) } } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 5192575972b02..65e389daa1fc8 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -529,14 +529,11 @@ pub fn check_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // items. hir::ItemImpl(.., Some(ref t), _, ref impl_items) => { let trait_did = tcx.expect_def(t.ref_id).def_id(); - let trait_items = tcx.trait_items(trait_did); - for impl_item in impl_items { - let item = trait_items.iter().find(|item| { - item.name() == impl_item.name - }).unwrap(); + let item = tcx.associated_items(trait_did) + .find(|item| item.name == impl_item.name).unwrap(); if warn_about_defns { - maybe_do_stability_check(tcx, item.def_id(), impl_item.span, cb); + maybe_do_stability_check(tcx, item.def_id, impl_item.span, cb); } } } @@ -685,15 +682,8 @@ fn is_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span) -> bool { } fn is_staged_api<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> bool { - match tcx.trait_item_of_item(id) { - Some(trait_method_id) if trait_method_id != id => { - is_staged_api(tcx, trait_method_id) - } - _ => { - *tcx.stability.borrow_mut().staged_api.entry(id.krate).or_insert_with( - || tcx.sess.cstore.is_staged_api(id.krate)) - } - } + *tcx.stability.borrow_mut().staged_api.entry(id.krate).or_insert_with( + || tcx.sess.cstore.is_staged_api(id.krate)) } impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 9435f96c08a22..a8ab4e7bc33a9 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -617,25 +617,23 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { in the supertrait listing" } - ObjectSafetyViolation::Method(method, + ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod) => { - buf = format!("method `{}` has no receiver", - method.name); + buf = format!("method `{}` has no receiver", name); &buf } - ObjectSafetyViolation::Method(method, + ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf) => { buf = format!("method `{}` references the `Self` type \ in its arguments or return type", - method.name); + name); &buf } - ObjectSafetyViolation::Method(method, + ObjectSafetyViolation::Method(name, MethodViolationCode::Generic) => { - buf = format!("method `{}` has generic type parameters", - method.name); + buf = format!("method `{}` has generic type parameters", name); &buf } }; diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 7ba10d9c0a58e..69f4137eb46c0 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -569,18 +569,14 @@ pub fn get_vtable_methods<'a, 'tcx>( supertraits(tcx, trait_ref).flat_map(move |trait_ref| { tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id()); - let trait_item_def_ids = tcx.impl_or_trait_items(trait_ref.def_id()); - let trait_methods = (0..trait_item_def_ids.len()).filter_map(move |i| { - match tcx.impl_or_trait_item(trait_item_def_ids[i]) { - ty::MethodTraitItem(m) => Some(m), - _ => None - } - }); + let trait_methods = tcx.associated_items(trait_ref.def_id()) + .filter(|item| item.kind == ty::AssociatedKind::Method); // Now list each method's DefId and Substs (for within its trait). // If the method can never be called from this object, produce None. trait_methods.map(move |trait_method| { debug!("get_vtable_methods: trait_method={:?}", trait_method); + let def_id = trait_method.def_id; // Some methods cannot be called on an object; skip those. if !tcx.is_vtable_safe_method(trait_ref.def_id(), &trait_method) { @@ -590,21 +586,21 @@ pub fn get_vtable_methods<'a, 'tcx>( // the method may have some early-bound lifetimes, add // regions for those - let substs = Substs::for_item(tcx, trait_method.def_id, - |_, _| tcx.mk_region(ty::ReErased), - |def, _| trait_ref.substs().type_for_def(def)); + let substs = Substs::for_item(tcx, def_id, + |_, _| tcx.mk_region(ty::ReErased), + |def, _| trait_ref.substs().type_for_def(def)); // It's possible that the method relies on where clauses that // do not hold for this particular set of type parameters. // Note that this method could then never be called, so we // do not want to try and trans it, in that case (see #23435). - let predicates = trait_method.predicates.instantiate_own(tcx, substs); + let predicates = tcx.lookup_predicates(def_id).instantiate_own(tcx, substs); if !normalize_and_test_predicates(tcx, predicates.predicates) { debug!("get_vtable_methods: predicates do not hold"); return None; } - Some((trait_method.def_id, substs)) + Some((def_id, substs)) }) }) } diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 5f7b71518291a..c783bd561bb1a 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -22,11 +22,10 @@ use super::elaborate_predicates; use hir::def_id::DefId; use traits; use ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; -use std::rc::Rc; use syntax::ast; #[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub enum ObjectSafetyViolation<'tcx> { +pub enum ObjectSafetyViolation { /// Self : Sized declared on the trait SizedSelf, @@ -35,7 +34,7 @@ pub enum ObjectSafetyViolation<'tcx> { SupertraitSelf, /// Method has something illegal - Method(Rc>, MethodViolationCode), + Method(ast::Name, MethodViolationCode), } /// Reasons a method might not be object-safe. @@ -77,7 +76,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// because `object_safety_violations` can't be used during /// type collection. pub fn astconv_object_safety_violations(self, trait_def_id: DefId) - -> Vec> + -> Vec { let mut violations = vec![]; @@ -93,7 +92,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn object_safety_violations(self, trait_def_id: DefId) - -> Vec> + -> Vec { traits::supertrait_def_ids(self, trait_def_id) .flat_map(|def_id| self.object_safety_violations_for_trait(def_id)) @@ -101,21 +100,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } fn object_safety_violations_for_trait(self, trait_def_id: DefId) - -> Vec> + -> Vec { // Check methods for violations. - let mut violations: Vec<_> = - self.trait_items(trait_def_id).iter() + let mut violations: Vec<_> = self.associated_items(trait_def_id) + .filter(|item| item.kind == ty::AssociatedKind::Method) .filter_map(|item| { - match *item { - ty::MethodTraitItem(ref m) => { - self.object_safety_violation_for_method(trait_def_id, &m) - .map(|code| ObjectSafetyViolation::Method(m.clone(), code)) - } - _ => None, - } - }) - .collect(); + self.object_safety_violation_for_method(trait_def_id, &item) + .map(|code| ObjectSafetyViolation::Method(item.name, code)) + }).collect(); // Check the trait itself. if self.trait_has_sized_self(trait_def_id) { @@ -198,7 +191,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Returns `Some(_)` if this method makes the containing trait not object safe. fn object_safety_violation_for_method(self, trait_def_id: DefId, - method: &ty::Method<'gcx>) + method: &ty::AssociatedItem) -> Option { // Any method that has a `Self : Sized` requisite is otherwise @@ -216,7 +209,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// otherwise ensure that they cannot be used when `Self=Trait`. pub fn is_vtable_safe_method(self, trait_def_id: DefId, - method: &ty::Method<'gcx>) + method: &ty::AssociatedItem) -> bool { // Any method that has a `Self : Sized` requisite can't be called. @@ -233,26 +226,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// `Self:Sized`. fn virtual_call_violation_for_method(self, trait_def_id: DefId, - method: &ty::Method<'tcx>) + method: &ty::AssociatedItem) -> Option { // The method's first parameter must be something that derefs (or // autorefs) to `&self`. For now, we only accept `self`, `&self` // and `Box`. - match method.explicit_self { - ty::ExplicitSelfCategory::Static => { - return Some(MethodViolationCode::StaticMethod); - } - - ty::ExplicitSelfCategory::ByValue | - ty::ExplicitSelfCategory::ByReference(..) | - ty::ExplicitSelfCategory::ByBox => { - } + if !method.method_has_self_argument { + return Some(MethodViolationCode::StaticMethod); } // The `Self` type is erased, so it should not appear in list of // arguments or return type apart from the receiver. - let ref sig = method.fty.sig; + let ref sig = self.lookup_item_type(method.def_id).ty.fn_sig(); for &input_ty in &sig.0.inputs[1..] { if self.contains_illegal_self_type_reference(trait_def_id, input_ty) { return Some(MethodViolationCode::ReferencesSelf); @@ -263,7 +249,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } // We can't monomorphize things like `fn foo(...)`. - if !method.generics.types.is_empty() { + if !self.lookup_generics(method.def_id).types.is_empty() { return Some(MethodViolationCode::Generic); } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index ce882c48377f7..b1ab61b09757e 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -33,8 +33,6 @@ use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt}; use ty::fold::{TypeFoldable, TypeFolder}; use util::common::FN_OUTPUT_NAME; -use std::rc::Rc; - /// Depending on the stage of compilation, we want projection to be /// more or less conservative. #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -945,7 +943,7 @@ fn assemble_candidates_from_impls<'cx, 'gcx, 'tcx>( // an error when we confirm the candidate // (which will ultimately lead to `normalize_to_error` // being invoked). - node_item.item.ty.is_some() + node_item.item.has_value } else { node_item.item.defaultness.is_default() }; @@ -1305,7 +1303,7 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>( match assoc_ty { Some(node_item) => { - let ty = node_item.item.ty.unwrap_or_else(|| { + let ty = if !node_item.item.has_value { // This means that the impl is missing a definition for the // associated type. This error will be reported by the type // checker method `check_impl_items_against_trait`, so here we @@ -1314,7 +1312,9 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>( node_item.item.name, obligation.predicate.trait_ref); tcx.types.err - }); + } else { + tcx.lookup_item_type(node_item.item.def_id).ty + }; let substs = translate_substs(selcx.infcx(), impl_def_id, substs, node_item.node); Progress { ty: ty.subst(tcx, substs), @@ -1339,27 +1339,25 @@ fn assoc_ty_def<'cx, 'gcx, 'tcx>( selcx: &SelectionContext<'cx, 'gcx, 'tcx>, impl_def_id: DefId, assoc_ty_name: ast::Name) - -> Option>>> + -> Option> { let trait_def_id = selcx.tcx().impl_trait_ref(impl_def_id).unwrap().def_id; if selcx.projection_mode() == Reveal::ExactMatch { let impl_node = specialization_graph::Node::Impl(impl_def_id); for item in impl_node.items(selcx.tcx()) { - if let ty::TypeTraitItem(assoc_ty) = item { - if assoc_ty.name == assoc_ty_name { - return Some(specialization_graph::NodeItem { - node: specialization_graph::Node::Impl(impl_def_id), - item: assoc_ty, - }); - } + if item.kind == ty::AssociatedKind::Type && item.name == assoc_ty_name { + return Some(specialization_graph::NodeItem { + node: specialization_graph::Node::Impl(impl_def_id), + item: item, + }); } } None } else { selcx.tcx().lookup_trait_def(trait_def_id) .ancestors(impl_def_id) - .type_defs(selcx.tcx(), assoc_ty_name) + .defs(selcx.tcx(), assoc_ty_name, ty::AssociatedKind::Type) .next() } } diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index e37425901c8c8..4bd8253e10de9 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -120,7 +120,8 @@ pub fn find_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap(); let trait_def = tcx.lookup_trait_def(trait_def_id); - match trait_def.ancestors(impl_data.impl_def_id).fn_defs(tcx, name).next() { + let ancestors = trait_def.ancestors(impl_data.impl_def_id); + match ancestors.defs(tcx, name, ty::AssociatedKind::Method).next() { Some(node_item) => { let substs = tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs); diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index 1374719ef49c4..bbcfc890f881d 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -8,13 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::rc::Rc; - use super::{OverlapError, specializes}; use hir::def_id::DefId; use traits::{self, Reveal}; -use ty::{self, TyCtxt, ImplOrTraitItem, TraitDef, TypeFoldable}; +use ty::{self, TyCtxt, TraitDef, TypeFoldable}; use ty::fast_reject::{self, SimplifiedType}; use syntax::ast::Name; use util::nodemap::{DefIdMap, FnvHashMap}; @@ -285,12 +283,10 @@ impl<'a, 'gcx, 'tcx> Node { } /// Iterate over the items defined directly by the given (impl or trait) node. - pub fn items(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> NodeItems<'a, 'gcx> { - NodeItems { - tcx: tcx.global_tcx(), - items: tcx.impl_or_trait_items(self.def_id()), - idx: 0, - } + #[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait. + pub fn items(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) + -> impl Iterator + 'a { + tcx.associated_items(self.def_id()) } pub fn def_id(&self) -> DefId { @@ -301,28 +297,6 @@ impl<'a, 'gcx, 'tcx> Node { } } -/// An iterator over the items defined within a trait or impl. -pub struct NodeItems<'a, 'tcx: 'a> { - tcx: TyCtxt<'a, 'tcx, 'tcx>, - items: Rc>, - idx: usize -} - -impl<'a, 'tcx> Iterator for NodeItems<'a, 'tcx> { - type Item = ImplOrTraitItem<'tcx>; - fn next(&mut self) -> Option> { - if self.idx < self.items.len() { - let item_def_id = self.items[self.idx]; - let items_table = self.tcx.impl_or_trait_items.borrow(); - let item = items_table[&item_def_id].clone(); - self.idx += 1; - Some(item) - } else { - None - } - } -} - pub struct Ancestors<'a, 'tcx: 'a> { trait_def: &'a TraitDef<'tcx>, current_source: Option, @@ -358,104 +332,16 @@ impl NodeItem { } } -pub struct TypeDefs<'a, 'tcx: 'a> { - // generally only invoked once or twice, so the box doesn't hurt - iter: Box>>> + 'a>, -} - -impl<'a, 'tcx> Iterator for TypeDefs<'a, 'tcx> { - type Item = NodeItem>>; - fn next(&mut self) -> Option { - self.iter.next() - } -} - -pub struct FnDefs<'a, 'tcx: 'a> { - // generally only invoked once or twice, so the box doesn't hurt - iter: Box>>> + 'a>, -} - -impl<'a, 'tcx> Iterator for FnDefs<'a, 'tcx> { - type Item = NodeItem>>; - fn next(&mut self) -> Option { - self.iter.next() - } -} - -pub struct ConstDefs<'a, 'tcx: 'a> { - // generally only invoked once or twice, so the box doesn't hurt - iter: Box>>> + 'a>, -} - -impl<'a, 'tcx> Iterator for ConstDefs<'a, 'tcx> { - type Item = NodeItem>>; - fn next(&mut self) -> Option { - self.iter.next() - } -} - impl<'a, 'gcx, 'tcx> Ancestors<'a, 'tcx> { - /// Search the items from the given ancestors, returning each type definition - /// with the given name. - pub fn type_defs(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, name: Name) -> TypeDefs<'a, 'gcx> { - let iter = self.flat_map(move |node| { - node.items(tcx) - .filter_map(move |item| { - if let ty::TypeTraitItem(assoc_ty) = item { - if assoc_ty.name == name { - return Some(NodeItem { - node: node, - item: assoc_ty, - }); - } - } - None - }) - - }); - TypeDefs { iter: Box::new(iter) } - } - - /// Search the items from the given ancestors, returning each fn definition - /// with the given name. - pub fn fn_defs(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, name: Name) -> FnDefs<'a, 'gcx> { - let iter = self.flat_map(move |node| { - node.items(tcx) - .filter_map(move |item| { - if let ty::MethodTraitItem(method) = item { - if method.name == name { - return Some(NodeItem { - node: node, - item: method, - }); - } - } - None - }) - - }); - FnDefs { iter: Box::new(iter) } - } - - /// Search the items from the given ancestors, returning each const - /// definition with the given name. - pub fn const_defs(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, name: Name) -> ConstDefs<'a, 'gcx> { - let iter = self.flat_map(move |node| { - node.items(tcx) - .filter_map(move |item| { - if let ty::ConstTraitItem(konst) = item { - if konst.name == name { - return Some(NodeItem { - node: node, - item: konst, - }); - } - } - None - }) - - }); - ConstDefs { iter: Box::new(iter) } + /// Search the items from the given ancestors, returning each definition + /// with the given name and the given kind. + #[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait. + pub fn defs(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, name: Name, kind: ty::AssociatedKind) + -> impl Iterator> + 'a { + self.flat_map(move |node| { + node.items(tcx).filter(move |item| item.kind == kind && item.name == name) + .map(move |item| NodeItem { node: node, item: item }) + }) } } diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index a0792dcf4dd59..68f6e73bcc20e 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -440,8 +440,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let mut entries = 0; // Count number of methods and add them to the total offset. // Skip over associated types and constants. - for trait_item in &self.trait_items(trait_ref.def_id())[..] { - if let ty::MethodTraitItem(_) = *trait_item { + for trait_item in self.associated_items(trait_ref.def_id()) { + if trait_item.kind == ty::AssociatedKind::Method { entries += 1; } } @@ -458,17 +458,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // add them to the total offset. // Skip over associated types and constants. let mut entries = object.vtable_base; - for trait_item in &self.trait_items(object.upcast_trait_ref.def_id())[..] { - if trait_item.def_id() == method_def_id { + for trait_item in self.associated_items(object.upcast_trait_ref.def_id()) { + if trait_item.def_id == method_def_id { // The item with the ID we were given really ought to be a method. - assert!(match *trait_item { - ty::MethodTraitItem(_) => true, - _ => false - }); - + assert_eq!(trait_item.kind, ty::AssociatedKind::Method); return entries; } - if let ty::MethodTraitItem(_) = *trait_item { + if trait_item.kind == ty::AssociatedKind::Method { entries += 1; } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 62cc78141db46..164b7a279aab0 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -333,14 +333,10 @@ pub struct GlobalCtxt<'tcx> { pub tables: RefCell>, /// Maps from a trait item to the trait item "descriptor" - pub impl_or_trait_items: RefCell>>, + pub associated_items: RefCell>>, /// Maps from an impl/trait def-id to a list of the def-ids of its items - pub impl_or_trait_item_def_ids: RefCell>>, - - /// A cache for the trait_items() routine; note that the routine - /// itself pushes the `TraitItems` dependency node. - trait_items_cache: RefCell>>, + pub associated_item_def_ids: RefCell>>, pub impl_trait_refs: RefCell>>, pub trait_defs: RefCell>>, @@ -760,9 +756,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { tcache: RefCell::new(DepTrackingMap::new(dep_graph.clone())), rcache: RefCell::new(FnvHashMap()), tc_cache: RefCell::new(FnvHashMap()), - impl_or_trait_items: RefCell::new(DepTrackingMap::new(dep_graph.clone())), - impl_or_trait_item_def_ids: RefCell::new(DepTrackingMap::new(dep_graph.clone())), - trait_items_cache: RefCell::new(DepTrackingMap::new(dep_graph.clone())), + associated_items: RefCell::new(DepTrackingMap::new(dep_graph.clone())), + associated_item_def_ids: RefCell::new(DepTrackingMap::new(dep_graph.clone())), ty_param_defs: RefCell::new(NodeMap()), normalized_cache: RefCell::new(FnvHashMap()), lang_items: lang_items, @@ -1477,15 +1472,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.mk_substs(iter::once(s).chain(t.into_iter().cloned()).map(Kind::from)) } - pub fn trait_items(self, trait_did: DefId) -> Rc>> { - self.trait_items_cache.memoize(trait_did, || { - let def_ids = self.impl_or_trait_items(trait_did); - Rc::new(def_ids.iter() - .map(|&def_id| self.impl_or_trait_item(def_id)) - .collect()) - }) - } - /// Obtain the representation annotation for a struct definition. pub fn lookup_repr_hints(self, did: DefId) -> Rc> { self.repr_hint_cache.memoize(did, || { diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index cad87081a93b4..43abb61e7fcd8 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -16,7 +16,7 @@ use ty::{self, Ty}; use std::cell::RefCell; use std::marker::PhantomData; use std::rc::Rc; -use syntax::{attr, ast}; +use syntax::attr; macro_rules! dep_map_ty { ($ty_name:ident : $node_name:ident ($key:ty) -> $value:ty) => { @@ -32,18 +32,16 @@ macro_rules! dep_map_ty { } } -dep_map_ty! { ImplOrTraitItems: ImplOrTraitItems(DefId) -> ty::ImplOrTraitItem<'tcx> } +dep_map_ty! { AssociatedItems: AssociatedItems(DefId) -> ty::AssociatedItem } dep_map_ty! { Tcache: ItemSignature(DefId) -> Ty<'tcx> } dep_map_ty! { Generics: ItemSignature(DefId) -> &'tcx ty::Generics<'tcx> } dep_map_ty! { Predicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> } dep_map_ty! { SuperPredicates: ItemSignature(DefId) -> ty::GenericPredicates<'tcx> } -dep_map_ty! { ImplOrTraitItemDefIds: ImplOrTraitItemDefIds(DefId) -> Rc> } +dep_map_ty! { AssociatedItemDefIds: AssociatedItemDefIds(DefId) -> Rc> } dep_map_ty! { ImplTraitRefs: ItemSignature(DefId) -> Option> } dep_map_ty! { TraitDefs: ItemSignature(DefId) -> &'tcx ty::TraitDef<'tcx> } dep_map_ty! { AdtDefs: ItemSignature(DefId) -> ty::AdtDefMaster<'tcx> } dep_map_ty! { ItemVariances: ItemSignature(DefId) -> Rc> } dep_map_ty! { InherentImpls: InherentImpls(DefId) -> Vec } -dep_map_ty! { TraitItems: TraitItems(DefId) -> Rc>> } dep_map_ty! { ReprHints: ReprHints(DefId) -> Rc> } -dep_map_ty! { InlinedClosures: Hir(DefId) -> ast::NodeId } dep_map_ty! { Mir: Mir(DefId) -> &'tcx RefCell> } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 588857e557c22..f61a45668b3e9 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -10,9 +10,8 @@ pub use self::Variance::*; pub use self::DtorKind::*; -pub use self::ImplOrTraitItemContainer::*; +pub use self::AssociatedItemContainer::*; pub use self::BorrowKind::*; -pub use self::ImplOrTraitItem::*; pub use self::IntVarValue::*; pub use self::LvaluePreference::*; pub use self::fold::TypeFoldable; @@ -135,12 +134,12 @@ impl DtorKind { } #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub enum ImplOrTraitItemContainer { +pub enum AssociatedItemContainer { TraitContainer(DefId), ImplContainer(DefId), } -impl ImplOrTraitItemContainer { +impl AssociatedItemContainer { pub fn id(&self) -> DefId { match *self { TraitContainer(id) => id, @@ -183,58 +182,34 @@ impl<'a, 'gcx, 'tcx> ImplHeader<'tcx> { } } -#[derive(Clone)] -pub enum ImplOrTraitItem<'tcx> { - ConstTraitItem(Rc>), - MethodTraitItem(Rc>), - TypeTraitItem(Rc>), -} - -impl<'tcx> ImplOrTraitItem<'tcx> { - pub fn def(&self) -> Def { - match *self { - ConstTraitItem(ref associated_const) => Def::AssociatedConst(associated_const.def_id), - MethodTraitItem(ref method) => Def::Method(method.def_id), - TypeTraitItem(ref ty) => Def::AssociatedTy(ty.def_id), - } - } - - pub fn def_id(&self) -> DefId { - match *self { - ConstTraitItem(ref associated_const) => associated_const.def_id, - MethodTraitItem(ref method) => method.def_id, - TypeTraitItem(ref associated_type) => associated_type.def_id, - } - } - - pub fn name(&self) -> Name { - match *self { - ConstTraitItem(ref associated_const) => associated_const.name, - MethodTraitItem(ref method) => method.name, - TypeTraitItem(ref associated_type) => associated_type.name, - } - } +#[derive(Copy, Clone, Debug)] +pub struct AssociatedItem { + pub def_id: DefId, + pub name: Name, + pub kind: AssociatedKind, + pub vis: Visibility, + pub defaultness: hir::Defaultness, + pub has_value: bool, + pub container: AssociatedItemContainer, - pub fn vis(&self) -> Visibility { - match *self { - ConstTraitItem(ref associated_const) => associated_const.vis, - MethodTraitItem(ref method) => method.vis, - TypeTraitItem(ref associated_type) => associated_type.vis, - } - } + /// Whether this is a method with an explicit self + /// as its first argument, allowing method calls. + pub method_has_self_argument: bool, +} - pub fn container(&self) -> ImplOrTraitItemContainer { - match *self { - ConstTraitItem(ref associated_const) => associated_const.container, - MethodTraitItem(ref method) => method.container, - TypeTraitItem(ref associated_type) => associated_type.container, - } - } +#[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable)] +pub enum AssociatedKind { + Const, + Method, + Type +} - pub fn as_opt_method(&self) -> Option>> { - match *self { - MethodTraitItem(ref m) => Some((*m).clone()), - _ => None, +impl AssociatedItem { + pub fn def(&self) -> Def { + match self.kind { + AssociatedKind::Const => Def::AssociatedConst(self.def_id), + AssociatedKind::Method => Def::Method(self.def_id), + AssociatedKind::Type => Def::AssociatedTy(self.def_id), } } } @@ -308,64 +283,6 @@ impl Visibility { } } -#[derive(Clone, Debug)] -pub struct Method<'tcx> { - pub name: Name, - pub generics: &'tcx Generics<'tcx>, - pub predicates: GenericPredicates<'tcx>, - pub fty: &'tcx BareFnTy<'tcx>, - pub explicit_self: ExplicitSelfCategory<'tcx>, - pub vis: Visibility, - pub defaultness: hir::Defaultness, - pub has_body: bool, - pub def_id: DefId, - pub container: ImplOrTraitItemContainer, -} - -impl<'tcx> Method<'tcx> { - pub fn container_id(&self) -> DefId { - match self.container { - TraitContainer(id) => id, - ImplContainer(id) => id, - } - } -} - -impl<'tcx> PartialEq for Method<'tcx> { - #[inline] - fn eq(&self, other: &Self) -> bool { self.def_id == other.def_id } -} - -impl<'tcx> Eq for Method<'tcx> {} - -impl<'tcx> Hash for Method<'tcx> { - #[inline] - fn hash(&self, s: &mut H) { - self.def_id.hash(s) - } -} - -#[derive(Clone, Copy, Debug)] -pub struct AssociatedConst<'tcx> { - pub name: Name, - pub ty: Ty<'tcx>, - pub vis: Visibility, - pub defaultness: hir::Defaultness, - pub def_id: DefId, - pub container: ImplOrTraitItemContainer, - pub has_value: bool -} - -#[derive(Clone, Copy, Debug)] -pub struct AssociatedType<'tcx> { - pub name: Name, - pub ty: Option>, - pub vis: Visibility, - pub defaultness: hir::Defaultness, - pub def_id: DefId, - pub container: ImplOrTraitItemContainer, -} - #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Copy)] pub enum Variance { Covariant, // T <: T iff A <: B -- e.g., function return type @@ -1288,19 +1205,10 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { tcx.region_maps.item_extent(id)) } hir::ImplItemKind::Method(_, ref body) => { - let method_def_id = tcx.map.local_def_id(id); - match tcx.impl_or_trait_item(method_def_id) { - MethodTraitItem(ref method_ty) => { - tcx.construct_parameter_environment( - impl_item.span, - method_ty.def_id, - tcx.region_maps.call_site_extent(id, body.id)) - } - _ => { - bug!("ParameterEnvironment::for_item(): \ - got non-method item from impl method?!") - } - } + tcx.construct_parameter_environment( + impl_item.span, + tcx.map.local_def_id(id), + tcx.region_maps.call_site_extent(id, body.id)) } } } @@ -1319,27 +1227,17 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { // Use call-site for extent (unless this is a // trait method with no default; then fallback // to the method id). - let method_def_id = tcx.map.local_def_id(id); - match tcx.impl_or_trait_item(method_def_id) { - MethodTraitItem(ref method_ty) => { - let extent = if let Some(ref body) = *body { - // default impl: use call_site extent as free_id_outlive bound. - tcx.region_maps.call_site_extent(id, body.id) - } else { - // no default impl: use item extent as free_id_outlive bound. - tcx.region_maps.item_extent(id) - }; - tcx.construct_parameter_environment( - trait_item.span, - method_ty.def_id, - extent) - } - _ => { - bug!("ParameterEnvironment::for_item(): \ - got non-method item from provided \ - method?!") - } - } + let extent = if let Some(ref body) = *body { + // default impl: use call_site extent as free_id_outlive bound. + tcx.region_maps.call_site_extent(id, body.id) + } else { + // no default impl: use item extent as free_id_outlive bound. + tcx.region_maps.item_extent(id) + }; + tcx.construct_parameter_environment( + trait_item.span, + tcx.map.local_def_id(id), + extent) } } } @@ -2065,7 +1963,7 @@ impl LvaluePreference { } /// Helper for looking things up in the various maps that are populated during -/// typeck::collect (e.g., `tcx.impl_or_trait_items`, `tcx.tcache`, etc). All of +/// typeck::collect (e.g., `tcx.associated_items`, `tcx.tcache`, etc). All of /// these share the pattern that if the id is local, it should have been loaded /// into the map by the `typeck::collect` phase. If the def-id is external, /// then we have to go consult the crate loading code (and cache the result for @@ -2276,13 +2174,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - pub fn provided_trait_methods(self, id: DefId) -> Vec>> { - self.impl_or_trait_items(id).iter().filter_map(|&def_id| { - match self.impl_or_trait_item(def_id) { - MethodTraitItem(ref m) if m.has_body => Some(m.clone()), - _ => None - } - }).collect() + pub fn provided_trait_methods(self, id: DefId) -> Vec { + self.associated_items(id) + .filter(|item| item.kind == AssociatedKind::Method && item.has_value) + .collect() } pub fn trait_impl_polarity(self, id: DefId) -> hir::ImplPolarity { @@ -2315,17 +2210,105 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { }) } - pub fn impl_or_trait_item(self, id: DefId) -> ImplOrTraitItem<'gcx> { - lookup_locally_or_in_crate_store( - "impl_or_trait_items", id, &self.impl_or_trait_items, - || self.sess.cstore.impl_or_trait_item(self.global_tcx(), id) - .expect("missing ImplOrTraitItem in metadata")) + pub fn associated_item(self, def_id: DefId) -> AssociatedItem { + self.associated_items.memoize(def_id, || { + if !def_id.is_local() { + return self.sess.cstore.associated_item(self.global_tcx(), def_id) + .expect("missing AssociatedItem in metadata"); + } + + let id = self.map.as_local_node_id(def_id).unwrap(); + let parent_id = self.map.get_parent(id); + let parent_def_id = self.map.local_def_id(parent_id); + match self.map.get(id) { + ast_map::NodeTraitItem(trait_item) => { + let (kind, has_self, has_value) = match trait_item.node { + hir::MethodTraitItem(ref sig, ref body) => { + (AssociatedKind::Method, sig.decl.get_self().is_some(), + body.is_some()) + } + hir::ConstTraitItem(_, ref value) => { + (AssociatedKind::Const, false, value.is_some()) + } + hir::TypeTraitItem(_, ref ty) => { + (AssociatedKind::Type, false, ty.is_some()) + } + }; + + AssociatedItem { + name: trait_item.name, + kind: kind, + vis: Visibility::from_hir(&hir::Inherited, id, self), + defaultness: hir::Defaultness::Default, + has_value: has_value, + def_id: def_id, + container: TraitContainer(parent_def_id), + method_has_self_argument: has_self + } + } + ast_map::NodeImplItem(impl_item) => { + let (kind, has_self) = match impl_item.node { + hir::ImplItemKind::Method(ref sig, _) => { + (AssociatedKind::Method, sig.decl.get_self().is_some()) + } + hir::ImplItemKind::Const(..) => (AssociatedKind::Const, false), + hir::ImplItemKind::Type(..) => (AssociatedKind::Type, false) + }; + + // Trait impl items are always public. + let public = hir::Public; + let parent_item = self.map.expect_item(parent_id); + let vis = if let hir::ItemImpl(.., Some(_), _, _) = parent_item.node { + &public + } else { + &impl_item.vis + }; + + AssociatedItem { + name: impl_item.name, + kind: kind, + vis: Visibility::from_hir(vis, id, self), + defaultness: impl_item.defaultness, + has_value: true, + def_id: def_id, + container: ImplContainer(parent_def_id), + method_has_self_argument: has_self + } + } + item => bug!("associated_item: {:?} not an associated item", item) + } + }) } - pub fn impl_or_trait_items(self, id: DefId) -> Rc> { - lookup_locally_or_in_crate_store( - "impl_or_trait_items", id, &self.impl_or_trait_item_def_ids, - || Rc::new(self.sess.cstore.impl_or_trait_items(id))) + pub fn associated_item_def_ids(self, def_id: DefId) -> Rc> { + self.associated_item_def_ids.memoize(def_id, || { + if !def_id.is_local() { + return Rc::new(self.sess.cstore.associated_item_def_ids(def_id)); + } + + let id = self.map.as_local_node_id(def_id).unwrap(); + let item = self.map.expect_item(id); + match item.node { + hir::ItemTrait(.., ref trait_items) => { + Rc::new(trait_items.iter().map(|trait_item| { + self.map.local_def_id(trait_item.id) + }).collect()) + } + hir::ItemImpl(.., ref impl_items) => { + Rc::new(impl_items.iter().map(|impl_item| { + self.map.local_def_id(impl_item.id) + }).collect()) + } + _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait") + } + }) + } + + #[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait. + pub fn associated_items(self, def_id: DefId) + -> impl Iterator + 'a { + let def_ids = self.associated_item_def_ids(def_id); + (0..def_ids.len()).map(move |i| self.associated_item(def_ids[i])) } /// Returns the trait-ref corresponding to a given impl, or None if it is @@ -2611,31 +2594,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { def.flags.set(def.flags.get() | TraitFlags::HAS_DEFAULT_IMPL) } - /// Load primitive inherent implementations if necessary - pub fn populate_implementations_for_primitive_if_necessary(self, - primitive_def_id: DefId) { - if primitive_def_id.is_local() { - return - } - - // The primitive is not local, hence we are reading this out - // of metadata. - let _ignore = self.dep_graph.in_ignore(); - - if self.populated_external_primitive_impls.borrow().contains(&primitive_def_id) { - return - } - - debug!("populate_implementations_for_primitive_if_necessary: searching for {:?}", - primitive_def_id); - - let impl_items = self.sess.cstore.impl_or_trait_items(primitive_def_id); - - // Store the implementation info. - self.impl_or_trait_item_def_ids.borrow_mut().insert(primitive_def_id, Rc::new(impl_items)); - self.populated_external_primitive_impls.borrow_mut().insert(primitive_def_id); - } - /// Populates the type context with all the inherent implementations for /// the given type if necessary. pub fn populate_inherent_implementations_for_type_if_necessary(self, @@ -2656,11 +2614,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { type_id); let inherent_impls = self.sess.cstore.inherent_implementations_for_type(type_id); - for &impl_def_id in &inherent_impls { - // Store the implementation info. - let impl_items = self.sess.cstore.impl_or_trait_items(impl_def_id); - self.impl_or_trait_item_def_ids.borrow_mut().insert(impl_def_id, Rc::new(impl_items)); - } self.inherent_impls.borrow_mut().insert(type_id, inherent_impls); self.populated_external_types.borrow_mut().insert(type_id); @@ -2689,23 +2642,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } for impl_def_id in self.sess.cstore.implementations_of_trait(Some(trait_id)) { - let impl_items = self.sess.cstore.impl_or_trait_items(impl_def_id); let trait_ref = self.impl_trait_ref(impl_def_id).unwrap(); // Record the trait->implementation mapping. let parent = self.sess.cstore.impl_parent(impl_def_id).unwrap_or(trait_id); def.record_remote_impl(self, impl_def_id, trait_ref, parent); - - // For any methods that use a default implementation, add them to - // the map. This is a bit unfortunate. - for &impl_item_def_id in &impl_items { - // load impl items eagerly for convenience - // FIXME: we may want to load these lazily - self.impl_or_trait_item(impl_item_def_id); - } - - // Store the implementation info. - self.impl_or_trait_item_def_ids.borrow_mut().insert(impl_def_id, Rc::new(impl_items)); } def.flags.set(def.flags.get() | TraitFlags::IMPLS_VALID); @@ -2751,17 +2692,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// ID of the impl that the method belongs to. Otherwise, return `None`. pub fn impl_of_method(self, def_id: DefId) -> Option { if def_id.krate != LOCAL_CRATE { - return self.sess.cstore.impl_or_trait_item(self.global_tcx(), def_id) + return self.sess.cstore.associated_item(self.global_tcx(), def_id) .and_then(|item| { - match item.container() { + match item.container { TraitContainer(_) => None, ImplContainer(def_id) => Some(def_id), } }); } - match self.impl_or_trait_items.borrow().get(&def_id).cloned() { + match self.associated_items.borrow().get(&def_id).cloned() { Some(trait_item) => { - match trait_item.container() { + match trait_item.container { TraitContainer(_) => None, ImplContainer(def_id) => Some(def_id), } @@ -2777,9 +2718,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if def_id.krate != LOCAL_CRATE { return self.sess.cstore.trait_of_item(def_id); } - match self.impl_or_trait_items.borrow().get(&def_id) { - Some(impl_or_trait_item) => { - match impl_or_trait_item.container() { + match self.associated_items.borrow().get(&def_id) { + Some(associated_item) => { + match associated_item.container { TraitContainer(def_id) => Some(def_id), ImplContainer(_) => None } @@ -2788,30 +2729,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - /// If the given def ID describes an item belonging to a trait, (either a - /// default method or an implementation of a trait method), return the ID of - /// the method inside trait definition (this means that if the given def ID - /// is already that of the original trait method, then the return value is - /// the same). - /// Otherwise, return `None`. - pub fn trait_item_of_item(self, def_id: DefId) -> Option { - let impl_or_trait_item = match self.impl_or_trait_items.borrow().get(&def_id) { - Some(m) => m.clone(), - None => return None, - }; - match impl_or_trait_item.container() { - TraitContainer(_) => Some(impl_or_trait_item.def_id()), - ImplContainer(def_id) => { - self.trait_id_of_impl(def_id).and_then(|trait_did| { - let name = impl_or_trait_item.name(); - self.trait_items(trait_did).iter() - .find(|item| item.name() == name) - .map(|item| item.def_id()) - }) - } - } - } - /// Construct a parameter environment suitable for static contexts or other contexts where there /// are no free type/lifetime parameters in scope. pub fn empty_parameter_environment(self) -> ParameterEnvironment<'tcx> { @@ -2941,15 +2858,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } -/// The category of explicit self. -#[derive(Clone, Copy, Eq, PartialEq, Debug, RustcEncodable, RustcDecodable)] -pub enum ExplicitSelfCategory<'tcx> { - Static, - ByValue, - ByReference(&'tcx Region, hir::Mutability), - ByBox, -} - impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn with_freevars(self, fid: NodeId, f: F) -> T where F: FnOnce(&[hir::Freevar]) -> T, diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 5ca567410291a..5e23921000527 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -682,18 +682,6 @@ impl<'tcx> fmt::Debug for ty::InstantiatedPredicates<'tcx> { } } -impl<'tcx> fmt::Debug for ty::ImplOrTraitItem<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "ImplOrTraitItem(")?; - match *self { - ty::ImplOrTraitItem::MethodTraitItem(ref i) => write!(f, "{:?}", i), - ty::ImplOrTraitItem::ConstTraitItem(ref i) => write!(f, "{:?}", i), - ty::ImplOrTraitItem::TypeTraitItem(ref i) => write!(f, "{:?}", i), - }?; - write!(f, ")") - } -} - impl<'tcx> fmt::Display for ty::FnSig<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "fn")?; @@ -1007,20 +995,6 @@ impl fmt::Display for ty::InferTy { } } -impl<'tcx> fmt::Display for ty::ExplicitSelfCategory<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str(match *self { - ty::ExplicitSelfCategory::Static => "static", - ty::ExplicitSelfCategory::ByValue => "self", - ty::ExplicitSelfCategory::ByReference(_, hir::MutMutable) => { - "&mut self" - } - ty::ExplicitSelfCategory::ByReference(_, hir::MutImmutable) => "&self", - ty::ExplicitSelfCategory::ByBox => "Box", - }) - } -} - impl fmt::Display for ty::ParamTy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.name) diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index c02cca0da7225..2c1201d389be2 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -1090,13 +1090,8 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // when constructing the inference context above. match selection { traits::VtableImpl(ref impl_data) => { - let ac = tcx.impl_or_trait_items(impl_data.impl_def_id) - .iter().filter_map(|&def_id| { - match tcx.impl_or_trait_item(def_id) { - ty::ConstTraitItem(ic) => Some(ic), - _ => None - } - }).find(|ic| ic.name == ti.name); + let ac = tcx.associated_items(impl_data.impl_def_id) + .find(|item| item.kind == ty::AssociatedKind::Const && item.name == ti.name); match ac { Some(ic) => lookup_const_by_id(tcx, ic.def_id, None), None => match ti.node { diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs index fea3de59520ca..28d45080284cd 100644 --- a/src/librustc_lint/bad_style.rs +++ b/src/librustc_lint/bad_style.rs @@ -29,10 +29,10 @@ pub enum MethodLateContext { pub fn method_context(cx: &LateContext, id: ast::NodeId, span: Span) -> MethodLateContext { let def_id = cx.tcx.map.local_def_id(id); - match cx.tcx.impl_or_trait_items.borrow().get(&def_id) { + match cx.tcx.associated_items.borrow().get(&def_id) { None => span_bug!(span, "missing method descriptor?!"), Some(item) => { - match item.container() { + match item.container { ty::TraitContainer(..) => MethodLateContext::TraitDefaultImpl, ty::ImplContainer(cid) => { match cx.tcx.impl_trait_ref(cid) { diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index eee34324a6583..d85615be24380 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -817,7 +817,7 @@ impl LateLintPass for UnconditionalRecursion { let method = match fn_kind { FnKind::ItemFn(..) => None, FnKind::Method(..) => { - cx.tcx.impl_or_trait_item(cx.tcx.map.local_def_id(id)).as_opt_method() + Some(cx.tcx.associated_item(cx.tcx.map.local_def_id(id))) } // closures can't recur, so they don't matter. FnKind::Closure(_) => return, @@ -936,7 +936,7 @@ impl LateLintPass for UnconditionalRecursion { // Check if the expression `id` performs a call to `method`. fn expr_refers_to_this_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - method: &ty::Method, + method: &ty::AssociatedItem, id: ast::NodeId) -> bool { // Check for method calls and overloaded operators. @@ -988,14 +988,14 @@ impl LateLintPass for UnconditionalRecursion { // Check if the method call to the method with the ID `callee_id` // and instantiated with `callee_substs` refers to method `method`. fn method_call_refers_to_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - method: &ty::Method, + method: &ty::AssociatedItem, callee_id: DefId, callee_substs: &Substs<'tcx>, expr_id: ast::NodeId) -> bool { - let callee_item = tcx.impl_or_trait_item(callee_id); + let callee_item = tcx.associated_item(callee_id); - match callee_item.container() { + match callee_item.container { // This is an inherent method, so the `def_id` refers // directly to the method definition. ty::ImplContainer(_) => callee_id == method.def_id, @@ -1036,7 +1036,7 @@ impl LateLintPass for UnconditionalRecursion { let container = ty::ImplContainer(vtable_impl.impl_def_id); // It matches if it comes from the same impl, // and has the same method name. - container == method.container && callee_item.name() == method.name + container == method.container && callee_item.name == method.name } // There's no way to know if this call is diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index a618c98ff774c..18ce514c9c42d 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -144,7 +144,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { result } - fn impl_or_trait_items(&self, def_id: DefId) -> Vec { + fn associated_item_def_ids(&self, def_id: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(def_id)); let mut result = vec![]; self.get_crate_data(def_id.krate) @@ -182,11 +182,11 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.get_crate_data(def_id.krate).get_trait_of_item(def_id.index) } - fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) - -> Option> + fn associated_item<'a>(&self, _tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) + -> Option { self.dep_graph.read(DepNode::MetaData(def)); - self.get_crate_data(def.krate).get_impl_or_trait_item(def.index, tcx) + self.get_crate_data(def.krate).get_associated_item(def.index) } fn is_const_fn(&self, did: DefId) -> bool @@ -427,9 +427,9 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { // the logic to do that already exists in `middle`. In order to // reuse that code, it needs to be able to look up the traits for // inlined items. - let ty_trait_item = tcx.impl_or_trait_item(def_id).clone(); + let ty_trait_item = tcx.associated_item(def_id).clone(); let trait_item_def_id = tcx.map.local_def_id(trait_item.id); - tcx.impl_or_trait_items.borrow_mut() + tcx.associated_items.borrow_mut() .insert(trait_item_def_id, ty_trait_item); } Some(&InlinedItem::ImplItem(_, ref impl_item)) => { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index ccd497860de8a..54a0f36b07a2d 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -36,7 +36,6 @@ use std::borrow::Cow; use std::cell::Ref; use std::io; use std::mem; -use std::rc::Rc; use std::str; use std::u32; @@ -792,10 +791,7 @@ impl<'a, 'tcx> CrateMetadata { self.entry(id).mir.map(|mir| mir.decode((self, tcx))) } - pub fn get_impl_or_trait_item(&self, - id: DefIndex, - tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> Option> { + pub fn get_associated_item(&self, id: DefIndex) -> Option { let item = self.entry(id); let parent_and_name = || { let def_key = item.def_key.decode(self); @@ -806,52 +802,43 @@ impl<'a, 'tcx> CrateMetadata { Some(match item.kind { EntryKind::AssociatedConst(container) => { let (parent, name) = parent_and_name(); - ty::ConstTraitItem(Rc::new(ty::AssociatedConst { + ty::AssociatedItem { name: name, - ty: item.ty.unwrap().decode((self, tcx)), + kind: ty::AssociatedKind::Const, vis: item.visibility, defaultness: container.defaultness(), + has_value: container.has_value(), def_id: self.local_def_id(id), container: container.with_def_id(parent), - has_value: container.has_body(), - })) + method_has_self_argument: false + } } EntryKind::Method(data) => { let (parent, name) = parent_and_name(); - let ity = item.ty.unwrap().decode((self, tcx)); - let fty = match ity.sty { - ty::TyFnDef(.., fty) => fty, - _ => { - bug!("the type {:?} of the method {:?} is not a function?", - ity, - name) - } - }; - let data = data.decode(self); - ty::MethodTraitItem(Rc::new(ty::Method { + ty::AssociatedItem { name: name, - generics: tcx.lookup_generics(self.local_def_id(id)), - predicates: item.predicates.unwrap().decode((self, tcx)), - fty: fty, - explicit_self: data.explicit_self.decode((self, tcx)), + kind: ty::AssociatedKind::Method, vis: item.visibility, defaultness: data.container.defaultness(), - has_body: data.container.has_body(), + has_value: data.container.has_value(), def_id: self.local_def_id(id), container: data.container.with_def_id(parent), - })) + method_has_self_argument: data.has_self + } } EntryKind::AssociatedType(container) => { let (parent, name) = parent_and_name(); - ty::TypeTraitItem(Rc::new(ty::AssociatedType { + ty::AssociatedItem { name: name, - ty: item.ty.map(|ty| ty.decode((self, tcx))), + kind: ty::AssociatedKind::Type, vis: item.visibility, defaultness: container.defaultness(), + has_value: container.has_value(), def_id: self.local_def_id(id), container: container.with_def_id(parent), - })) + method_has_self_argument: false + } } _ => return None, }) diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index e8734e4275712..a4a9cafb31c16 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -457,19 +457,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let node_id = tcx.map.as_local_node_id(def_id).unwrap(); let ast_item = tcx.map.expect_trait_item(node_id); - let trait_item = tcx.impl_or_trait_item(def_id); + let trait_item = tcx.associated_item(def_id); - let container = |has_body| if has_body { + let container = if trait_item.has_value { AssociatedContainer::TraitWithDefault } else { AssociatedContainer::TraitRequired }; - let kind = match trait_item { - ty::ConstTraitItem(ref associated_const) => { - EntryKind::AssociatedConst(container(associated_const.has_value)) - } - ty::MethodTraitItem(ref method_ty) => { + let kind = match trait_item.kind { + ty::AssociatedKind::Const => EntryKind::AssociatedConst(container), + ty::AssociatedKind::Method => { let fn_data = if let hir::MethodTraitItem(ref sig, _) = ast_item.node { FnData { constness: hir::Constness::NotConst, @@ -478,30 +476,35 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } else { bug!() }; - let data = MethodData { + EntryKind::Method(self.lazy(&MethodData { fn_data: fn_data, - container: container(method_ty.has_body), - explicit_self: self.lazy(&method_ty.explicit_self), - }; - EntryKind::Method(self.lazy(&data)) + container: container, + has_self: trait_item.method_has_self_argument, + })) } - ty::TypeTraitItem(_) => EntryKind::AssociatedType(container(false)), + ty::AssociatedKind::Type => EntryKind::AssociatedType(container), }; Entry { kind: kind, - visibility: trait_item.vis().simplify(), + visibility: trait_item.vis.simplify(), def_key: self.encode_def_key(def_id), attributes: self.encode_attributes(&ast_item.attrs), children: LazySeq::empty(), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), - ty: match trait_item { - ty::ConstTraitItem(_) | - ty::MethodTraitItem(_) => Some(self.encode_item_type(def_id)), - ty::TypeTraitItem(ref associated_type) => { - associated_type.ty.map(|ty| self.lazy(&ty)) + ty: match trait_item.kind { + ty::AssociatedKind::Const | + ty::AssociatedKind::Method => { + Some(self.encode_item_type(def_id)) + } + ty::AssociatedKind::Type => { + if trait_item.has_value { + Some(self.encode_item_type(def_id)) + } else { + None + } } }, inherent_impls: LazySeq::empty(), @@ -509,8 +512,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), - ast: if let ty::ConstTraitItem(_) = trait_item { - let trait_def_id = trait_item.container().id(); + ast: if trait_item.kind == ty::AssociatedKind::Const { + let trait_def_id = trait_item.container.id(); Some(self.encode_inlined_item(InlinedItemRef::TraitItem(trait_def_id, ast_item))) } else { None @@ -522,17 +525,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> { let node_id = self.tcx.map.as_local_node_id(def_id).unwrap(); let ast_item = self.tcx.map.expect_impl_item(node_id); - let impl_item = self.tcx.impl_or_trait_item(def_id); - let impl_def_id = impl_item.container().id(); + let impl_item = self.tcx.associated_item(def_id); + let impl_def_id = impl_item.container.id(); - let container = match ast_item.defaultness { + let container = match impl_item.defaultness { hir::Defaultness::Default => AssociatedContainer::ImplDefault, hir::Defaultness::Final => AssociatedContainer::ImplFinal, }; - let kind = match impl_item { - ty::ConstTraitItem(_) => EntryKind::AssociatedConst(container), - ty::MethodTraitItem(ref method_ty) => { + let kind = match impl_item.kind { + ty::AssociatedKind::Const => EntryKind::AssociatedConst(container), + ty::AssociatedKind::Method => { let fn_data = if let hir::ImplItemKind::Method(ref sig, _) = ast_item.node { FnData { constness: sig.constness, @@ -541,17 +544,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } else { bug!() }; - let data = MethodData { + EntryKind::Method(self.lazy(&MethodData { fn_data: fn_data, container: container, - explicit_self: self.lazy(&method_ty.explicit_self), - }; - EntryKind::Method(self.lazy(&data)) + has_self: impl_item.method_has_self_argument, + })) } - ty::TypeTraitItem(_) => EntryKind::AssociatedType(container), + ty::AssociatedKind::Type => EntryKind::AssociatedType(container) }; - let (ast, mir) = if let ty::ConstTraitItem(_) = impl_item { + let (ast, mir) = if impl_item.kind == ty::AssociatedKind::Const { (true, true) } else if let hir::ImplItemKind::Method(ref sig, _) = ast_item.node { let generics = self.tcx.lookup_generics(def_id); @@ -565,20 +567,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { Entry { kind: kind, - visibility: impl_item.vis().simplify(), + visibility: impl_item.vis.simplify(), def_key: self.encode_def_key(def_id), attributes: self.encode_attributes(&ast_item.attrs), children: LazySeq::empty(), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), - ty: match impl_item { - ty::ConstTraitItem(_) | - ty::MethodTraitItem(_) => Some(self.encode_item_type(def_id)), - ty::TypeTraitItem(ref associated_type) => { - associated_type.ty.map(|ty| self.lazy(&ty)) - } - }, + ty: Some(self.encode_item_type(def_id)), inherent_impls: LazySeq::empty(), variances: LazySeq::empty(), generics: Some(self.encode_generics(def_id)), @@ -758,7 +754,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } hir::ItemImpl(..) | hir::ItemTrait(..) => { - self.lazy_seq(tcx.impl_or_trait_items(def_id).iter().map(|&def_id| { + self.lazy_seq(tcx.associated_item_def_ids(def_id).iter().map(|&def_id| { assert!(def_id.is_local()); def_id.index })) @@ -880,14 +876,14 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { self.encode_fields(def_id); } hir::ItemImpl(..) => { - for &trait_item_def_id in &self.tcx.impl_or_trait_items(def_id)[..] { + for &trait_item_def_id in &self.tcx.associated_item_def_ids(def_id)[..] { self.record(trait_item_def_id, EncodeContext::encode_info_for_impl_item, trait_item_def_id); } } hir::ItemTrait(..) => { - for &item_def_id in &self.tcx.impl_or_trait_items(def_id)[..] { + for &item_def_id in &self.tcx.associated_item_def_ids(def_id)[..] { self.record(item_def_id, EncodeContext::encode_info_for_trait_item, item_def_id); diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 3d1bd77d8bc28..ff2a764571025 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -245,7 +245,7 @@ pub enum EntryKind<'tcx> { Trait(Lazy>), Impl(Lazy>), DefaultImpl(Lazy>), - Method(Lazy>), + Method(Lazy), AssociatedType(AssociatedContainer), AssociatedConst(AssociatedContainer), } @@ -300,7 +300,7 @@ pub enum AssociatedContainer { } impl AssociatedContainer { - pub fn with_def_id(&self, def_id: DefId) -> ty::ImplOrTraitItemContainer { + pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer { match *self { AssociatedContainer::TraitRequired | AssociatedContainer::TraitWithDefault => ty::TraitContainer(def_id), @@ -310,7 +310,7 @@ impl AssociatedContainer { } } - pub fn has_body(&self) -> bool { + pub fn has_value(&self) -> bool { match *self { AssociatedContainer::TraitRequired => false, @@ -332,10 +332,10 @@ impl AssociatedContainer { } #[derive(RustcEncodable, RustcDecodable)] -pub struct MethodData<'tcx> { +pub struct MethodData { pub fn_data: FnData, pub container: AssociatedContainer, - pub explicit_self: Lazy>, + pub has_self: bool, } #[derive(RustcEncodable, RustcDecodable)] diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 678db1e544cb0..ecc2d8fe050ad 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -147,20 +147,14 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { -> (Ty<'tcx>, Literal<'tcx>) { let method_name = token::intern(method_name); let substs = self.tcx.mk_substs_trait(self_ty, params); - for trait_item in self.tcx.trait_items(trait_def_id).iter() { - match *trait_item { - ty::ImplOrTraitItem::MethodTraitItem(ref method) => { - if method.name == method_name { - let method_ty = self.tcx.lookup_item_type(method.def_id); - let method_ty = method_ty.ty.subst(self.tcx, substs); - return (method_ty, Literal::Item { - def_id: method.def_id, - substs: substs, - }); - } - } - ty::ImplOrTraitItem::ConstTraitItem(..) | - ty::ImplOrTraitItem::TypeTraitItem(..) => {} + for item in self.tcx.associated_items(trait_def_id) { + if item.kind == ty::AssociatedKind::Method && item.name == method_name { + let method_ty = self.tcx.lookup_item_type(item.def_id); + let method_ty = method_ty.ty.subst(self.tcx, substs); + return (method_ty, Literal::Item { + def_id: item.def_id, + substs: substs, + }); } } diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 8ad4d7f57a6f0..f57c035f00715 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -541,7 +541,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node v.handle_const_fn_call(e, did, node_ty) } Some(Def::Method(did)) => { - match v.tcx.impl_or_trait_item(did).container() { + match v.tcx.associated_item(did).container { ty::ImplContainer(_) => { v.handle_const_fn_call(e, did, node_ty) } @@ -556,7 +556,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } hir::ExprMethodCall(..) => { let method = v.tcx.tables.borrow().method_map[&method_call]; - let is_const = match v.tcx.impl_or_trait_item(method.def_id).container() { + let is_const = match v.tcx.associated_item(method.def_id).container { ty::ImplContainer(_) => v.handle_const_fn_call(e, method.def_id, node_ty), ty::TraitContainer(_) => false }; diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 77b3e76fc541f..b02d56bf1975a 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -399,7 +399,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { // Checks that a method is in scope. fn check_method(&mut self, span: Span, method_def_id: DefId) { - match self.tcx.impl_or_trait_item(method_def_id).container() { + match self.tcx.associated_item(method_def_id).container { // Trait methods are always all public. The only controlling factor // is whether the trait itself is accessible or not. ty::TraitContainer(trait_def_id) if !self.item_is_accessible(trait_def_id) => { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index d90fe769caf63..922775449ce8d 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -456,7 +456,7 @@ impl<'b> Resolver<'b> { self.define(parent, name, TypeNS, (module, DUMMY_SP, vis)); // If this is a trait, add all the trait item names to the trait info. - let trait_item_def_ids = self.session.cstore.impl_or_trait_items(def_id); + let trait_item_def_ids = self.session.cstore.associated_item_def_ids(def_id); for trait_item_def_id in trait_item_def_ids { let trait_item_name = self.session.cstore.def_key(trait_item_def_id) .disambiguated_data.data.get_opt_name() diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 8a628289b7f94..3f105dda9728e 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -32,7 +32,7 @@ use rustc::hir::def::Def; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::hir::map::{Node, NodeItem}; use rustc::session::Session; -use rustc::ty::{self, TyCtxt, ImplOrTraitItem, ImplOrTraitItemContainer}; +use rustc::ty::{self, TyCtxt, AssociatedItemContainer}; use std::collections::HashSet; use std::collections::hash_map::DefaultHasher; @@ -402,19 +402,19 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { // with the right name. if !self.span.filter_generated(Some(method_data.span), span) { let container = - self.tcx.impl_or_trait_item(self.tcx.map.local_def_id(id)).container(); + self.tcx.associated_item(self.tcx.map.local_def_id(id)).container; let mut trait_id; let mut decl_id = None; match container { - ImplOrTraitItemContainer::ImplContainer(id) => { + AssociatedItemContainer::ImplContainer(id) => { trait_id = self.tcx.trait_id_of_impl(id); match trait_id { Some(id) => { - for item in &**self.tcx.trait_items(id) { - if let &ImplOrTraitItem::MethodTraitItem(ref m) = item { - if m.name == name { - decl_id = Some(m.def_id); + for item in self.tcx.associated_items(id) { + if item.kind == ty::AssociatedKind::Method { + if item.name == name { + decl_id = Some(item.def_id); break; } } @@ -429,7 +429,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { } } } - ImplOrTraitItemContainer::TraitContainer(id) => { + AssociatedItemContainer::TraitContainer(id) => { trait_id = Some(id); } } @@ -916,11 +916,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { // Modules or types in the path prefix. match self.tcx.expect_def(id) { Def::Method(did) => { - let ti = self.tcx.impl_or_trait_item(did); - if let ty::MethodTraitItem(m) = ti { - if m.explicit_self == ty::ExplicitSelfCategory::Static { - self.write_sub_path_trait_truncated(path); - } + let ti = self.tcx.associated_item(did); + if ti.kind == ty::AssociatedKind::Method && ti.method_has_self_argument { + self.write_sub_path_trait_truncated(path); } } Def::Fn(..) | diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 15c74f2ed6ab5..9b2ee3a10499f 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -313,7 +313,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { name: ast::Name, span: Span) -> Option { // The qualname for a method is the trait name or name of the struct in an impl in // which the method is declared in, followed by the method's name. - let (qualname, parent_scope, vis, docs) = + let (qualname, parent_scope, decl_id, vis, docs) = match self.tcx.impl_of_method(self.tcx.map.local_def_id(id)) { Some(impl_id) => match self.tcx.map.get_if_local(impl_id) { Some(NodeItem(item)) => { @@ -323,12 +323,19 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { result.push_str(&rustc::hir::print::ty_to_string(&ty)); let trait_id = self.tcx.trait_id_of_impl(impl_id); + let mut decl_id = None; if let Some(def_id) = trait_id { result.push_str(" as "); result.push_str(&self.tcx.item_path_str(def_id)); + self.tcx.associated_items(def_id) + .find(|item| item.name == name) + .map(|item| decl_id = Some(item.def_id)); } result.push_str(">"); - (result, trait_id, From::from(&item.vis), docs_for_attrs(&item.attrs)) + + (result, trait_id, decl_id, + From::from(&item.vis), + docs_for_attrs(&item.attrs)) } _ => { span_bug!(span, @@ -351,7 +358,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { match self.tcx.map.get_if_local(def_id) { Some(NodeItem(item)) => { (format!("::{}", self.tcx.item_path_str(def_id)), - Some(def_id), + Some(def_id), None, From::from(&item.vis), docs_for_attrs(&item.attrs)) } @@ -373,15 +380,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let qualname = format!("{}::{}", qualname, name); - let def_id = self.tcx.map.local_def_id(id); - let decl_id = self.tcx.trait_item_of_item(def_id).and_then(|new_def_id| { - if new_def_id != def_id { - Some(new_def_id) - } else { - None - } - }); - let sub_span = self.span_utils.sub_span_after_keyword(span, keywords::Fn); filter!(self.span_utils, sub_span, span, None); Some(FunctionData { @@ -473,7 +471,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ast::ExprKind::MethodCall(..) => { let method_call = ty::MethodCall::expr(expr.id); let method_id = self.tcx.tables.borrow().method_map[&method_call].def_id; - let (def_id, decl_id) = match self.tcx.impl_or_trait_item(method_id).container() { + let (def_id, decl_id) = match self.tcx.associated_item(method_id).container { ty::ImplContainer(_) => (Some(method_id), None), ty::TraitContainer(_) => (None, Some(method_id)), }; @@ -535,21 +533,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let sub_span = self.span_utils.sub_span_for_meth_name(path.span); filter!(self.span_utils, sub_span, path.span, None); let def_id = if decl_id.is_local() { - let ti = self.tcx.impl_or_trait_item(decl_id); - match ti.container() { - ty::TraitContainer(def_id) => { - self.tcx - .trait_items(def_id) - .iter() - .find(|mr| mr.name() == ti.name() && self.trait_method_has_body(mr)) - .map(|mr| mr.def_id()) - } - ty::ImplContainer(def_id) => { - Some(*self.tcx.impl_or_trait_items(def_id).iter().find(|&&mr| { - self.tcx.impl_or_trait_item(mr).name() == ti.name() - }).unwrap()) - } - } + let ti = self.tcx.associated_item(decl_id); + self.tcx.associated_items(ti.container.id()) + .find(|item| item.name == ti.name && item.has_value) + .map(|item| item.def_id) } else { None }; @@ -582,20 +569,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } - fn trait_method_has_body(&self, mr: &ty::ImplOrTraitItem) -> bool { - let def_id = mr.def_id(); - if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) { - let trait_item = self.tcx.map.expect_trait_item(node_id); - if let hir::TraitItem_::MethodTraitItem(_, Some(_)) = trait_item.node { - true - } else { - false - } - } else { - false - } - } - pub fn get_field_ref_data(&self, field_ref: &ast::Field, variant: ty::VariantDef, diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 8348da9f7b7bf..1288be482f4c1 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -844,17 +844,12 @@ fn do_static_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, param_substs); if let Some(trait_def_id) = scx.tcx().trait_of_item(fn_def_id) { - match scx.tcx().impl_or_trait_item(fn_def_id) { - ty::MethodTraitItem(ref method) => { - debug!(" => trait method, attempting to find impl"); - do_static_trait_method_dispatch(scx, - method, - trait_def_id, - fn_substs, - param_substs) - } - _ => bug!() - } + debug!(" => trait method, attempting to find impl"); + do_static_trait_method_dispatch(scx, + &scx.tcx().associated_item(fn_def_id), + trait_def_id, + fn_substs, + param_substs) } else { debug!(" => regular function"); // The function is not part of an impl or trait, no dispatching @@ -866,7 +861,7 @@ fn do_static_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, // Given a trait-method and substitution information, find out the actual // implementation of the trait method. fn do_static_trait_method_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, - trait_method: &ty::Method, + trait_method: &ty::AssociatedItem, trait_id: DefId, callee_substs: &'tcx Substs<'tcx>, param_substs: &'tcx Substs<'tcx>) @@ -1190,7 +1185,7 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(scx: &SharedCrateContext<'a, ' continue; } - if !method.generics.types.is_empty() { + if !tcx.lookup_generics(method.def_id).types.is_empty() { continue; } diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 3d0d889760943..b8d346b11c13f 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -248,13 +248,8 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { let vtable = common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref); if let traits::VtableImpl(vtable_impl) = vtable { let name = ccx.tcx().item_name(instance.def); - let ac = ccx.tcx().impl_or_trait_items(vtable_impl.impl_def_id) - .iter().filter_map(|&def_id| { - match ccx.tcx().impl_or_trait_item(def_id) { - ty::ConstTraitItem(ac) => Some(ac), - _ => None - } - }).find(|ic| ic.name == name); + let ac = ccx.tcx().associated_items(vtable_impl.impl_def_id) + .find(|item| item.kind == ty::AssociatedKind::Const && item.name == name); if let Some(ac) = ac { instance = Instance::new(ac.def_id, vtable_impl.substs); } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 8799050b1b999..540d8b7a77ab3 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -107,11 +107,6 @@ pub trait AstConv<'gcx, 'tcx> { fn get_type_parameter_bounds(&self, span: Span, def_id: ast::NodeId) -> Result>, ErrorReported>; - /// Returns true if the trait with id `trait_def_id` defines an - /// associated type with the name `name`. - fn trait_defines_associated_type_named(&self, trait_def_id: DefId, name: ast::Name) - -> bool; - /// Return an (optional) substitution to convert bound type parameters that /// are in scope into free ones. This function should only return Some /// within a fn body. @@ -833,6 +828,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { Some(self_ty)) } + fn trait_defines_associated_type_named(&self, + trait_def_id: DefId, + assoc_name: ast::Name) + -> bool + { + self.tcx().associated_items(trait_def_id).any(|item| { + item.kind == ty::AssociatedKind::Type && item.name == assoc_name + }) + } + fn ast_type_binding_to_poly_projection_predicate( &self, path_id: ast::NodeId, @@ -1146,20 +1151,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let mut associated_types = FnvHashSet::default(); for tr in traits::supertraits(tcx, principal) { - if let Some(trait_id) = tcx.map.as_local_node_id(tr.def_id()) { - use collect::trait_associated_type_names; - - associated_types.extend(trait_associated_type_names(tcx, trait_id) - .map(|name| (tr.def_id(), name))) - } else { - let trait_items = tcx.impl_or_trait_items(tr.def_id()); - associated_types.extend(trait_items.iter().filter_map(|&def_id| { - match tcx.impl_or_trait_item(def_id) { - ty::TypeTraitItem(ref item) => Some(item.name), - _ => None - } - }).map(|name| (tr.def_id(), name))); - } + associated_types.extend(tcx.associated_items(tr.def_id()) + .filter(|item| item.kind == ty::AssociatedKind::Type) + .map(|item| (tr.def_id(), item.name))); } for projection_bound in &projection_bounds { @@ -1262,14 +1256,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { if bounds.len() > 1 { let spans = bounds.iter().map(|b| { - self.tcx().impl_or_trait_items(b.def_id()).iter() - .find(|&&def_id| { - match self.tcx().impl_or_trait_item(def_id) { - ty::TypeTraitItem(ref item) => item.name.as_str() == assoc_name, - _ => false - } + self.tcx().associated_items(b.def_id()).find(|item| { + item.kind == ty::AssociatedKind::Type && item.name.as_str() == assoc_name }) - .and_then(|&def_id| self.tcx().map.as_local_node_id(def_id)) + .and_then(|item| self.tcx().map.as_local_node_id(item.def_id)) .and_then(|node_id| self.tcx().map.opt_span(node_id)) }); @@ -1385,25 +1375,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let trait_did = bound.0.def_id; let ty = self.projected_ty_from_poly_trait_ref(span, bound, assoc_name); - let item_did = if let Some(trait_id) = tcx.map.as_local_node_id(trait_did) { - // `ty::trait_items` used below requires information generated - // by type collection, which may be in progress at this point. - match tcx.map.expect_item(trait_id).node { - hir::ItemTrait(.., ref trait_items) => { - let item = trait_items.iter() - .find(|i| i.name == assoc_name) - .expect("missing associated type"); - tcx.map.local_def_id(item.id) - } - _ => bug!() - } - } else { - let trait_items = tcx.trait_items(trait_did); - let item = trait_items.iter().find(|i| i.name() == assoc_name); - item.expect("missing associated type").def_id() - }; - - (ty, Def::AssociatedTy(item_did)) + let item = tcx.associated_items(trait_did).find(|i| i.name == assoc_name); + (ty, Def::AssociatedTy(item.expect("missing associated type").def_id)) } fn qpath_to_ty(&self, @@ -1696,13 +1669,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { hir::TyBareFn(ref bf) => { require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span); let anon_scope = rscope.anon_type_scope(); - let (bare_fn_ty, _) = - self.ty_of_method_or_bare_fn(bf.unsafety, - bf.abi, - None, - &bf.decl, - anon_scope, - anon_scope); + let bare_fn_ty = self.ty_of_method_or_bare_fn(bf.unsafety, + bf.abi, + None, + &bf.decl, + anon_scope, + anon_scope); // Find any late-bound regions declared in return type that do // not appear in the arguments. These are not wellformed. @@ -1844,7 +1816,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { sig: &hir::MethodSig, untransformed_self_ty: Ty<'tcx>, anon_scope: Option) - -> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory<'tcx>) { + -> &'tcx ty::BareFnTy<'tcx> { self.ty_of_method_or_bare_fn(sig.unsafety, sig.abi, Some(untransformed_self_ty), @@ -1859,7 +1831,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { decl: &hir::FnDecl, anon_scope: Option) -> &'tcx ty::BareFnTy<'tcx> { - self.ty_of_method_or_bare_fn(unsafety, abi, None, decl, None, anon_scope).0 + self.ty_of_method_or_bare_fn(unsafety, abi, None, decl, None, anon_scope) } fn ty_of_method_or_bare_fn(&self, @@ -1869,7 +1841,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { decl: &hir::FnDecl, arg_anon_scope: Option, ret_anon_scope: Option) - -> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory<'tcx>) + -> &'tcx ty::BareFnTy<'tcx> { debug!("ty_of_method_or_bare_fn"); @@ -1882,13 +1854,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // lifetime elision, we can determine it in two ways. First (determined // here), if self is by-reference, then the implied output region is the // region of the self parameter. - let (self_ty, explicit_self_category) = match (opt_untransformed_self_ty, decl.get_self()) { + let (self_ty, explicit_self) = match (opt_untransformed_self_ty, decl.get_self()) { (Some(untransformed_self_ty), Some(explicit_self)) => { let self_type = self.determine_self_type(&rb, untransformed_self_ty, &explicit_self); - (Some(self_type.0), self_type.1) + (Some(self_type), Some(ExplicitSelf::determine(untransformed_self_ty, self_type))) } - _ => (None, ty::ExplicitSelfCategory::Static), + _ => (None, None), }; // HACK(eddyb) replace the fake self type in the AST with the actual type. @@ -1903,8 +1875,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // Second, if there was exactly one lifetime (either a substitution or a // reference) in the arguments, then any anonymous regions in the output // have that lifetime. - let implied_output_region = match explicit_self_category { - ty::ExplicitSelfCategory::ByReference(region, _) => Ok(*region), + let implied_output_region = match explicit_self { + Some(ExplicitSelf::ByReference(region, _)) => Ok(*region), _ => { // `pat_to_string` is expensive and // `find_implied_output_region` only needs its result when @@ -1930,7 +1902,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { debug!("ty_of_method_or_bare_fn: input_tys={:?}", input_tys); debug!("ty_of_method_or_bare_fn: output_ty={:?}", output_ty); - (self.tcx().mk_bare_fn(ty::BareFnTy { + self.tcx().mk_bare_fn(ty::BareFnTy { unsafety: unsafety, abi: abi, sig: ty::Binder(ty::FnSig { @@ -1938,95 +1910,30 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { output: output_ty, variadic: decl.variadic }), - }), explicit_self_category) + }) } fn determine_self_type<'a>(&self, rscope: &RegionScope, untransformed_self_ty: Ty<'tcx>, explicit_self: &hir::ExplicitSelf) - -> (Ty<'tcx>, ty::ExplicitSelfCategory<'tcx>) + -> Ty<'tcx> { - return match explicit_self.node { - SelfKind::Value(..) => { - (untransformed_self_ty, ty::ExplicitSelfCategory::ByValue) - } + match explicit_self.node { + SelfKind::Value(..) => untransformed_self_ty, SelfKind::Region(ref lifetime, mutability) => { let region = self.opt_ast_region_to_region( rscope, explicit_self.span, lifetime); - (self.tcx().mk_ref(region, + self.tcx().mk_ref(region, ty::TypeAndMut { ty: untransformed_self_ty, mutbl: mutability - }), - ty::ExplicitSelfCategory::ByReference(region, mutability)) - } - SelfKind::Explicit(ref ast_type, _) => { - let explicit_type = self.ast_ty_to_ty(rscope, &ast_type); - - // We wish to (for now) categorize an explicit self - // declaration like `self: SomeType` into either `self`, - // `&self`, `&mut self`, or `Box`. We do this here - // by some simple pattern matching. A more precise check - // is done later in `check_method_self_type()`. - // - // Examples: - // - // ``` - // impl Foo for &T { - // // Legal declarations: - // fn method1(self: &&T); // ExplicitSelfCategory::ByReference - // fn method2(self: &T); // ExplicitSelfCategory::ByValue - // fn method3(self: Box<&T>); // ExplicitSelfCategory::ByBox - // - // // Invalid cases will be caught later by `check_method_self_type`: - // fn method_err1(self: &mut T); // ExplicitSelfCategory::ByReference - // } - // ``` - // - // To do the check we just count the number of "modifiers" - // on each type and compare them. If they are the same or - // the impl has more, we call it "by value". Otherwise, we - // look at the outermost modifier on the method decl and - // call it by-ref, by-box as appropriate. For method1, for - // example, the impl type has one modifier, but the method - // type has two, so we end up with - // ExplicitSelfCategory::ByReference. - - let impl_modifiers = count_modifiers(untransformed_self_ty); - let method_modifiers = count_modifiers(explicit_type); - - debug!("determine_explicit_self_category(self_info.untransformed_self_ty={:?} \ - explicit_type={:?} \ - modifiers=({},{})", - untransformed_self_ty, - explicit_type, - impl_modifiers, - method_modifiers); - - let category = if impl_modifiers >= method_modifiers { - ty::ExplicitSelfCategory::ByValue - } else { - match explicit_type.sty { - ty::TyRef(r, mt) => ty::ExplicitSelfCategory::ByReference(r, mt.mutbl), - ty::TyBox(_) => ty::ExplicitSelfCategory::ByBox, - _ => ty::ExplicitSelfCategory::ByValue, - } - }; - - (explicit_type, category) - } - }; - - fn count_modifiers(ty: Ty) -> usize { - match ty.sty { - ty::TyRef(_, mt) => count_modifiers(mt.ty) + 1, - ty::TyBox(t) => count_modifiers(t) + 1, - _ => 0, + }) } + SelfKind::Explicit(ref ast_type, _) => self.ast_ty_to_ty(rscope, &ast_type) } } @@ -2336,3 +2243,64 @@ impl<'a, 'gcx, 'tcx> Bounds<'tcx> { vec } } + +pub enum ExplicitSelf<'tcx> { + ByValue, + ByReference(&'tcx ty::Region, hir::Mutability), + ByBox +} + +impl<'tcx> ExplicitSelf<'tcx> { + /// We wish to (for now) categorize an explicit self + /// declaration like `self: SomeType` into either `self`, + /// `&self`, `&mut self`, or `Box`. We do this here + /// by some simple pattern matching. A more precise check + /// is done later in `check_method_self_type()`. + /// + /// Examples: + /// + /// ``` + /// impl Foo for &T { + /// // Legal declarations: + /// fn method1(self: &&T); // ExplicitSelf::ByReference + /// fn method2(self: &T); // ExplicitSelf::ByValue + /// fn method3(self: Box<&T>); // ExplicitSelf::ByBox + /// + /// // Invalid cases will be caught later by `check_method_self_type`: + /// fn method_err1(self: &mut T); // ExplicitSelf::ByReference + /// } + /// ``` + /// + /// To do the check we just count the number of "modifiers" + /// on each type and compare them. If they are the same or + /// the impl has more, we call it "by value". Otherwise, we + /// look at the outermost modifier on the method decl and + /// call it by-ref, by-box as appropriate. For method1, for + /// example, the impl type has one modifier, but the method + /// type has two, so we end up with + /// ExplicitSelf::ByReference. + pub fn determine(untransformed_self_ty: Ty<'tcx>, + self_arg_ty: Ty<'tcx>) + -> ExplicitSelf<'tcx> { + fn count_modifiers(ty: Ty) -> usize { + match ty.sty { + ty::TyRef(_, mt) => count_modifiers(mt.ty) + 1, + ty::TyBox(t) => count_modifiers(t) + 1, + _ => 0, + } + } + + let impl_modifiers = count_modifiers(untransformed_self_ty); + let method_modifiers = count_modifiers(self_arg_ty); + + if impl_modifiers >= method_modifiers { + ExplicitSelf::ByValue + } else { + match self_arg_ty.sty { + ty::TyRef(r, mt) => ExplicitSelf::ByReference(r, mt.mutbl), + ty::TyBox(_) => ExplicitSelf::ByBox, + _ => ExplicitSelf::ByValue, + } + } + } +} diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 25e9f1f522c96..a3c77dd17d1f2 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -9,6 +9,8 @@ // except according to those terms. use middle::free_region::FreeRegionMap; +use rustc::hir; +use rustc::hir::def_id::DefId; use rustc::infer::{self, InferOk, TypeOrigin}; use rustc::ty; use rustc::traits::{self, Reveal}; @@ -21,6 +23,7 @@ use syntax_pos::Span; use CrateCtxt; use super::assoc; +use astconv::ExplicitSelf; /// Checks that a method from an impl conforms to the signature of /// the same method as declared in the trait. @@ -34,10 +37,10 @@ use super::assoc; /// - impl_trait_ref: the TraitRef corresponding to the trait implementation pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - impl_m: &ty::Method<'tcx>, + impl_m: &ty::AssociatedItem, impl_m_span: Span, impl_m_body_id: ast::NodeId, - trait_m: &ty::Method<'tcx>, + trait_m: &ty::AssociatedItem, impl_trait_ref: &ty::TraitRef<'tcx>, trait_item_span: Option) { debug!("compare_impl_method(impl_trait_ref={:?})", impl_trait_ref); @@ -56,48 +59,65 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // that the error messages you get out of this code are a bit more // inscrutable, particularly for cases where one method has no // self. - match (&trait_m.explicit_self, &impl_m.explicit_self) { - (&ty::ExplicitSelfCategory::Static, &ty::ExplicitSelfCategory::Static) => {} - (&ty::ExplicitSelfCategory::Static, _) => { + + let self_string = |method: &ty::AssociatedItem| { + let untransformed_self_ty = match method.container { + ty::ImplContainer(_) => impl_trait_ref.self_ty(), + ty::TraitContainer(_) => tcx.mk_self_type() + }; + let method_ty = tcx.lookup_item_type(method.def_id).ty; + let self_arg_ty = *method_ty.fn_sig().input(0).skip_binder(); + match ExplicitSelf::determine(untransformed_self_ty, self_arg_ty) { + ExplicitSelf::ByValue => "self".to_string(), + ExplicitSelf::ByReference(_, hir::MutImmutable) => "&self".to_string(), + ExplicitSelf::ByReference(_, hir::MutMutable) => "&mut self".to_string(), + _ => format!("self: {}", self_arg_ty) + } + }; + + match (trait_m.method_has_self_argument, impl_m.method_has_self_argument) { + (false, false) | (true, true) => {} + + (false, true) => { + let self_descr = self_string(impl_m); let mut err = struct_span_err!(tcx.sess, impl_m_span, E0185, "method `{}` has a `{}` declaration in the impl, but \ not in the trait", trait_m.name, - impl_m.explicit_self); - err.span_label(impl_m_span, - &format!("`{}` used in impl", impl_m.explicit_self)); + self_descr); + err.span_label(impl_m_span, &format!("`{}` used in impl", self_descr)); if let Some(span) = tcx.map.span_if_local(trait_m.def_id) { - err.span_label(span, - &format!("trait declared without `{}`", impl_m.explicit_self)); + err.span_label(span, &format!("trait declared without `{}`", self_descr)); } err.emit(); return; } - (_, &ty::ExplicitSelfCategory::Static) => { + + (true, false) => { + let self_descr = self_string(trait_m); let mut err = struct_span_err!(tcx.sess, impl_m_span, E0186, "method `{}` has a `{}` declaration in the trait, but \ not in the impl", trait_m.name, - trait_m.explicit_self); + self_descr); err.span_label(impl_m_span, - &format!("expected `{}` in impl", trait_m.explicit_self)); + &format!("expected `{}` in impl", self_descr)); if let Some(span) = tcx.map.span_if_local(trait_m.def_id) { - err.span_label(span, &format!("`{}` used in trait", trait_m.explicit_self)); + err.span_label(span, &format!("`{}` used in trait", self_descr)); } err.emit(); return; } - _ => { - // Let the type checker catch other errors below - } } - let num_impl_m_type_params = impl_m.generics.types.len(); - let num_trait_m_type_params = trait_m.generics.types.len(); + let impl_m_generics = tcx.lookup_generics(impl_m.def_id); + let trait_m_generics = tcx.lookup_generics(trait_m.def_id); + let num_impl_m_type_params = impl_m_generics.types.len(); + let num_trait_m_type_params = trait_m_generics.types.len(); if num_impl_m_type_params != num_trait_m_type_params { let impl_m_node_id = tcx.map.as_local_node_id(impl_m.def_id).unwrap(); let span = match tcx.map.expect_impl_item(impl_m_node_id).node { @@ -154,9 +174,17 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, return; } - if impl_m.fty.sig.0.inputs.len() != trait_m.fty.sig.0.inputs.len() { - let trait_number_args = trait_m.fty.sig.0.inputs.len(); - let impl_number_args = impl_m.fty.sig.0.inputs.len(); + let m_fty = |method: &ty::AssociatedItem| { + match tcx.lookup_item_type(method.def_id).ty.sty { + ty::TyFnDef(_, _, f) => f, + _ => bug!() + } + }; + let impl_m_fty = m_fty(impl_m); + let trait_m_fty = m_fty(trait_m); + if impl_m_fty.sig.0.inputs.len() != trait_m_fty.sig.0.inputs.len() { + let trait_number_args = trait_m_fty.sig.0.inputs.len(); + let impl_number_args = impl_m_fty.sig.0.inputs.len(); let trait_m_node_id = tcx.map.as_local_node_id(trait_m.def_id); let trait_span = if let Some(trait_id) = trait_m_node_id { match tcx.map.expect_trait_item(trait_id).node { @@ -295,7 +323,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // Create mapping from trait to skolemized. let trait_to_skol_substs = impl_to_skol_substs.rebase_onto(tcx, - impl_m.container_id(), + impl_m.container.id(), trait_to_impl_substs.subst(tcx, impl_to_skol_substs)); debug!("compare_impl_method: trait_to_skol_substs={:?}", @@ -305,9 +333,9 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // ParamBounds. if !check_region_bounds_on_impl_method(ccx, impl_m_span, - impl_m, - &trait_m.generics, - &impl_m.generics, + impl_m.name, + trait_m_generics, + impl_m_generics, trait_to_skol_substs, impl_to_skol_substs) { return; @@ -321,7 +349,8 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // environment. We can't just use `impl_env.caller_bounds`, // however, because we want to replace all late-bound regions with // region variables. - let impl_predicates = tcx.lookup_predicates(impl_m.predicates.parent.unwrap()); + let impl_m_predicates = tcx.lookup_predicates(impl_m.def_id); + let impl_predicates = tcx.lookup_predicates(impl_m_predicates.parent.unwrap()); let mut hybrid_preds = impl_predicates.instantiate(tcx, impl_to_skol_substs); debug!("compare_impl_method: impl_bounds={:?}", hybrid_preds); @@ -334,7 +363,8 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // We then register the obligations from the impl_m and check to see // if all constraints hold. hybrid_preds.predicates - .extend(trait_m.predicates.instantiate_own(tcx, trait_to_skol_substs).predicates); + .extend(tcx.lookup_predicates(trait_m.def_id) + .instantiate_own(tcx, trait_to_skol_substs).predicates); // Construct trait parameter environment and then shift it into the skolemized viewpoint. // The key step here is to update the caller_bounds's predicates to be @@ -351,7 +381,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let mut selcx = traits::SelectionContext::new(&infcx); - let impl_m_own_bounds = impl_m.predicates.instantiate_own(tcx, impl_to_skol_substs); + let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_skol_substs); let (impl_m_own_bounds, _) = infcx.replace_late_bound_regions_with_fresh_var(impl_m_span, infer::HigherRankedType, &ty::Binder(impl_m_own_bounds.predicates)); @@ -389,7 +419,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let (impl_sig, _) = infcx.replace_late_bound_regions_with_fresh_var(impl_m_span, infer::HigherRankedType, - &impl_m.fty.sig); + &impl_m_fty.sig); let impl_sig = impl_sig.subst(tcx, impl_to_skol_substs); let impl_sig = assoc::normalize_associated_types_in(&infcx, &mut fulfillment_cx, @@ -397,14 +427,14 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, impl_m_body_id, &impl_sig); let impl_fty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy { - unsafety: impl_m.fty.unsafety, - abi: impl_m.fty.abi, + unsafety: impl_m_fty.unsafety, + abi: impl_m_fty.abi, sig: ty::Binder(impl_sig.clone()), })); debug!("compare_impl_method: impl_fty={:?}", impl_fty); let trait_sig = tcx.liberate_late_bound_regions(infcx.parameter_environment.free_id_outlive, - &trait_m.fty.sig); + &trait_m_fty.sig); let trait_sig = trait_sig.subst(tcx, trait_to_skol_substs); let trait_sig = assoc::normalize_associated_types_in(&infcx, &mut fulfillment_cx, @@ -412,8 +442,8 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, impl_m_body_id, &trait_sig); let trait_fty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy { - unsafety: trait_m.fty.unsafety, - abi: trait_m.fty.abi, + unsafety: trait_m_fty.unsafety, + abi: trait_m_fty.abi, sig: ty::Binder(trait_sig.clone()), })); @@ -427,9 +457,9 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let (impl_err_span, trait_err_span) = extract_spans_for_error_reporting(&infcx, &terr, origin, - impl_m, + impl_m.def_id, impl_sig, - trait_m, + trait_m.def_id, trait_sig); let origin = TypeOrigin::MethodCompatCheck(impl_err_span); @@ -477,7 +507,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn check_region_bounds_on_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, span: Span, - impl_m: &ty::Method<'tcx>, + name: ast::Name, trait_generics: &ty::Generics<'tcx>, impl_generics: &ty::Generics<'tcx>, trait_to_skol_substs: &Substs<'tcx>, @@ -512,7 +542,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, E0195, "lifetime parameters or bounds on method `{}` do not match the \ trait declaration", - impl_m.name) + name) .span_label(span, &format!("lifetimes do not match trait")) .emit(); return false; @@ -524,13 +554,13 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, terr: &TypeError, origin: TypeOrigin, - impl_m: &ty::Method, + impl_m: DefId, impl_sig: ty::FnSig<'tcx>, - trait_m: &ty::Method, + trait_m: DefId, trait_sig: ty::FnSig<'tcx>) -> (Span, Option) { let tcx = infcx.tcx; - let impl_m_node_id = tcx.map.as_local_node_id(impl_m.def_id).unwrap(); + let impl_m_node_id = tcx.map.as_local_node_id(impl_m).unwrap(); let (impl_m_output, impl_m_iter) = match tcx.map.expect_impl_item(impl_m_node_id).node { ImplItemKind::Method(ref impl_m_sig, _) => { (&impl_m_sig.decl.output, impl_m_sig.decl.inputs.iter()) @@ -540,7 +570,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, match *terr { TypeError::Mutability => { - if let Some(trait_m_node_id) = tcx.map.as_local_node_id(trait_m.def_id) { + if let Some(trait_m_node_id) = tcx.map.as_local_node_id(trait_m) { let trait_m_iter = match tcx.map.expect_trait_item(trait_m_node_id).node { TraitItem_::MethodTraitItem(ref trait_m_sig, _) => { trait_m_sig.decl.inputs.iter() @@ -572,13 +602,13 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } } }) - .unwrap_or((origin.span(), tcx.map.span_if_local(trait_m.def_id))) + .unwrap_or((origin.span(), tcx.map.span_if_local(trait_m))) } else { - (origin.span(), tcx.map.span_if_local(trait_m.def_id)) + (origin.span(), tcx.map.span_if_local(trait_m)) } } TypeError::Sorts(ExpectedFound { .. }) => { - if let Some(trait_m_node_id) = tcx.map.as_local_node_id(trait_m.def_id) { + if let Some(trait_m_node_id) = tcx.map.as_local_node_id(trait_m) { let (trait_m_output, trait_m_iter) = match tcx.map.expect_trait_item(trait_m_node_id).node { TraitItem_::MethodTraitItem(ref trait_m_sig, _) => { @@ -604,22 +634,22 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, .is_err() { (impl_m_output.span(), Some(trait_m_output.span())) } else { - (origin.span(), tcx.map.span_if_local(trait_m.def_id)) + (origin.span(), tcx.map.span_if_local(trait_m)) } }) } else { - (origin.span(), tcx.map.span_if_local(trait_m.def_id)) + (origin.span(), tcx.map.span_if_local(trait_m)) } } - _ => (origin.span(), tcx.map.span_if_local(trait_m.def_id)), + _ => (origin.span(), tcx.map.span_if_local(trait_m)), } } } pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - impl_c: &ty::AssociatedConst<'tcx>, + impl_c: &ty::AssociatedItem, impl_c_span: Span, - trait_c: &ty::AssociatedConst<'tcx>, + trait_c: &ty::AssociatedItem, impl_trait_ref: &ty::TraitRef<'tcx>) { debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref); @@ -651,8 +681,8 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, trait_to_skol_substs); // Compute skolemized form of impl and trait const tys. - let impl_ty = impl_c.ty.subst(tcx, impl_to_skol_substs); - let trait_ty = trait_c.ty.subst(tcx, trait_to_skol_substs); + let impl_ty = tcx.lookup_item_type(impl_c.def_id).ty.subst(tcx, impl_to_skol_substs); + let trait_ty = tcx.lookup_item_type(trait_c.def_id).ty.subst(tcx, trait_to_skol_substs); let mut origin = TypeOrigin::Misc(impl_c_span); let err = infcx.commit_if_ok(|_| { diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 5e2b49bac1b2f..4cae960b8ea35 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -547,9 +547,9 @@ fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, // attributes attached to the impl's generics. let dtor_method = adt_def.destructor() .expect("dtorck type without destructor impossible"); - let method = tcx.impl_or_trait_item(dtor_method); - let impl_id: DefId = method.container().id(); - let revised_ty = revise_self_ty(tcx, adt_def, impl_id, substs); + let method = tcx.associated_item(dtor_method); + let impl_def_id = method.container.id(); + let revised_ty = revise_self_ty(tcx, adt_def, impl_def_id, substs); return DropckKind::RevisedSelf(revised_ty); } ty::TyTrait(..) | ty::TyProjection(..) | ty::TyAnon(..) => { diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 722089cd50c0c..3ef6b6cb650db 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -37,16 +37,6 @@ impl<'a, 'gcx, 'tcx> Deref for ConfirmContext<'a, 'gcx, 'tcx> { } } -struct InstantiatedMethodSig<'tcx> { - /// Function signature of the method being invoked. The 0th - /// argument is the receiver. - method_sig: ty::FnSig<'tcx>, - - /// Generic bounds on the method's parameters which must be added - /// as pending obligations. - method_predicates: ty::InstantiatedPredicates<'tcx>, -} - impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn confirm_method(&self, span: Span, @@ -98,31 +88,18 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { debug!("all_substs={:?}", all_substs); // Create the final signature for the method, replacing late-bound regions. - let InstantiatedMethodSig { method_sig, method_predicates } = - self.instantiate_method_sig(&pick, all_substs); - let method_self_ty = method_sig.inputs[0]; + let (method_ty, method_predicates) = self.instantiate_method_sig(&pick, all_substs); // Unify the (adjusted) self type with what the method expects. - self.unify_receivers(self_ty, method_self_ty); - - // Create the method type - let def_id = pick.item.def_id(); - let method_ty = pick.item.as_opt_method().unwrap(); - let fty = self.tcx.mk_fn_def(def_id, - all_substs, - self.tcx.mk_bare_fn(ty::BareFnTy { - sig: ty::Binder(method_sig), - unsafety: method_ty.fty.unsafety, - abi: method_ty.fty.abi.clone(), - })); + self.unify_receivers(self_ty, method_ty.fn_sig().input(0).skip_binder()); // Add any trait/regions obligations specified on the method's type parameters. - self.add_obligations(fty, all_substs, &method_predicates); + self.add_obligations(method_ty, all_substs, &method_predicates); // Create the final `MethodCallee`. let callee = ty::MethodCallee { - def_id: def_id, - ty: fty, + def_id: pick.item.def_id, + ty: method_ty, substs: all_substs, }; @@ -193,7 +170,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { -> &'tcx Substs<'tcx> { match pick.kind { probe::InherentImplPick => { - let impl_def_id = pick.item.container().id(); + let impl_def_id = pick.item.container.id(); assert!(self.tcx.impl_trait_ref(impl_def_id).is_none(), "impl {:?} is not an inherent impl", impl_def_id); @@ -201,7 +178,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { } probe::ObjectPick => { - let trait_def_id = pick.item.container().id(); + let trait_def_id = pick.item.container.id(); self.extract_existential_trait_ref(self_ty, |this, object_ty, principal| { // The object data has no entry for the Self // Type. For the purposes of this method call, we @@ -244,7 +221,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { } probe::TraitPick => { - let trait_def_id = pick.item.container().id(); + let trait_def_id = pick.item.container.id(); // Make a trait reference `$0 : Trait<$1...$n>` // consisting entirely of type variables. Later on in @@ -299,8 +276,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // If they were not explicitly supplied, just construct fresh // variables. let num_supplied_types = supplied_method_types.len(); - let method = pick.item.as_opt_method().unwrap(); - let num_method_types = method.generics.types.len(); + let method_generics = self.tcx.lookup_generics(pick.item.def_id); + let num_method_types = method_generics.types.len(); if num_supplied_types > 0 && num_supplied_types != num_method_types { if num_method_types == 0 { @@ -332,18 +309,15 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // parameters from the type and those from the method. // // FIXME -- permit users to manually specify lifetimes - let supplied_start = substs.params().len() + method.generics.regions.len(); - Substs::for_item(self.tcx, - method.def_id, - |def, _| { + let supplied_start = substs.params().len() + method_generics.regions.len(); + Substs::for_item(self.tcx, pick.item.def_id, |def, _| { let i = def.index as usize; if i < substs.params().len() { substs.region_at(i) } else { self.region_var_for_def(self.span, def) } - }, - |def, cur_substs| { + }, |def, cur_substs| { let i = def.index as usize; if i < substs.params().len() { substs.type_at(i) @@ -376,7 +350,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { fn instantiate_method_sig(&mut self, pick: &probe::Pick<'tcx>, all_substs: &'tcx Substs<'tcx>) - -> InstantiatedMethodSig<'tcx> { + -> (Ty<'tcx>, ty::InstantiatedPredicates<'tcx>) { debug!("instantiate_method_sig(pick={:?}, all_substs={:?})", pick, all_substs); @@ -384,36 +358,40 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // Instantiate the bounds on the method with the // type/early-bound-regions substitutions performed. There can // be no late-bound regions appearing here. - let method_predicates = pick.item - .as_opt_method() - .unwrap() - .predicates - .instantiate(self.tcx, all_substs); - let method_predicates = self.normalize_associated_types_in(self.span, &method_predicates); + let def_id = pick.item.def_id; + let method_predicates = self.tcx.lookup_predicates(def_id) + .instantiate(self.tcx, all_substs); + let method_predicates = self.normalize_associated_types_in(self.span, + &method_predicates); debug!("method_predicates after subst = {:?}", method_predicates); + let fty = match self.tcx.lookup_item_type(def_id).ty.sty { + ty::TyFnDef(_, _, f) => f, + _ => bug!() + }; + // Instantiate late-bound regions and substitute the trait // parameters into the method type to get the actual method type. // // NB: Instantiate late-bound regions first so that // `instantiate_type_scheme` can normalize associated types that // may reference those regions. - let method_sig = self.replace_late_bound_regions_with_fresh_var(&pick.item - .as_opt_method() - .unwrap() - .fty - .sig); + let method_sig = self.replace_late_bound_regions_with_fresh_var(&fty.sig); debug!("late-bound lifetimes from method instantiated, method_sig={:?}", method_sig); let method_sig = self.instantiate_type_scheme(self.span, all_substs, &method_sig); debug!("type scheme substituted, method_sig={:?}", method_sig); - InstantiatedMethodSig { - method_sig: method_sig, - method_predicates: method_predicates, - } + let method_ty = self.tcx.mk_fn_def(def_id, all_substs, + self.tcx.mk_bare_fn(ty::BareFnTy { + sig: ty::Binder(method_sig), + unsafety: fty.unsafety, + abi: fty.abi, + })); + + (method_ty, method_predicates) } fn add_obligations(&mut self, @@ -583,7 +561,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { fn enforce_illegal_method_limitations(&self, pick: &probe::Pick) { // Disallow calls to the method `drop` defined in the `Drop` trait. - match pick.item.container() { + match pick.item.container { ty::TraitContainer(trait_def_id) => { callee::check_legal_trait_for_method_call(self.ccx, self.span, trait_def_id) } diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index f084b85a45f81..f1a46c62a55bf 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -228,14 +228,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Trait must have a method named `m_name` and it should not have // type parameters or early-bound regions. let tcx = self.tcx; - let method_item = self.impl_or_trait_item(trait_def_id, m_name).unwrap(); - let method_ty = method_item.as_opt_method().unwrap(); - assert_eq!(method_ty.generics.types.len(), 0); - assert_eq!(method_ty.generics.regions.len(), 0); + let method_item = self.associated_item(trait_def_id, m_name).unwrap(); + let def_id = method_item.def_id; + let generics = tcx.lookup_generics(def_id); + assert_eq!(generics.types.len(), 0); + assert_eq!(generics.regions.len(), 0); - debug!("lookup_in_trait_adjusted: method_item={:?} method_ty={:?}", - method_item, - method_ty); + debug!("lookup_in_trait_adjusted: method_item={:?}", method_item); // Instantiate late-bound regions and substitute the trait // parameters into the method type to get the actual method type. @@ -243,22 +242,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // NB: Instantiate late-bound regions first so that // `instantiate_type_scheme` can normalize associated types that // may reference those regions. - let fn_sig = - self.replace_late_bound_regions_with_fresh_var(span, infer::FnCall, &method_ty.fty.sig) - .0; + let original_method_ty = tcx.lookup_item_type(def_id).ty; + let fty = match original_method_ty.sty { + ty::TyFnDef(_, _, f) => f, + _ => bug!() + }; + let fn_sig = self.replace_late_bound_regions_with_fresh_var(span, + infer::FnCall, + &fty.sig).0; let fn_sig = self.instantiate_type_scheme(span, trait_ref.substs, &fn_sig); let transformed_self_ty = fn_sig.inputs[0]; - let def_id = method_item.def_id(); - let fty = tcx.mk_fn_def(def_id, - trait_ref.substs, - tcx.mk_bare_fn(ty::BareFnTy { - sig: ty::Binder(fn_sig), - unsafety: method_ty.fty.unsafety, - abi: method_ty.fty.abi.clone(), - })); - - debug!("lookup_in_trait_adjusted: matched method fty={:?} obligation={:?}", - fty, + let method_ty = tcx.mk_fn_def(def_id, trait_ref.substs, + tcx.mk_bare_fn(ty::BareFnTy { + sig: ty::Binder(fn_sig), + unsafety: fty.unsafety, + abi: fty.abi + })); + + debug!("lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}", + method_ty, obligation); // Register obligations for the parameters. This will include the @@ -269,13 +271,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // // Note that as the method comes from a trait, it should not have // any late-bound regions appearing in its bounds. - let method_bounds = self.instantiate_bounds(span, trait_ref.substs, &method_ty.predicates); + let method_bounds = self.instantiate_bounds(span, def_id, trait_ref.substs); assert!(!method_bounds.has_escaping_regions()); self.add_obligations_for_parameters(traits::ObligationCause::misc(span, self.body_id), &method_bounds); // Also register an obligation for the method type being well-formed. - self.register_wf_obligation(fty, span, traits::MiscObligation); + self.register_wf_obligation(method_ty, span, traits::MiscObligation); // FIXME(#18653) -- Try to resolve obligations, giving us more // typing information, which can sometimes be needed to avoid @@ -283,61 +285,38 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.select_obligations_where_possible(); // Insert any adjustments needed (always an autoref of some mutability). - match self_expr { - None => {} - - Some(self_expr) => { - debug!("lookup_in_trait_adjusted: inserting adjustment if needed \ - (self-id={}, autoderefs={}, unsize={}, explicit_self={:?})", - self_expr.id, - autoderefs, - unsize, - method_ty.explicit_self); - - match method_ty.explicit_self { - ty::ExplicitSelfCategory::ByValue => { - // Trait method is fn(self), no transformation needed. - assert!(!unsize); - self.write_autoderef_adjustment(self_expr.id, autoderefs); - } - - ty::ExplicitSelfCategory::ByReference(..) => { - // Trait method is fn(&self) or fn(&mut self), need an - // autoref. Pull the region etc out of the type of first argument. - match transformed_self_ty.sty { - ty::TyRef(region, ty::TypeAndMut { mutbl, ty: _ }) => { - self.write_adjustment(self_expr.id, - AdjustDerefRef(AutoDerefRef { - autoderefs: autoderefs, - autoref: Some(AutoPtr(region, mutbl)), - unsize: if unsize { - Some(transformed_self_ty) - } else { - None - }, - })); - } - - _ => { - span_bug!(span, - "trait method is &self but first arg is: {}", - transformed_self_ty); + if let Some(self_expr) = self_expr { + debug!("lookup_in_trait_adjusted: inserting adjustment if needed \ + (self-id={}, autoderefs={}, unsize={}, fty={:?})", + self_expr.id, autoderefs, unsize, original_method_ty); + + let original_sig = original_method_ty.fn_sig(); + match (&original_sig.input(0).skip_binder().sty, &transformed_self_ty.sty) { + (&ty::TyRef(..), &ty::TyRef(region, ty::TypeAndMut { mutbl, ty: _ })) => { + // Trait method is fn(&self) or fn(&mut self), need an + // autoref. Pull the region etc out of the type of first argument. + self.write_adjustment(self_expr.id, + AdjustDerefRef(AutoDerefRef { + autoderefs: autoderefs, + autoref: Some(AutoPtr(region, mutbl)), + unsize: if unsize { + Some(transformed_self_ty) + } else { + None } - } - } - - _ => { - span_bug!(span, - "unexpected explicit self type in operator method: {:?}", - method_ty.explicit_self); - } + })); + } + _ => { + // Trait method is fn(self), no transformation needed. + assert!(!unsize); + self.write_autoderef_adjustment(self_expr.id, autoderefs); } } } let callee = ty::MethodCallee { def_id: def_id, - ty: fty, + ty: method_ty, substs: trait_ref.substs, }; @@ -361,7 +340,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let def = pick.item.def(); if let probe::InherentImplPick = pick.kind { - if !pick.item.vis().is_accessible_from(self.body_id, &self.tcx.map) { + if !pick.item.vis.is_accessible_from(self.body_id, &self.tcx.map) { let msg = format!("{} `{}` is private", def.kind_name(), &method_name.as_str()); self.tcx.sess.span_err(span, &msg); } @@ -371,14 +350,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// Find item with name `item_name` defined in impl/trait `def_id` /// and return it, or `None`, if no such item was defined there. - pub fn impl_or_trait_item(&self, - def_id: DefId, - item_name: ast::Name) - -> Option> { - self.tcx - .impl_or_trait_items(def_id) - .iter() - .map(|&did| self.tcx.impl_or_trait_item(did)) - .find(|m| m.name() == item_name) + pub fn associated_item(&self, def_id: DefId, item_name: ast::Name) + -> Option { + self.tcx.associated_items(def_id).find(|item| item.name == item_name) } } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 43837de2f345d..6e34e919f6f1b 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -72,7 +72,7 @@ struct CandidateStep<'tcx> { #[derive(Debug)] struct Candidate<'tcx> { xform_self_ty: Ty<'tcx>, - item: ty::ImplOrTraitItem<'tcx>, + item: ty::AssociatedItem, kind: CandidateKind<'tcx>, import_id: Option, } @@ -95,7 +95,7 @@ enum CandidateKind<'tcx> { #[derive(Debug)] pub struct Pick<'tcx> { - pub item: ty::ImplOrTraitItem<'tcx>, + pub item: ty::AssociatedItem, pub kind: PickKind<'tcx>, pub import_id: Option, @@ -384,8 +384,6 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { fn assemble_inherent_impl_for_primitive(&mut self, lang_def_id: Option) { if let Some(impl_def_id) = lang_def_id { - self.tcx.populate_implementations_for_primitive_if_necessary(impl_def_id); - self.assemble_inherent_impl_probe(impl_def_id); } } @@ -409,7 +407,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { debug!("assemble_inherent_impl_probe {:?}", impl_def_id); - let item = match self.impl_or_trait_item(impl_def_id) { + let item = match self.associated_item(impl_def_id) { Some(m) => m, None => { return; @@ -421,7 +419,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { return self.record_static_candidate(ImplSource(impl_def_id)); } - if !item.vis().is_accessible_from(self.body_id, &self.tcx.map) { + if !item.vis.is_accessible_from(self.body_id, &self.tcx.map) { self.private_candidate = Some(item.def()); return; } @@ -512,17 +510,6 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { let xform_self_ty = this.xform_self_ty(&item, trait_ref.self_ty(), trait_ref.substs); - if let Some(ref m) = item.as_opt_method() { - debug!("found match: trait_ref={:?} substs={:?} m={:?}", - trait_ref, - trait_ref.substs, - m); - assert_eq!(m.generics.parent_types as usize, - trait_ref.substs.types().count()); - assert_eq!(m.generics.parent_regions as usize, - trait_ref.substs.regions().count()); - } - // Because this trait derives from a where-clause, it // should not contain any inference variables or other // artifacts. This means it is safe to put into the @@ -544,13 +531,13 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { fn elaborate_bounds(&mut self, bounds: &[ty::PolyTraitRef<'tcx>], mut mk_cand: F) where F: for<'b> FnMut(&mut ProbeContext<'b, 'gcx, 'tcx>, ty::PolyTraitRef<'tcx>, - ty::ImplOrTraitItem<'tcx>) + ty::AssociatedItem) { debug!("elaborate_bounds(bounds={:?})", bounds); let tcx = self.tcx; for bound_trait_ref in traits::transitive_bounds(tcx, bounds) { - let item = match self.impl_or_trait_item(bound_trait_ref.def_id()) { + let item = match self.associated_item(bound_trait_ref.def_id()) { Some(v) => v, None => { continue; @@ -601,9 +588,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { trait_def_id); // Check whether `trait_def_id` defines a method with suitable name: - let trait_items = self.tcx.trait_items(trait_def_id); - let maybe_item = trait_items.iter() - .find(|item| item.name() == self.item_name); + let maybe_item = self.tcx.associated_items(trait_def_id) + .find(|item| item.name == self.item_name); let item = match maybe_item { Some(i) => i, None => { @@ -612,7 +598,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { }; // Check whether `trait_def_id` defines a method with suitable name: - if !self.has_applicable_self(item) { + if !self.has_applicable_self(&item) { debug!("method has inapplicable self"); self.record_static_candidate(TraitSource(trait_def_id)); return Ok(()); @@ -631,7 +617,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { fn assemble_extension_candidates_for_trait_impls(&mut self, trait_def_id: DefId, - item: ty::ImplOrTraitItem<'tcx>) { + item: ty::AssociatedItem) { let trait_def = self.tcx.lookup_trait_def(trait_def_id); // FIXME(arielb1): can we use for_each_relevant_impl here? @@ -700,7 +686,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { fn assemble_closure_candidates(&mut self, trait_def_id: DefId, - item: ty::ImplOrTraitItem<'tcx>) + item: ty::AssociatedItem) -> Result<(), MethodError<'tcx>> { // Check if this is one of the Fn,FnMut,FnOnce traits. let tcx = self.tcx; @@ -765,7 +751,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { fn assemble_projection_candidates(&mut self, trait_def_id: DefId, - item: ty::ImplOrTraitItem<'tcx>) { + item: ty::AssociatedItem) { debug!("assemble_projection_candidates(\ trait_def_id={:?}, \ item={:?})", @@ -820,7 +806,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { fn assemble_where_clause_candidates(&mut self, trait_def_id: DefId, - item: ty::ImplOrTraitItem<'tcx>) { + item: ty::AssociatedItem) { debug!("assemble_where_clause_candidates(trait_def_id={:?})", trait_def_id); @@ -865,7 +851,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { self.assemble_extension_candidates_for_all_traits()?; let out_of_scope_traits = match self.pick_core() { - Some(Ok(p)) => vec![p.item.container().id()], + Some(Ok(p)) => vec![p.item.container.id()], Some(Err(MethodError::Ambiguity(v))) => { v.into_iter() .map(|source| { @@ -1065,7 +1051,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // don't have enough information to fully evaluate). let (impl_def_id, substs, ref_obligations) = match probe.kind { InherentImplCandidate(ref substs, ref ref_obligations) => { - (probe.item.container().id(), substs, ref_obligations) + (probe.item.container.id(), substs, ref_obligations) } ExtensionImplCandidate(impl_def_id, ref substs, ref ref_obligations) => { @@ -1128,12 +1114,12 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { /// use, so it's ok to just commit to "using the method from the trait Foo". fn collapse_candidates_to_trait_pick(&self, probes: &[&Candidate<'tcx>]) -> Option> { // Do all probes correspond to the same trait? - let container = probes[0].item.container(); + let container = probes[0].item.container; match container { ty::TraitContainer(_) => {} ty::ImplContainer(_) => return None, } - if probes[1..].iter().any(|p| p.item.container() != container) { + if probes[1..].iter().any(|p| p.item.container != container) { return None; } @@ -1150,19 +1136,11 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { /////////////////////////////////////////////////////////////////////////// // MISCELLANY - fn has_applicable_self(&self, item: &ty::ImplOrTraitItem) -> bool { + fn has_applicable_self(&self, item: &ty::AssociatedItem) -> bool { // "fast track" -- check for usage of sugar - match *item { - ty::ImplOrTraitItem::MethodTraitItem(ref method) => { - match method.explicit_self { - ty::ExplicitSelfCategory::Static => self.mode == Mode::Path, - ty::ExplicitSelfCategory::ByValue | - ty::ExplicitSelfCategory::ByReference(..) | - ty::ExplicitSelfCategory::ByBox => true, - } - } - ty::ImplOrTraitItem::ConstTraitItem(..) => self.mode == Mode::Path, - _ => false, + match self.mode { + Mode::MethodCall => item.method_has_self_argument, + Mode::Path => true } // FIXME -- check for types that deref to `Self`, // like `Rc` and so on. @@ -1177,24 +1155,26 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { } fn xform_self_ty(&self, - item: &ty::ImplOrTraitItem<'tcx>, + item: &ty::AssociatedItem, impl_ty: Ty<'tcx>, substs: &Substs<'tcx>) -> Ty<'tcx> { - match item.as_opt_method() { - Some(ref method) => self.xform_method_self_ty(method, impl_ty, substs), - None => impl_ty, + if item.kind == ty::AssociatedKind::Method && self.mode == Mode::MethodCall { + self.xform_method_self_ty(item.def_id, impl_ty, substs) + } else { + impl_ty } } fn xform_method_self_ty(&self, - method: &Rc>, + method: DefId, impl_ty: Ty<'tcx>, substs: &Substs<'tcx>) -> Ty<'tcx> { + let self_ty = self.tcx.lookup_item_type(method).ty.fn_sig().input(0); debug!("xform_self_ty(impl_ty={:?}, self_ty={:?}, substs={:?})", impl_ty, - method.fty.sig.0.inputs.get(0), + self_ty, substs); assert!(!substs.has_escaping_regions()); @@ -1204,26 +1184,18 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // are given do not include type/lifetime parameters for the // method yet. So create fresh variables here for those too, // if there are any. - assert_eq!(substs.types().count(), - method.generics.parent_types as usize); - assert_eq!(substs.regions().count(), - method.generics.parent_regions as usize); - - if self.mode == Mode::Path { - return impl_ty; - } + let generics = self.tcx.lookup_generics(method); + assert_eq!(substs.types().count(), generics.parent_types as usize); + assert_eq!(substs.regions().count(), generics.parent_regions as usize); // Erase any late-bound regions from the method and substitute // in the values from the substitution. - let xform_self_ty = method.fty.sig.input(0); - let xform_self_ty = self.erase_late_bound_regions(&xform_self_ty); + let xform_self_ty = self.erase_late_bound_regions(&self_ty); - if method.generics.types.is_empty() && method.generics.regions.is_empty() { + if generics.types.is_empty() && generics.regions.is_empty() { xform_self_ty.subst(self.tcx, substs) } else { - let substs = Substs::for_item(self.tcx, - method.def_id, - |def, _| { + let substs = Substs::for_item(self.tcx, method, |def, _| { let i = def.index as usize; if i < substs.params().len() { substs.region_at(i) @@ -1232,8 +1204,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // `impl_self_ty()` for an explanation. self.tcx.mk_region(ty::ReErased) } - }, - |def, cur_substs| { + }, |def, cur_substs| { let i = def.index as usize; if i < substs.params().len() { substs.type_at(i) @@ -1283,8 +1254,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { /// Find item with name `item_name` defined in impl/trait `def_id` /// and return it, or `None`, if no such item was defined there. - fn impl_or_trait_item(&self, def_id: DefId) -> Option> { - self.fcx.impl_or_trait_item(def_id, self.item_name) + fn associated_item(&self, def_id: DefId) -> Option { + self.fcx.associated_item(def_id, self.item_name) } } @@ -1317,11 +1288,11 @@ impl<'tcx> Candidate<'tcx> { fn to_source(&self) -> CandidateSource { match self.kind { - InherentImplCandidate(..) => ImplSource(self.item.container().id()), + InherentImplCandidate(..) => ImplSource(self.item.container.id()), ExtensionImplCandidate(def_id, ..) => ImplSource(def_id), ObjectCandidate | TraitCandidate | - WhereClauseCandidate(_) => TraitSource(self.item.container().id()), + WhereClauseCandidate(_) => TraitSource(self.item.container.id()), } } } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 32bf839a4ed4e..07dd4fc7fb713 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -89,20 +89,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { CandidateSource::ImplSource(impl_did) => { // Provide the best span we can. Use the item, if local to crate, else // the impl, if local to crate (item may be defaulted), else nothing. - let item = self.impl_or_trait_item(impl_did, item_name) + let item = self.associated_item(impl_did, item_name) .or_else(|| { - self.impl_or_trait_item(self.tcx - .impl_trait_ref(impl_did) - .unwrap() - .def_id, - - item_name) - }) - .unwrap(); - let note_span = self.tcx - .map - .span_if_local(item.def_id()) - .or_else(|| self.tcx.map.span_if_local(impl_did)); + self.associated_item( + self.tcx.impl_trait_ref(impl_did).unwrap().def_id, + + item_name + ) + }).unwrap(); + let note_span = self.tcx.map.span_if_local(item.def_id).or_else(|| { + self.tcx.map.span_if_local(impl_did) + }); let impl_ty = self.impl_self_ty(span, impl_did).ty; @@ -127,8 +124,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } CandidateSource::TraitSource(trait_did) => { - let item = self.impl_or_trait_item(trait_did, item_name).unwrap(); - let item_span = self.tcx.map.def_id_span(item.def_id(), span); + let item = self.associated_item(trait_did, item_name).unwrap(); + let item_span = self.tcx.map.def_id_span(item.def_id, span); span_note!(err, item_span, "candidate #{} is defined in the trait `{}`", @@ -334,8 +331,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // this isn't perfect (that is, there are cases when // implementing a trait would be legal but is rejected // here). - (type_is_local || info.def_id.is_local()) && - self.impl_or_trait_item(info.def_id, item_name).is_some() + (type_is_local || info.def_id.is_local()) + && self.associated_item(info.def_id, item_name).is_some() }) .collect::>(); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 75a14bb3db922..80d94599c1903 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -938,21 +938,13 @@ fn check_specialization_validity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { let ancestors = trait_def.ancestors(impl_id); - let parent = match impl_item.node { - hir::ImplItemKind::Const(..) => { - ancestors.const_defs(tcx, impl_item.name).skip(1).next() - .map(|node_item| node_item.map(|parent| parent.defaultness)) - } - hir::ImplItemKind::Method(..) => { - ancestors.fn_defs(tcx, impl_item.name).skip(1).next() - .map(|node_item| node_item.map(|parent| parent.defaultness)) - - } - hir::ImplItemKind::Type(_) => { - ancestors.type_defs(tcx, impl_item.name).skip(1).next() - .map(|node_item| node_item.map(|parent| parent.defaultness)) - } + let kind = match impl_item.node { + hir::ImplItemKind::Const(..) => ty::AssociatedKind::Const, + hir::ImplItemKind::Method(..) => ty::AssociatedKind::Method, + hir::ImplItemKind::Type(_) => ty::AssociatedKind::Type }; + let parent = ancestors.defs(tcx, impl_item.name, kind).skip(1).next() + .map(|node_item| node_item.map(|parent| parent.defaultness)); if let Some(parent) = parent { if parent.item.is_final() { @@ -975,93 +967,77 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // Locate trait definition and items let tcx = ccx.tcx; let trait_def = tcx.lookup_trait_def(impl_trait_ref.def_id); - let trait_items = tcx.trait_items(impl_trait_ref.def_id); let mut overridden_associated_type = None; // Check existing impl methods to see if they are both present in trait // and compatible with trait signature for impl_item in impl_items { - let ty_impl_item = tcx.impl_or_trait_item(tcx.map.local_def_id(impl_item.id)); - let ty_trait_item = trait_items.iter() - .find(|ac| ac.name() == ty_impl_item.name()); + let ty_impl_item = tcx.associated_item(tcx.map.local_def_id(impl_item.id)); + let ty_trait_item = tcx.associated_items(impl_trait_ref.def_id) + .find(|ac| ac.name == ty_impl_item.name); // Check that impl definition matches trait definition if let Some(ty_trait_item) = ty_trait_item { match impl_item.node { hir::ImplItemKind::Const(..) => { - let impl_const = match ty_impl_item { - ty::ConstTraitItem(ref cti) => cti, - _ => span_bug!(impl_item.span, "non-const impl-item for const") - }; - // Find associated const definition. - if let &ty::ConstTraitItem(ref trait_const) = ty_trait_item { + if ty_trait_item.kind == ty::AssociatedKind::Const { compare_const_impl(ccx, - &impl_const, + &ty_impl_item, impl_item.span, - trait_const, + &ty_trait_item, &impl_trait_ref); } else { let mut err = struct_span_err!(tcx.sess, impl_item.span, E0323, "item `{}` is an associated const, \ which doesn't match its trait `{:?}`", - impl_const.name, + ty_impl_item.name, impl_trait_ref); err.span_label(impl_item.span, &format!("does not match trait")); // We can only get the spans from local trait definition // Same for E0324 and E0325 - if let Some(trait_span) = tcx.map.span_if_local(ty_trait_item.def_id()) { + if let Some(trait_span) = tcx.map.span_if_local(ty_trait_item.def_id) { err.span_label(trait_span, &format!("item in trait")); } err.emit() } } hir::ImplItemKind::Method(_, ref body) => { - let impl_method = match ty_impl_item { - ty::MethodTraitItem(ref mti) => mti, - _ => span_bug!(impl_item.span, "non-method impl-item for method") - }; - - let trait_span = tcx.map.span_if_local(ty_trait_item.def_id()); - if let &ty::MethodTraitItem(ref trait_method) = ty_trait_item { + let trait_span = tcx.map.span_if_local(ty_trait_item.def_id); + if ty_trait_item.kind == ty::AssociatedKind::Method { compare_impl_method(ccx, - &impl_method, + &ty_impl_item, impl_item.span, body.id, - &trait_method, + &ty_trait_item, &impl_trait_ref, trait_span); } else { let mut err = struct_span_err!(tcx.sess, impl_item.span, E0324, "item `{}` is an associated method, \ which doesn't match its trait `{:?}`", - impl_method.name, + ty_impl_item.name, impl_trait_ref); err.span_label(impl_item.span, &format!("does not match trait")); - if let Some(trait_span) = tcx.map.span_if_local(ty_trait_item.def_id()) { + if let Some(trait_span) = tcx.map.span_if_local(ty_trait_item.def_id) { err.span_label(trait_span, &format!("item in trait")); } err.emit() } } hir::ImplItemKind::Type(_) => { - let impl_type = match ty_impl_item { - ty::TypeTraitItem(ref tti) => tti, - _ => span_bug!(impl_item.span, "non-type impl-item for type") - }; - - if let &ty::TypeTraitItem(ref at) = ty_trait_item { - if let Some(_) = at.ty { + if ty_trait_item.kind == ty::AssociatedKind::Type { + if ty_trait_item.has_value { overridden_associated_type = Some(impl_item); } } else { let mut err = struct_span_err!(tcx.sess, impl_item.span, E0325, "item `{}` is an associated type, \ which doesn't match its trait `{:?}`", - impl_type.name, + ty_impl_item.name, impl_trait_ref); err.span_label(impl_item.span, &format!("does not match trait")); - if let Some(trait_span) = tcx.map.span_if_local(ty_trait_item.def_id()) { + if let Some(trait_span) = tcx.map.span_if_local(ty_trait_item.def_id) { err.span_label(trait_span, &format!("item in trait")); } err.emit() @@ -1074,49 +1050,21 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, } // Check for missing items from trait - let provided_methods = tcx.provided_trait_methods(impl_trait_ref.def_id); let mut missing_items = Vec::new(); let mut invalidated_items = Vec::new(); let associated_type_overridden = overridden_associated_type.is_some(); - for trait_item in trait_items.iter() { - let is_implemented; - let is_provided; - - match *trait_item { - ty::ConstTraitItem(ref associated_const) => { - is_provided = associated_const.has_value; - is_implemented = impl_items.iter().any(|ii| { - match ii.node { - hir::ImplItemKind::Const(..) => { - ii.name == associated_const.name - } - _ => false, - } - }); - } - ty::MethodTraitItem(ref trait_method) => { - is_provided = provided_methods.iter().any(|m| m.name == trait_method.name); - is_implemented = trait_def.ancestors(impl_id) - .fn_defs(tcx, trait_method.name) - .next() - .map(|node_item| !node_item.node.is_from_trait()) - .unwrap_or(false); - } - ty::TypeTraitItem(ref trait_assoc_ty) => { - is_provided = trait_assoc_ty.ty.is_some(); - is_implemented = trait_def.ancestors(impl_id) - .type_defs(tcx, trait_assoc_ty.name) - .next() - .map(|node_item| !node_item.node.is_from_trait()) - .unwrap_or(false); - } - } + for trait_item in tcx.associated_items(impl_trait_ref.def_id) { + let is_implemented = trait_def.ancestors(impl_id) + .defs(tcx, trait_item.name, trait_item.kind) + .next() + .map(|node_item| !node_item.node.is_from_trait()) + .unwrap_or(false); if !is_implemented { - if !is_provided { - missing_items.push(trait_item.name()); + if !trait_item.has_value { + missing_items.push(trait_item.name); } else if associated_type_overridden { - invalidated_items.push(trait_item.name()); + invalidated_items.push(trait_item.name); } } } @@ -1351,19 +1299,6 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { Ok(r) } - fn trait_defines_associated_type_named(&self, - trait_def_id: DefId, - assoc_name: ast::Name) - -> bool - { - self.tcx().impl_or_trait_items(trait_def_id).iter().any(|&def_id| { - match self.tcx().impl_or_trait_item(def_id) { - ty::TypeTraitItem(ref item) => item.name == assoc_name, - _ => false - } - }) - } - fn ty_infer(&self, _span: Span) -> Ty<'tcx> { self.next_ty_var() } @@ -1608,12 +1543,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// As `instantiate_type_scheme`, but for the bounds found in a /// generic type scheme. - fn instantiate_bounds(&self, - span: Span, - substs: &Substs<'tcx>, - bounds: &ty::GenericPredicates<'tcx>) - -> ty::InstantiatedPredicates<'tcx> - { + fn instantiate_bounds(&self, span: Span, def_id: DefId, substs: &Substs<'tcx>) + -> ty::InstantiatedPredicates<'tcx> { + let bounds = self.tcx.lookup_predicates(def_id); let result = bounds.instantiate(self.tcx, substs); let result = self.normalize_associated_types_in(span, &result.predicates); debug!("instantiate_bounds(bounds={:?}, substs={:?}) = {:?}", @@ -3254,8 +3186,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } // Check bounds on type arguments used in the path. - let type_predicates = self.tcx.lookup_predicates(did); - let bounds = self.instantiate_bounds(path.span, substs, &type_predicates); + let bounds = self.instantiate_bounds(path.span, did, substs); let cause = traits::ObligationCause::new(path.span, self.body_id, traits::ItemObligation(did)); self.add_obligations_for_parameters(cause, &bounds); @@ -4122,7 +4053,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Case 3. Reference to a method or associated const. Def::Method(def_id) | Def::AssociatedConst(def_id) => { - let container = self.tcx.impl_or_trait_item(def_id).container(); + let container = self.tcx.associated_item(def_id).container; match container { ty::TraitContainer(trait_did) => { callee::check_legal_trait_for_method_call(self.ccx, span, trait_did) @@ -4263,13 +4194,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // The things we are substituting into the type should not contain // escaping late-bound regions, and nor should the base type scheme. let scheme = self.tcx.lookup_item_type(def.def_id()); - let type_predicates = self.tcx.lookup_predicates(def.def_id()); assert!(!substs.has_escaping_regions()); assert!(!scheme.ty.has_escaping_regions()); // Add all the obligations that are required, substituting and // normalized appropriately. - let bounds = self.instantiate_bounds(span, &substs, &type_predicates); + let bounds = self.instantiate_bounds(span, def.def_id(), &substs); self.add_obligations_for_parameters( traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def.def_id())), &bounds); diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index e3634cfe5f5e3..794f3369c9bb1 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use astconv::ExplicitSelf; use check::FnCtxt; use constrained_type_params::{identify_constrained_type_params, Parameter}; use CrateCtxt; + use hir::def_id::DefId; use middle::region::{CodeExtent}; use rustc::infer::TypeOrigin; @@ -156,8 +158,8 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { self.check_variances_for_type_defn(item, ast_generics); } - hir::ItemTrait(.., ref items) => { - self.check_trait(item, items); + hir::ItemTrait(..) => { + self.check_trait(item); } _ => {} } @@ -172,32 +174,39 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { let free_substs = &fcx.parameter_environment.free_substs; let free_id_outlive = fcx.parameter_environment.free_id_outlive; - let item = fcx.tcx.impl_or_trait_item(fcx.tcx.map.local_def_id(item_id)); + let item = fcx.tcx.associated_item(fcx.tcx.map.local_def_id(item_id)); - let (mut implied_bounds, self_ty) = match item.container() { + let (mut implied_bounds, self_ty) = match item.container { ty::TraitContainer(_) => (vec![], fcx.tcx.mk_self_type()), ty::ImplContainer(def_id) => (fcx.impl_implied_bounds(def_id, span), fcx.tcx.lookup_item_type(def_id).ty) }; - match item { - ty::ConstTraitItem(assoc_const) => { - let ty = fcx.instantiate_type_scheme(span, free_substs, &assoc_const.ty); + match item.kind { + ty::AssociatedKind::Const => { + let ty = fcx.tcx.lookup_item_type(item.def_id).ty; + let ty = fcx.instantiate_type_scheme(span, free_substs, &ty); fcx.register_wf_obligation(ty, span, code.clone()); } - ty::MethodTraitItem(method) => { - reject_shadowing_type_parameters(fcx.tcx, span, &method.generics); - let method_ty = fcx.instantiate_type_scheme(span, free_substs, &method.fty); - let predicates = fcx.instantiate_bounds(span, free_substs, &method.predicates); - this.check_fn_or_method(fcx, span, &method_ty, &predicates, + ty::AssociatedKind::Method => { + reject_shadowing_type_parameters(fcx.tcx, span, item.def_id); + let method_ty = fcx.tcx.lookup_item_type(item.def_id).ty; + let method_ty = fcx.instantiate_type_scheme(span, free_substs, &method_ty); + let predicates = fcx.instantiate_bounds(span, item.def_id, free_substs); + let fty = match method_ty.sty { + ty::TyFnDef(_, _, f) => f, + _ => bug!() + }; + this.check_fn_or_method(fcx, span, fty, &predicates, free_id_outlive, &mut implied_bounds); let sig_if_method = sig_if_method.expect("bad signature for method"); - this.check_method_receiver(fcx, sig_if_method, &method, + this.check_method_receiver(fcx, sig_if_method, &item, free_id_outlive, self_ty); } - ty::TypeTraitItem(assoc_type) => { - if let Some(ref ty) = assoc_type.ty { - let ty = fcx.instantiate_type_scheme(span, free_substs, ty); + ty::AssociatedKind::Type => { + if item.has_value { + let ty = fcx.tcx.lookup_item_type(item.def_id).ty; + let ty = fcx.instantiate_type_scheme(span, free_substs, &ty); fcx.register_wf_obligation(ty, span, code.clone()); } } @@ -248,19 +257,15 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { } let free_substs = &fcx.parameter_environment.free_substs; - let predicates = fcx.tcx.lookup_predicates(fcx.tcx.map.local_def_id(item.id)); - let predicates = fcx.instantiate_bounds(item.span, free_substs, &predicates); + let def_id = fcx.tcx.map.local_def_id(item.id); + let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs); this.check_where_clauses(fcx, item.span, &predicates); vec![] // no implied bounds in a struct def'n }); } - fn check_auto_trait(&mut self, - trait_def_id: DefId, - items: &[hir::TraitItem], - span: Span) - { + fn check_auto_trait(&mut self, trait_def_id: DefId, span: Span) { // We want to ensure: // // 1) that there are no items contained within @@ -302,7 +307,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { // extraneous predicates created by things like // an associated type inside the trait. let mut err = None; - if !items.is_empty() { + if !self.tcx().associated_item_def_ids(trait_def_id).is_empty() { error_380(self.ccx, span); } else if has_ty_params { err = Some(struct_span_err!(self.tcx().sess, span, E0567, @@ -326,20 +331,16 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { } } - fn check_trait(&mut self, - item: &hir::Item, - items: &[hir::TraitItem]) - { + fn check_trait(&mut self, item: &hir::Item) { let trait_def_id = self.tcx().map.local_def_id(item.id); if self.tcx().trait_has_default_impl(trait_def_id) { - self.check_auto_trait(trait_def_id, items, item.span); + self.check_auto_trait(trait_def_id, item.span); } self.for_item(item).with_fcx(|fcx, this| { let free_substs = &fcx.parameter_environment.free_substs; - let predicates = fcx.tcx.lookup_predicates(trait_def_id); - let predicates = fcx.instantiate_bounds(item.span, free_substs, &predicates); + let predicates = fcx.instantiate_bounds(item.span, trait_def_id, free_substs); this.check_where_clauses(fcx, item.span, &predicates); vec![] }); @@ -351,7 +352,8 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { { self.for_item(item).with_fcx(|fcx, this| { let free_substs = &fcx.parameter_environment.free_substs; - let type_scheme = fcx.tcx.lookup_item_type(fcx.tcx.map.local_def_id(item.id)); + let def_id = fcx.tcx.map.local_def_id(item.id); + let type_scheme = fcx.tcx.lookup_item_type(def_id); let item_ty = fcx.instantiate_type_scheme(item.span, free_substs, &type_scheme.ty); let bare_fn_ty = match item_ty.sty { ty::TyFnDef(.., ref bare_fn_ty) => bare_fn_ty, @@ -360,8 +362,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { } }; - let predicates = fcx.tcx.lookup_predicates(fcx.tcx.map.local_def_id(item.id)); - let predicates = fcx.instantiate_bounds(item.span, free_substs, &predicates); + let predicates = fcx.instantiate_bounds(item.span, def_id, free_substs); let mut implied_bounds = vec![]; let free_id_outlive = fcx.tcx.region_maps.call_site_extent(item.id, body.id); @@ -422,8 +423,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { } } - let predicates = fcx.tcx.lookup_predicates(item_def_id); - let predicates = fcx.instantiate_bounds(item.span, free_substs, &predicates); + let predicates = fcx.instantiate_bounds(item.span, item_def_id, free_substs); this.check_where_clauses(fcx, item.span, &predicates); fcx.impl_implied_bounds(fcx.tcx.map.local_def_id(item.id), item.span) @@ -476,35 +476,39 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { fn check_method_receiver<'fcx, 'tcx>(&mut self, fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, method_sig: &hir::MethodSig, - method: &ty::Method<'tcx>, + method: &ty::AssociatedItem, free_id_outlive: CodeExtent, self_ty: ty::Ty<'tcx>) { // check that the type of the method's receiver matches the // method's first parameter. - debug!("check_method_receiver({:?},cat={:?},self_ty={:?})", - method.name, method.explicit_self, self_ty); + debug!("check_method_receiver({:?}, self_ty={:?})", + method, self_ty); - let rcvr_ty = match method.explicit_self { - ty::ExplicitSelfCategory::Static => return, - ty::ExplicitSelfCategory::ByValue => self_ty, - ty::ExplicitSelfCategory::ByReference(region, mutability) => { - fcx.tcx.mk_ref(region, ty::TypeAndMut { - ty: self_ty, - mutbl: mutability - }) - } - ty::ExplicitSelfCategory::ByBox => fcx.tcx.mk_box(self_ty) - }; + if !method.method_has_self_argument { + return; + } let span = method_sig.decl.inputs[0].pat.span; let free_substs = &fcx.parameter_environment.free_substs; - let fty = fcx.instantiate_type_scheme(span, free_substs, &method.fty); - let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &fty.sig); + let method_ty = fcx.tcx.lookup_item_type(method.def_id).ty; + let fty = fcx.instantiate_type_scheme(span, free_substs, &method_ty); + let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &fty.fn_sig()); debug!("check_method_receiver: sig={:?}", sig); + let self_arg_ty = sig.inputs[0]; + let rcvr_ty = match ExplicitSelf::determine(self_ty, self_arg_ty) { + ExplicitSelf::ByValue => self_ty, + ExplicitSelf::ByReference(region, mutbl) => { + fcx.tcx.mk_ref(region, ty::TypeAndMut { + ty: self_ty, + mutbl: mutbl + }) + } + ExplicitSelf::ByBox => fcx.tcx.mk_box(self_ty) + }; let rcvr_ty = fcx.instantiate_type_scheme(span, free_substs, &rcvr_ty); let rcvr_ty = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &ty::Binder(rcvr_ty)); @@ -512,7 +516,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty); let origin = TypeOrigin::MethodReceiver(span); - fcx.demand_eqtype_with_origin(origin, rcvr_ty, sig.inputs[0]); + fcx.demand_eqtype_with_origin(origin, rcvr_ty, self_arg_ty); } fn check_variances_for_type_defn(&self, @@ -578,7 +582,8 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { } } -fn reject_shadowing_type_parameters(tcx: TyCtxt, span: Span, generics: &ty::Generics) { +fn reject_shadowing_type_parameters(tcx: TyCtxt, span: Span, def_id: DefId) { + let generics = tcx.lookup_generics(def_id); let parent = tcx.lookup_generics(generics.parent.unwrap()); let impl_params: FnvHashMap<_, _> = parent.types .iter() diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index ca22faa2ec36a..748f52b6caf37 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -38,8 +38,6 @@ use rustc::hir::intravisit; use rustc::hir::{Item, ItemImpl}; use rustc::hir; -use std::rc::Rc; - mod orphan; mod overlap; mod unsafety; @@ -113,8 +111,6 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { // If there are no traits, then this implementation must have a // base type. - let impl_items = self.create_impl_from_item(item); - if let Some(trait_ref) = self.crate_context.tcx.impl_trait_ref(impl_did) { debug!("(checking implementation) adding impl for trait '{:?}', item '{}'", trait_ref, @@ -144,8 +140,6 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { self.add_inherent_impl(base_def_id, impl_did); } } - - tcx.impl_or_trait_item_def_ids.borrow_mut().insert(impl_did, Rc::new(impl_items)); } fn add_inherent_impl(&self, base_def_id: DefId, impl_def_id: DefId) { @@ -161,20 +155,6 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { trait_def.record_local_impl(self.crate_context.tcx, impl_def_id, impl_trait_ref); } - // Converts an implementation in the AST to a vector of items. - fn create_impl_from_item(&self, item: &Item) -> Vec { - match item.node { - ItemImpl(.., ref impl_items) => { - impl_items.iter() - .map(|impl_item| self.crate_context.tcx.map.local_def_id(impl_item.id)) - .collect() - } - _ => { - span_bug!(item.span, "can't convert a non-impl to an impl"); - } - } - } - // Destructors // @@ -187,10 +167,8 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { tcx.populate_implementations_for_trait_if_necessary(drop_trait); let drop_trait = tcx.lookup_trait_def(drop_trait); - let impl_items = tcx.impl_or_trait_item_def_ids.borrow(); - drop_trait.for_each_impl(tcx, |impl_did| { - let items = impl_items.get(&impl_did).unwrap(); + let items = tcx.associated_item_def_ids(impl_did); if items.is_empty() { // We'll error out later. For now, just don't ICE. return; diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 1bf140c21a5a5..b5aba512a66bd 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -48,25 +48,23 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { Value, } - fn name_and_namespace<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId) - -> (ast::Name, Namespace) { - let item = tcx.impl_or_trait_item(def_id); - (item.name(), - match item { - ty::TypeTraitItem(..) => Namespace::Type, - ty::ConstTraitItem(..) => Namespace::Value, - ty::MethodTraitItem(..) => Namespace::Value, - }) - } + let name_and_namespace = |def_id| { + let item = self.tcx.associated_item(def_id); + (item.name, match item.kind { + ty::AssociatedKind::Type => Namespace::Type, + ty::AssociatedKind::Const | + ty::AssociatedKind::Method => Namespace::Value, + }) + }; - let impl_items = self.tcx.impl_or_trait_item_def_ids.borrow(); + let impl_items1 = self.tcx.associated_item_def_ids(impl1); + let impl_items2 = self.tcx.associated_item_def_ids(impl2); - for &item1 in &impl_items[&impl1][..] { - let (name, namespace) = name_and_namespace(self.tcx, item1); + for &item1 in &impl_items1[..] { + let (name, namespace) = name_and_namespace(item1); - for &item2 in &impl_items[&impl2][..] { - if (name, namespace) == name_and_namespace(self.tcx, item2) { + for &item2 in &impl_items2[..] { + if (name, namespace) == name_and_namespace(item2) { let msg = format!("duplicate definitions with name `{}`", name); let node_id = self.tcx.map.as_local_node_id(item1).unwrap(); self.tcx.sess.add_lint(lint::builtin::OVERLAPPING_INHERENT_IMPLS, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 202e176df0dbc..93492ed453800 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -66,7 +66,7 @@ use middle::const_val::ConstVal; use rustc_const_eval::EvalHint::UncheckedExprHint; use rustc_const_eval::{eval_const_expr_partial, report_const_eval_err}; use rustc::ty::subst::Substs; -use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer}; +use rustc::ty::{ToPredicate, ImplContainer, AssociatedItemContainer, TraitContainer}; use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt, TypeScheme}; use rustc::ty::util::IntTypeExt; use rscope::*; @@ -79,7 +79,6 @@ use rustc_const_math::ConstInt; use std::cell::RefCell; use std::collections::hash_map::Entry::{Occupied, Vacant}; -use std::rc::Rc; use syntax::{abi, ast, attr}; use syntax::parse::token::keywords; @@ -351,24 +350,6 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { }) } - fn trait_defines_associated_type_named(&self, - trait_def_id: DefId, - assoc_name: ast::Name) - -> bool - { - if let Some(trait_id) = self.tcx().map.as_local_node_id(trait_def_id) { - trait_associated_type_names(self.tcx(), trait_id) - .any(|name| name == assoc_name) - } else { - self.tcx().impl_or_trait_items(trait_def_id).iter().any(|&def_id| { - match self.tcx().impl_or_trait_item(def_id) { - ty::TypeTraitItem(ref item) => item.name == assoc_name, - _ => false - } - }) - } - } - fn get_free_substs(&self) -> Option<&Substs<'tcx>> { None } @@ -557,60 +538,6 @@ fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - container: ImplOrTraitItemContainer, - name: ast::Name, - id: ast::NodeId, - vis: &hir::Visibility, - sig: &hir::MethodSig, - defaultness: hir::Defaultness, - has_body: bool, - untransformed_rcvr_ty: Ty<'tcx>, - rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) { - let def_id = ccx.tcx.map.local_def_id(id); - let ty_generics = generics_of_def_id(ccx, def_id); - - let ty_generic_predicates = - ty_generic_predicates(ccx, &sig.generics, ty_generics.parent, vec![], false); - - let (fty, explicit_self_category) = { - let anon_scope = match container { - ImplContainer(_) => Some(AnonTypeScope::new(def_id)), - TraitContainer(_) => None - }; - AstConv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)), - sig, untransformed_rcvr_ty, anon_scope) - }; - - let ty_method = ty::Method { - name: name, - generics: ty_generics, - predicates: ty_generic_predicates, - fty: fty, - explicit_self: explicit_self_category, - vis: ty::Visibility::from_hir(vis, id, ccx.tcx), - defaultness: defaultness, - has_body: has_body, - def_id: def_id, - container: container, - }; - - let substs = mk_item_substs(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)), - ccx.tcx.map.span(id), def_id); - let fty = ccx.tcx.mk_fn_def(def_id, substs, ty_method.fty); - debug!("method {} (id {}) has type {:?}", - name, id, fty); - ccx.tcx.tcache.borrow_mut().insert(def_id, fty); - write_ty_to_tcx(ccx, id, fty); - ccx.tcx.predicates.borrow_mut().insert(def_id, ty_method.predicates.clone()); - - debug!("writing method type: def_id={:?} mty={:?}", - def_id, ty_method); - - ccx.tcx.impl_or_trait_items.borrow_mut().insert(def_id, - ty::MethodTraitItem(Rc::new(ty_method))); -} - fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, struct_generics: &'tcx ty::Generics<'tcx>, struct_predicates: &ty::GenericPredicates<'tcx>, @@ -631,62 +558,65 @@ fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, struct_predicates.clone()); } +fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, + container: AssociatedItemContainer, + id: ast::NodeId, + sig: &hir::MethodSig, + untransformed_rcvr_ty: Ty<'tcx>, + rcvr_ty_predicates: &ty::GenericPredicates<'tcx>) { + let def_id = ccx.tcx.map.local_def_id(id); + let ty_generics = generics_of_def_id(ccx, def_id); + + let ty_generic_predicates = + ty_generic_predicates(ccx, &sig.generics, ty_generics.parent, vec![], false); + + let anon_scope = match container { + ImplContainer(_) => Some(AnonTypeScope::new(def_id)), + TraitContainer(_) => None + }; + let fty = AstConv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)), + sig, untransformed_rcvr_ty, anon_scope); + + let substs = mk_item_substs(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)), + ccx.tcx.map.span(id), def_id); + let fty = ccx.tcx.mk_fn_def(def_id, substs, fty); + ccx.tcx.tcache.borrow_mut().insert(def_id, fty); + write_ty_to_tcx(ccx, id, fty); + ccx.tcx.predicates.borrow_mut().insert(def_id, ty_generic_predicates); +} + fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - container: ImplOrTraitItemContainer, - name: ast::Name, + container: AssociatedItemContainer, id: ast::NodeId, - vis: &hir::Visibility, - defaultness: hir::Defaultness, - ty: ty::Ty<'tcx>, - has_value: bool) + ty: ty::Ty<'tcx>) { let predicates = ty::GenericPredicates { parent: Some(container.id()), predicates: vec![] }; - ccx.tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(id), - predicates); + let def_id = ccx.tcx.map.local_def_id(id); + ccx.tcx.predicates.borrow_mut().insert(def_id, predicates); + ccx.tcx.tcache.borrow_mut().insert(def_id, ty); write_ty_to_tcx(ccx, id, ty); - - let associated_const = Rc::new(ty::AssociatedConst { - name: name, - vis: ty::Visibility::from_hir(vis, id, ccx.tcx), - defaultness: defaultness, - def_id: ccx.tcx.map.local_def_id(id), - container: container, - ty: ty, - has_value: has_value - }); - ccx.tcx.impl_or_trait_items.borrow_mut() - .insert(ccx.tcx.map.local_def_id(id), ty::ConstTraitItem(associated_const)); } fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - container: ImplOrTraitItemContainer, - name: ast::Name, + container: AssociatedItemContainer, id: ast::NodeId, - vis: &hir::Visibility, - defaultness: hir::Defaultness, ty: Option>) { let predicates = ty::GenericPredicates { parent: Some(container.id()), predicates: vec![] }; - ccx.tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(id), - predicates); + let def_id = ccx.tcx.map.local_def_id(id); + ccx.tcx.predicates.borrow_mut().insert(def_id, predicates); - let associated_type = Rc::new(ty::AssociatedType { - name: name, - vis: ty::Visibility::from_hir(vis, id, ccx.tcx), - defaultness: defaultness, - ty: ty, - def_id: ccx.tcx.map.local_def_id(id), - container: container - }); - ccx.tcx.impl_or_trait_items.borrow_mut() - .insert(ccx.tcx.map.local_def_id(id), ty::TypeTraitItem(associated_type)); + if let Some(ty) = ty { + ccx.tcx.tcache.borrow_mut().insert(def_id, ty); + write_ty_to_tcx(ccx, id, ty); + } } fn ensure_no_ty_param_bounds(ccx: &CrateCtxt, @@ -820,14 +750,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { generics: ty_generics, ty: ty, }); - // Trait-associated constants are always public. - let public = &hir::Public; - let visibility = if opt_trait_ref.is_some() { public } else { &impl_item.vis }; convert_associated_const(ccx, ImplContainer(def_id), - impl_item.name, impl_item.id, - visibility, - impl_item.defaultness, - ty, true /* has_value */); + impl_item.id, ty); } } @@ -844,21 +768,14 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, ty); - convert_associated_type(ccx, ImplContainer(def_id), - impl_item.name, impl_item.id, &impl_item.vis, - impl_item.defaultness, Some(typ)); + convert_associated_type(ccx, ImplContainer(def_id), impl_item.id, Some(typ)); } } for impl_item in impl_items { if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node { - // Trait methods are always public. - let public = &hir::Public; - let method_vis = if opt_trait_ref.is_some() { public } else { &impl_item.vis }; - convert_method(ccx, ImplContainer(def_id), - impl_item.name, impl_item.id, method_vis, - sig, impl_item.defaultness, true, selfty, + impl_item.id, sig, selfty, &ty_predicates); } } @@ -880,7 +797,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { // Convert all the associated constants. for trait_item in trait_items { - if let hir::ConstTraitItem(ref ty, ref default) = trait_item.node { + if let hir::ConstTraitItem(ref ty, _) = trait_item.node { let const_def_id = ccx.tcx.map.local_def_id(trait_item.id); let ty_generics = generics_of_def_id(ccx, const_def_id); let ty = ccx.icx(&trait_predicates) @@ -890,14 +807,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { generics: ty_generics, ty: ty, }); - convert_associated_const(ccx, - container, - trait_item.name, - trait_item.id, - &hir::Public, - hir::Defaultness::Default, - ty, - default.is_some()) + convert_associated_const(ccx, container, trait_item.id, ty) } } @@ -911,39 +821,21 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { |ty| ccx.icx(&trait_predicates).to_ty(&ExplicitRscope, &ty) }); - convert_associated_type(ccx, - container, - trait_item.name, - trait_item.id, - &hir::Public, - hir::Defaultness::Default, - typ); + convert_associated_type(ccx, container, trait_item.id, typ); } } // Convert all the methods for trait_item in trait_items { - if let hir::MethodTraitItem(ref sig, ref body) = trait_item.node { + if let hir::MethodTraitItem(ref sig, _) = trait_item.node { convert_method(ccx, container, - trait_item.name, trait_item.id, - &hir::Inherited, sig, - hir::Defaultness::Default, - body.is_some(), tcx.mk_self_type(), &trait_predicates); - } } - - // Add an entry mapping - let trait_item_def_ids = Rc::new(trait_items.iter().map(|trait_item| { - ccx.tcx.map.local_def_id(trait_item.id) - }).collect()); - tcx.impl_or_trait_item_def_ids.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id), - trait_item_def_ids); }, hir::ItemStruct(ref struct_def, _) | hir::ItemUnion(ref struct_def, _) => { @@ -1308,28 +1200,6 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, tcx.intern_trait_def(trait_def) } -pub fn trait_associated_type_names<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - trait_node_id: ast::NodeId) - -> impl Iterator + 'a -{ - let item = match tcx.map.get(trait_node_id) { - hir_map::NodeItem(item) => item, - _ => bug!("trait_node_id {} is not an item", trait_node_id) - }; - - let trait_items = match item.node { - hir::ItemTrait(.., ref trait_items) => trait_items, - _ => bug!("trait_node_id {} is not a trait", trait_node_id) - }; - - trait_items.iter().filter_map(|trait_item| { - match trait_item.node { - hir::TypeTraitItem(..) => Some(trait_item.name), - _ => None, - } - }) -} - fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) { let tcx = ccx.tcx; let trait_def = trait_def_of_item(ccx, it); @@ -2210,13 +2080,14 @@ fn enforce_impl_lifetimes_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, &impl_predicates.predicates.as_slice(), impl_trait_ref, &mut input_parameters); let lifetimes_in_associated_types: FnvHashSet<_> = impl_items.iter() - .map(|item| ccx.tcx.impl_or_trait_item(ccx.tcx.map.local_def_id(item.id))) - .filter_map(|item| match item { - ty::TypeTraitItem(ref assoc_ty) => assoc_ty.ty, - ty::ConstTraitItem(..) | ty::MethodTraitItem(..) => None + .map(|item| ccx.tcx.map.local_def_id(item.id)) + .filter(|&def_id| { + let item = ccx.tcx.associated_item(def_id); + item.kind == ty::AssociatedKind::Type && item.has_value }) - .flat_map(|ty| ctp::parameters_for(&ty, true)) - .collect(); + .flat_map(|def_id| { + ctp::parameters_for(&ccx.tcx.lookup_item_type(def_id).ty, true) + }).collect(); for (ty_lifetime, lifetime) in impl_scheme.generics.regions.iter() .zip(&ast_generics.lifetimes) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 31497b6bd3352..248116ab58ee7 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -163,7 +163,7 @@ pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) { pub fn build_external_trait<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId) -> clean::Trait { let def = tcx.lookup_trait_def(did); - let trait_items = tcx.trait_items(did).clean(cx); + let trait_items = tcx.associated_items(did).map(|item| item.clean(cx)).collect(); let predicates = tcx.lookup_predicates(did); let generics = (def.generics, &predicates).clean(cx); let generics = filter_non_trait_generics(did, generics); @@ -307,7 +307,6 @@ pub fn build_impls<'a, 'tcx>(cx: &DocContext, for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) { if !def_id.is_local() { - tcx.populate_implementations_for_primitive_if_necessary(def_id); build_impl(cx, tcx, def_id, &mut impls); } } @@ -367,21 +366,18 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext, } let predicates = tcx.lookup_predicates(did); - let trait_items = tcx.sess.cstore.impl_or_trait_items(did) - .iter() - .filter_map(|&did| { - match tcx.impl_or_trait_item(did) { - ty::ConstTraitItem(ref assoc_const) => { - let did = assoc_const.def_id; - let type_scheme = tcx.lookup_item_type(did); - let default = if assoc_const.has_value { + let trait_items = tcx.associated_items(did).filter_map(|item| { + match item.kind { + ty::AssociatedKind::Const => { + let type_scheme = tcx.lookup_item_type(item.def_id); + let default = if item.has_value { Some(pprust::expr_to_string( - lookup_const_by_id(tcx, did, None).unwrap().0)) + lookup_const_by_id(tcx, item.def_id, None).unwrap().0)) } else { None }; Some(clean::Item { - name: Some(assoc_const.name.clean(cx)), + name: Some(item.name.clean(cx)), inner: clean::AssociatedConstItem( type_scheme.ty.clean(cx), default, @@ -389,21 +385,21 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext, source: clean::Span::empty(), attrs: vec![], visibility: None, - stability: tcx.lookup_stability(did).clean(cx), - deprecation: tcx.lookup_deprecation(did).clean(cx), - def_id: did + stability: tcx.lookup_stability(item.def_id).clean(cx), + deprecation: tcx.lookup_deprecation(item.def_id).clean(cx), + def_id: item.def_id }) } - ty::MethodTraitItem(method) => { - if method.vis != ty::Visibility::Public && associated_trait.is_none() { + ty::AssociatedKind::Method => { + if item.vis != ty::Visibility::Public && associated_trait.is_none() { return None } - let mut item = method.clean(cx); - item.inner = match item.inner.clone() { + let mut cleaned = item.clean(cx); + cleaned.inner = match cleaned.inner.clone() { clean::TyMethodItem(clean::TyMethod { unsafety, decl, generics, abi }) => { - let constness = if tcx.sess.cstore.is_const_fn(did) { + let constness = if tcx.sess.cstore.is_const_fn(item.def_id) { hir::Constness::Const } else { hir::Constness::NotConst @@ -419,12 +415,11 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext, } _ => panic!("not a tymethod"), }; - Some(item) + Some(cleaned) } - ty::TypeTraitItem(ref assoc_ty) => { - let did = assoc_ty.def_id; + ty::AssociatedKind::Type => { let typedef = clean::Typedef { - type_: assoc_ty.ty.unwrap().clean(cx), + type_: tcx.lookup_item_type(item.def_id).ty.clean(cx), generics: clean::Generics { lifetimes: vec![], type_params: vec![], @@ -432,14 +427,14 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext, } }; Some(clean::Item { - name: Some(assoc_ty.name.clean(cx)), + name: Some(item.name.clean(cx)), inner: clean::TypedefItem(typedef, true), source: clean::Span::empty(), attrs: vec![], visibility: None, - stability: tcx.lookup_stability(did).clean(cx), - deprecation: tcx.lookup_deprecation(did).clean(cx), - def_id: did + stability: tcx.lookup_stability(item.def_id).clean(cx), + deprecation: tcx.lookup_deprecation(item.def_id).clean(cx), + def_id: item.def_id }) } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 265b66b01ea52..ea2eacea30047 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1338,48 +1338,117 @@ impl Clean for hir::ImplItem { } } -impl<'tcx> Clean for ty::Method<'tcx> { +impl<'tcx> Clean for ty::AssociatedItem { fn clean(&self, cx: &DocContext) -> Item { - let generics = (self.generics, &self.predicates).clean(cx); - let mut decl = (self.def_id, &self.fty.sig).clean(cx); - match self.explicit_self { - ty::ExplicitSelfCategory::ByValue => { - decl.inputs.values[0].type_ = Infer; + let inner = match self.kind { + ty::AssociatedKind::Const => { + let ty = cx.tcx().lookup_item_type(self.def_id).ty; + AssociatedConstItem(ty.clean(cx), None) } - ty::ExplicitSelfCategory::ByReference(..) => { - match decl.inputs.values[0].type_ { - BorrowedRef{ref mut type_, ..} => **type_ = Infer, - _ => unreachable!(), + ty::AssociatedKind::Method => { + let generics = (cx.tcx().lookup_generics(self.def_id), + &cx.tcx().lookup_predicates(self.def_id)).clean(cx); + let fty = match cx.tcx().lookup_item_type(self.def_id).ty.sty { + ty::TyFnDef(_, _, f) => f, + _ => unreachable!() + }; + let mut decl = (self.def_id, &fty.sig).clean(cx); + + if self.method_has_self_argument { + let self_ty = match self.container { + ty::ImplContainer(def_id) => { + cx.tcx().lookup_item_type(def_id).ty + } + ty::TraitContainer(_) => cx.tcx().mk_self_type() + }; + let self_arg_ty = *fty.sig.input(0).skip_binder(); + if self_arg_ty == self_ty { + decl.inputs.values[0].type_ = Infer; + } else if let ty::TyRef(_, mt) = self_arg_ty.sty { + if mt.ty == self_ty { + match decl.inputs.values[0].type_ { + BorrowedRef{ref mut type_, ..} => **type_ = Infer, + _ => unreachable!(), + } + } + } + } + let provided = match self.container { + ty::ImplContainer(_) => false, + ty::TraitContainer(_) => self.has_value + }; + if provided { + MethodItem(Method { + unsafety: fty.unsafety, + generics: generics, + decl: decl, + abi: fty.abi, + + // trait methods canot (currently, at least) be const + constness: hir::Constness::NotConst, + }) + } else { + TyMethodItem(TyMethod { + unsafety: fty.unsafety, + generics: generics, + decl: decl, + abi: fty.abi, + }) } } - _ => {} - } - let provided = match self.container { - ty::ImplContainer(..) => false, - ty::TraitContainer(did) => { - cx.tcx().provided_trait_methods(did).iter().any(|m| { - m.def_id == self.def_id - }) + ty::AssociatedKind::Type => { + let my_name = self.name.clean(cx); + + let mut bounds = if let ty::TraitContainer(did) = self.container { + // When loading a cross-crate associated type, the bounds for this type + // are actually located on the trait/impl itself, so we need to load + // all of the generics from there and then look for bounds that are + // applied to this associated type in question. + let def = cx.tcx().lookup_trait_def(did); + let predicates = cx.tcx().lookup_predicates(did); + let generics = (def.generics, &predicates).clean(cx); + generics.where_predicates.iter().filter_map(|pred| { + let (name, self_type, trait_, bounds) = match *pred { + WherePredicate::BoundPredicate { + ty: QPath { ref name, ref self_type, ref trait_ }, + ref bounds + } => (name, self_type, trait_, bounds), + _ => return None, + }; + if *name != my_name { return None } + match **trait_ { + ResolvedPath { did, .. } if did == self.container.id() => {} + _ => return None, + } + match **self_type { + Generic(ref s) if *s == "Self" => {} + _ => return None, + } + Some(bounds) + }).flat_map(|i| i.iter().cloned()).collect::>() + } else { + vec![] + }; + + // Our Sized/?Sized bound didn't get handled when creating the generics + // because we didn't actually get our whole set of bounds until just now + // (some of them may have come from the trait). If we do have a sized + // bound, we remove it, and if we don't then we add the `?Sized` bound + // at the end. + match bounds.iter().position(|b| b.is_sized_bound(cx)) { + Some(i) => { bounds.remove(i); } + None => bounds.push(TyParamBound::maybe_sized(cx)), + } + + let ty = if self.has_value { + Some(cx.tcx().lookup_item_type(self.def_id).ty) + } else { + None + }; + + AssociatedTypeItem(bounds, ty.clean(cx)) } }; - let inner = if provided { - MethodItem(Method { - unsafety: self.fty.unsafety, - generics: generics, - decl: decl, - abi: self.fty.abi, - - // trait methods canot (currently, at least) be const - constness: hir::Constness::NotConst, - }) - } else { - TyMethodItem(TyMethod { - unsafety: self.fty.unsafety, - generics: generics, - decl: decl, - abi: self.fty.abi, - }) - }; Item { name: Some(self.name.clean(cx)), @@ -1394,16 +1463,6 @@ impl<'tcx> Clean for ty::Method<'tcx> { } } -impl<'tcx> Clean for ty::ImplOrTraitItem<'tcx> { - fn clean(&self, cx: &DocContext) -> Item { - match *self { - ty::ConstTraitItem(ref cti) => cti.clean(cx), - ty::MethodTraitItem(ref mti) => mti.clean(cx), - ty::TypeTraitItem(ref tti) => tti.clean(cx), - } - } -} - /// A trait reference, which may have higher ranked lifetimes. #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] pub struct PolyTrait { @@ -2884,79 +2943,6 @@ impl Clean for attr::Deprecation { } } -impl<'tcx> Clean for ty::AssociatedConst<'tcx> { - fn clean(&self, cx: &DocContext) -> Item { - Item { - source: DUMMY_SP.clean(cx), - name: Some(self.name.clean(cx)), - attrs: Vec::new(), - inner: AssociatedConstItem(self.ty.clean(cx), None), - visibility: None, - def_id: self.def_id, - stability: None, - deprecation: None, - } - } -} - -impl<'tcx> Clean for ty::AssociatedType<'tcx> { - fn clean(&self, cx: &DocContext) -> Item { - let my_name = self.name.clean(cx); - - let mut bounds = if let ty::TraitContainer(did) = self.container { - // When loading a cross-crate associated type, the bounds for this type - // are actually located on the trait/impl itself, so we need to load - // all of the generics from there and then look for bounds that are - // applied to this associated type in question. - let def = cx.tcx().lookup_trait_def(did); - let predicates = cx.tcx().lookup_predicates(did); - let generics = (def.generics, &predicates).clean(cx); - generics.where_predicates.iter().filter_map(|pred| { - let (name, self_type, trait_, bounds) = match *pred { - WherePredicate::BoundPredicate { - ty: QPath { ref name, ref self_type, ref trait_ }, - ref bounds - } => (name, self_type, trait_, bounds), - _ => return None, - }; - if *name != my_name { return None } - match **trait_ { - ResolvedPath { did, .. } if did == self.container.id() => {} - _ => return None, - } - match **self_type { - Generic(ref s) if *s == "Self" => {} - _ => return None, - } - Some(bounds) - }).flat_map(|i| i.iter().cloned()).collect::>() - } else { - vec![] - }; - - // Our Sized/?Sized bound didn't get handled when creating the generics - // because we didn't actually get our whole set of bounds until just now - // (some of them may have come from the trait). If we do have a sized - // bound, we remove it, and if we don't then we add the `?Sized` bound - // at the end. - match bounds.iter().position(|b| b.is_sized_bound(cx)) { - Some(i) => { bounds.remove(i); } - None => bounds.push(TyParamBound::maybe_sized(cx)), - } - - Item { - source: DUMMY_SP.clean(cx), - name: Some(self.name.clean(cx)), - attrs: inline::load_attrs(cx, cx.tcx(), self.def_id), - inner: AssociatedTypeItem(bounds, self.ty.clean(cx)), - visibility: self.vis.clean(cx), - def_id: self.def_id, - stability: cx.tcx().lookup_stability(self.def_id).clean(cx), - deprecation: cx.tcx().lookup_deprecation(self.def_id).clean(cx), - } - } -} - fn lang_struct(cx: &DocContext, did: Option, t: ty::Ty, name: &str, fallback: fn(Box) -> Type) -> Type { From af0b27e01fc23ddeb43d6e48aa810294e526e334 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 27 Oct 2016 09:06:31 +1100 Subject: [PATCH 22/33] Don't hash span filenames twice in IchHasher. This significantly reduces the number of bytes hashed by IchHasher. --- .../calculate_svh/svh_visitor.rs | 42 ++++++++++++++----- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs index 51c894e1b78f0..09f12d1a7381a 100644 --- a/src/librustc_incremental/calculate_svh/svh_visitor.rs +++ b/src/librustc_incremental/calculate_svh/svh_visitor.rs @@ -82,6 +82,8 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> { // within the CodeMap. // Also note that we are hashing byte offsets for the column, not unicode // codepoint offsets. For the purpose of the hash that's sufficient. + // Also, hashing filenames is expensive so we avoid doing it twice when the + // span starts and ends in the same file, which is almost always the case. fn hash_span(&mut self, span: Span) { debug_assert!(self.hash_spans); debug!("hash_span: st={:?}", self.st); @@ -98,21 +100,35 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> { span.hi }; - let loc1 = self.codemap.byte_pos_to_line_and_col(span.lo); - let loc2 = self.codemap.byte_pos_to_line_and_col(span_hi); - - let expansion_kind = match span.expn_id { + let expn_kind = match span.expn_id { NO_EXPANSION => SawSpanExpnKind::NoExpansion, COMMAND_LINE_EXPN => SawSpanExpnKind::CommandLine, _ => SawSpanExpnKind::SomeExpansion, }; - SawSpan(loc1.as_ref().map(|&(ref fm, line, col)| (&fm.name[..], line, col)), - loc2.as_ref().map(|&(ref fm, line, col)| (&fm.name[..], line, col)), - expansion_kind) - .hash(self.st); + let loc1 = self.codemap.byte_pos_to_line_and_col(span.lo); + let loc1 = loc1.as_ref() + .map(|&(ref fm, line, col)| (&fm.name[..], line, col)) + .unwrap_or(("???", 0, BytePos(0))); + + let loc2 = self.codemap.byte_pos_to_line_and_col(span_hi); + let loc2 = loc2.as_ref() + .map(|&(ref fm, line, col)| (&fm.name[..], line, col)) + .unwrap_or(("???", 0, BytePos(0))); + + let saw = if loc1.0 == loc2.0 { + SawSpan(loc1.0, + loc1.1, loc1.2, + loc2.1, loc2.2, + expn_kind) + } else { + SawSpanTwoFiles(loc1.0, loc1.1, loc1.2, + loc2.0, loc2.1, loc2.2, + expn_kind) + }; + saw.hash(self.st); - if expansion_kind == SawSpanExpnKind::SomeExpansion { + if expn_kind == SawSpanExpnKind::SomeExpansion { let call_site = self.codemap.codemap().source_callsite(span); self.hash_span(call_site); } @@ -184,9 +200,13 @@ enum SawAbiComponent<'a> { SawAssocTypeBinding, SawAttribute(ast::AttrStyle), SawMacroDef, - SawSpan(Option<(&'a str, usize, BytePos)>, - Option<(&'a str, usize, BytePos)>, + SawSpan(&'a str, + usize, BytePos, + usize, BytePos, SawSpanExpnKind), + SawSpanTwoFiles(&'a str, usize, BytePos, + &'a str, usize, BytePos, + SawSpanExpnKind), } /// SawExprComponent carries all of the information that we want From 942f909c1f6d2d203661831366e828ef030588c6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 2 Nov 2016 19:08:10 +0100 Subject: [PATCH 23/33] Add missing urls for ErrorKind's variants --- src/libstd/io/error.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index ddf0030858eda..54372d91c893e 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -124,23 +124,28 @@ pub enum ErrorKind { InvalidInput, /// Data not valid for the operation were encountered. /// - /// Unlike `InvalidInput`, this typically means that the operation + /// Unlike [`InvalidInput`], this typically means that the operation /// parameters were valid, however the error was caused by malformed /// input data. /// /// For example, a function that reads a file into a string will error with /// `InvalidData` if the file's contents are not valid UTF-8. + /// + /// [`InvalidInput`]: #variant.InvalidInput #[stable(feature = "io_invalid_data", since = "1.2.0")] InvalidData, /// The I/O operation's timeout expired, causing it to be canceled. #[stable(feature = "rust1", since = "1.0.0")] TimedOut, /// An error returned when an operation could not be completed because a - /// call to `write` returned `Ok(0)`. + /// call to [`write()`] returned [`Ok(0)`]. /// /// This typically means that an operation could only succeed if it wrote a /// particular number of bytes but only a smaller number of bytes could be /// written. + /// + /// [`write()`]: ../../std/io/trait.Write.html#tymethod.write + /// [`Ok(0)`]: ../../std/io/type.Result.html #[stable(feature = "rust1", since = "1.0.0")] WriteZero, /// This operation was interrupted. From d73c68ceef6984b8e762a173b96279c42d1fe851 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 27 Oct 2016 09:23:38 +1100 Subject: [PATCH 24/33] leb128-encode integers before hashing them in IchHasher. This significantly reduces the number of bytes hashed by IchHasher. --- .../calculate_svh/hasher.rs | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/librustc_incremental/calculate_svh/hasher.rs b/src/librustc_incremental/calculate_svh/hasher.rs index 49683a81227b1..d7d9c231a91f4 100644 --- a/src/librustc_incremental/calculate_svh/hasher.rs +++ b/src/librustc_incremental/calculate_svh/hasher.rs @@ -9,13 +9,16 @@ // except according to those terms. use std::mem; +use std::hash::Hasher; use rustc_data_structures::blake2b::Blake2bHasher; use rustc::ty::util::ArchIndependentHasher; use ich::Fingerprint; +use rustc_serialize::leb128::write_unsigned_leb128; #[derive(Debug)] pub struct IchHasher { state: ArchIndependentHasher, + leb128_helper: Vec, bytes_hashed: u64, } @@ -24,6 +27,7 @@ impl IchHasher { let hash_size = mem::size_of::(); IchHasher { state: ArchIndependentHasher::new(Blake2bHasher::new(hash_size, &[])), + leb128_helper: vec![], bytes_hashed: 0 } } @@ -37,9 +41,19 @@ impl IchHasher { fingerprint.0.copy_from_slice(self.state.into_inner().finalize()); fingerprint } + + #[inline] + fn write_uleb128(&mut self, value: u64) { + let len = write_unsigned_leb128(&mut self.leb128_helper, 0, value); + self.state.write(&self.leb128_helper[0..len]); + self.bytes_hashed += len as u64; + } } -impl ::std::hash::Hasher for IchHasher { +// For the non-u8 integer cases we leb128 encode them first. Because small +// integers dominate, this significantly and cheaply reduces the number of +// bytes hashed, which is good because blake2b is expensive. +impl Hasher for IchHasher { fn finish(&self) -> u64 { bug!("Use other finish() implementation to get the full 128-bit hash."); } @@ -49,4 +63,26 @@ impl ::std::hash::Hasher for IchHasher { self.state.write(bytes); self.bytes_hashed += bytes.len() as u64; } + + // There is no need to leb128-encode u8 values. + + #[inline] + fn write_u16(&mut self, i: u16) { + self.write_uleb128(i as u64); + } + + #[inline] + fn write_u32(&mut self, i: u32) { + self.write_uleb128(i as u64); + } + + #[inline] + fn write_u64(&mut self, i: u64) { + self.write_uleb128(i); + } + + #[inline] + fn write_usize(&mut self, i: usize) { + self.write_uleb128(i as u64); + } } From 7d06bdd4a148ccb924cd6628a94ca8bc0d3611fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Inf=C3=BChr?= Date: Thu, 3 Nov 2016 10:53:13 +0100 Subject: [PATCH 25/33] set frame pointer elimination attribute for main The rustc-generated function `main` should respect the same config for frame pointer elimination as the rest of code. --- src/librustc_trans/base.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 977ababbf5688..47b6fdc740a34 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -1196,6 +1196,9 @@ pub fn maybe_create_entry_wrapper(ccx: &CrateContext) { } let llfn = declare::declare_cfn(ccx, "main", llfty); + // `main` should respect same config for frame pointer elimination as rest of code + attributes::set_frame_pointer_elimination(ccx, llfn); + let llbb = unsafe { llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llfn, "top\0".as_ptr() as *const _) }; From dc138b3156677f81f9be2afbf80465a0be8179c8 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Thu, 3 Nov 2016 11:51:11 +0100 Subject: [PATCH 26/33] use DefId's in const eval for cross-crate const fn's --- src/librustc_const_eval/eval.rs | 13 ++++++------- src/test/run-pass/auxiliary/issue-36954.rs | 18 ++++++++++++++++++ src/test/run-pass/issue-36954.rs | 17 +++++++++++++++++ 3 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 src/test/run-pass/auxiliary/issue-36954.rs create mode 100644 src/test/run-pass/issue-36954.rs diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index c02cca0da7225..41baa1080b1fb 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -27,7 +27,7 @@ use rustc::ty::util::IntTypeExt; use rustc::ty::subst::Substs; use rustc::traits::Reveal; use rustc::util::common::ErrorReported; -use rustc::util::nodemap::NodeMap; +use rustc::util::nodemap::DefIdMap; use rustc::lint; use graphviz::IntoCow; @@ -413,7 +413,7 @@ pub fn eval_const_expr_checked<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, eval_const_expr_partial(tcx, e, ExprTypeChecked, None) } -pub type FnArgMap<'a> = Option<&'a NodeMap>; +pub type FnArgMap<'a> = Option<&'a DefIdMap>; #[derive(Clone, Debug)] pub struct ConstEvalErr { @@ -835,9 +835,8 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ConstVal::Struct(e.id) } Def::Local(def_id) => { - let id = tcx.map.as_local_node_id(def_id).unwrap(); - debug!("Def::Local({:?}): {:?}", id, fn_args); - if let Some(val) = fn_args.and_then(|args| args.get(&id)) { + debug!("Def::Local({:?}): {:?}", def_id, fn_args); + if let Some(val) = fn_args.and_then(|args| args.get(&def_id)) { val.clone() } else { signal!(e, NonConstPath); @@ -863,7 +862,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let result = result.as_ref().expect("const fn has no result expression"); assert_eq!(decl.inputs.len(), args.len()); - let mut call_args = NodeMap(); + let mut call_args = DefIdMap(); for (arg, arg_expr) in decl.inputs.iter().zip(args.iter()) { let arg_hint = ty_hint.erase_hint(); let arg_val = eval_const_expr_partial( @@ -873,7 +872,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn_args )?; debug!("const call arg: {:?}", arg); - let old = call_args.insert(arg.pat.id, arg_val); + let old = call_args.insert(tcx.expect_def(arg.pat.id).def_id(), arg_val); assert!(old.is_none()); } debug!("const call({:?})", call_args); diff --git a/src/test/run-pass/auxiliary/issue-36954.rs b/src/test/run-pass/auxiliary/issue-36954.rs new file mode 100644 index 0000000000000..832ee1d7c1b45 --- /dev/null +++ b/src/test/run-pass/auxiliary/issue-36954.rs @@ -0,0 +1,18 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(const_fn)] +#![crate_type = "lib"] + +const fn foo(i: i32) -> i32 { + i +} + +pub const FOO: i32 = foo(1); diff --git a/src/test/run-pass/issue-36954.rs b/src/test/run-pass/issue-36954.rs new file mode 100644 index 0000000000000..f8330ba99b7ae --- /dev/null +++ b/src/test/run-pass/issue-36954.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:issue-36954.rs + +extern crate issue_36954 as lib; + +fn main() { + let _ = lib::FOO; +} From ed0230ee568ca9325a1fb5ffeca2ee9b34233ce1 Mon Sep 17 00:00:00 2001 From: Martin Glagla Date: Thu, 3 Nov 2016 22:22:27 +0100 Subject: [PATCH 27/33] Peekable::peek(): Use Option::as_ref() --- src/libcore/iter/mod.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index df4f5e5c57643..97a232de6718e 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -1341,10 +1341,7 @@ impl Peekable { if self.peeked.is_none() { self.peeked = self.iter.next(); } - match self.peeked { - Some(ref value) => Some(value), - None => None, - } + self.peeked.as_ref() } } From d5f72d21afffcda4cc71945f12477136774aa604 Mon Sep 17 00:00:00 2001 From: Mark-Simulacrum Date: Thu, 3 Nov 2016 14:55:35 -0600 Subject: [PATCH 28/33] Fix ICE when querying DefId on Def::Err. --- src/librustc_typeck/collect.rs | 7 +++---- src/test/compile-fail/issue-37534.rs | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 src/test/compile-fail/issue-37534.rs diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 202e176df0dbc..0e0f5cb1a7e15 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1724,16 +1724,15 @@ fn add_unsized_bound<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, match unbound { Some(ref tpb) => { // FIXME(#8559) currently requires the unbound to be built-in. - let trait_def_id = tcx.expect_def(tpb.ref_id).def_id(); - match kind_id { - Ok(kind_id) if trait_def_id != kind_id => { + if let Ok(kind_id) = kind_id { + let trait_def = tcx.expect_def(tpb.ref_id); + if trait_def != Def::Trait(kind_id) { tcx.sess.span_warn(span, "default bound relaxed for a type parameter, but \ this does nothing because the given bound is not \ a default. Only `?Sized` is supported"); tcx.try_add_builtin_trait(kind_id, bounds); } - _ => {} } } _ if kind_id.is_ok() => { diff --git a/src/test/compile-fail/issue-37534.rs b/src/test/compile-fail/issue-37534.rs new file mode 100644 index 0000000000000..eb676601e89ce --- /dev/null +++ b/src/test/compile-fail/issue-37534.rs @@ -0,0 +1,16 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo { } +//~^ ERROR trait `Hash` is not in scope [E0405] +//~^^ ERROR parameter `T` is never used [E0392] +//~^^^ WARN default bound relaxed for a type parameter, but this does nothing + +fn main() { } From 6a34feb034407cfcc82ccd951c13fb654689f130 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 3 Nov 2016 22:15:43 +0000 Subject: [PATCH 29/33] Set RUSTC_BOOTSTRAP to some value. Environment variables on windows can't be empty. --- mk/main.mk | 2 +- src/bootstrap/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mk/main.mk b/mk/main.mk index a5e3764122003..2fa8ccf3621e0 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -372,7 +372,7 @@ CFG_INFO := $(info cfg: disabling unstable features (CFG_DISABLE_UNSTABLE_FEATUR # Turn on feature-staging export CFG_DISABLE_UNSTABLE_FEATURES # Subvert unstable feature lints to do the self-build -export RUSTC_BOOTSTRAP +export RUSTC_BOOTSTRAP=1 endif ifdef CFG_MUSL_ROOT export CFG_MUSL_ROOT diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 7c5a0c7373f88..fdd7a1ec57df9 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -873,7 +873,7 @@ impl Build { /// Adds the compiler's bootstrap key to the environment of `cmd`. fn add_bootstrap_key(&self, cmd: &mut Command) { - cmd.env("RUSTC_BOOTSTRAP", ""); + cmd.env("RUSTC_BOOTSTRAP", "1"); // FIXME: Transitionary measure to bootstrap using the old bootstrap logic. // Remove this once the bootstrap compiler uses the new login in Issue #36548. cmd.env("RUSTC_BOOTSTRAP_KEY", "62b3e239"); From 67626e0cc30e07fe8763d344e855d7b4750b0b33 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Fri, 4 Nov 2016 00:16:04 +0100 Subject: [PATCH 30/33] core::ptr: Specify issue for ptr_wrapping_offset feature --- src/libcore/ptr.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index befab1b3669b3..2ad38de72b1b9 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -377,7 +377,7 @@ impl *const T { /// ptr = ptr.wrapping_offset(step); /// } /// ``` - #[unstable(feature = "ptr_wrapping_offset", issue = "0")] + #[unstable(feature = "ptr_wrapping_offset", issue = "37570")] #[inline] pub fn wrapping_offset(self, count: isize) -> *const T where T: Sized { unsafe { @@ -501,7 +501,7 @@ impl *mut T { /// } /// assert_eq!(&data, &[0, 2, 0, 4, 0]); /// ``` - #[unstable(feature = "ptr_wrapping_offset", issue = "0")] + #[unstable(feature = "ptr_wrapping_offset", issue = "37570")] #[inline] pub fn wrapping_offset(self, count: isize) -> *mut T where T: Sized { unsafe { From f0e6b90790da2203f04fa44ee3ed8f24dcc5f4dc Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Fri, 4 Nov 2016 00:24:59 +0100 Subject: [PATCH 31/33] Link the tracking issue for TrustedLen --- src/libcollections/vec.rs | 2 +- src/libcore/iter/mod.rs | 14 +++++++------- src/libcore/iter/range.rs | 2 +- src/libcore/iter/traits.rs | 4 ++-- src/libcore/option.rs | 6 +++--- src/libcore/result.rs | 6 +++--- src/libcore/slice.rs | 4 ++-- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 16331960cc198..053dcd8272e29 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1931,7 +1931,7 @@ impl ExactSizeIterator for IntoIter {} #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for IntoIter {} -#[unstable(feature = "trusted_len", issue = "0")] +#[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for IntoIter {} #[stable(feature = "vec_into_iter_clone", since = "1.8.0")] diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 9fa950cd94d9e..58d04218e072c 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -328,7 +328,7 @@ pub use self::traits::{FromIterator, IntoIterator, DoubleEndedIterator, Extend}; pub use self::traits::{ExactSizeIterator, Sum, Product}; #[unstable(feature = "fused", issue = "35602")] pub use self::traits::FusedIterator; -#[unstable(feature = "trusted_len", issue = "0")] +#[unstable(feature = "trusted_len", issue = "37572")] pub use self::traits::TrustedLen; mod iterator; @@ -374,7 +374,7 @@ impl ExactSizeIterator for Rev impl FusedIterator for Rev where I: FusedIterator + DoubleEndedIterator {} -#[unstable(feature = "trusted_len", issue = "0")] +#[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for Rev where I: TrustedLen + DoubleEndedIterator {} @@ -438,7 +438,7 @@ unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned fn may_have_side_effect() -> bool { true } } -#[unstable(feature = "trusted_len", issue = "0")] +#[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<'a, I, T: 'a> TrustedLen for Cloned where I: TrustedLen, T: Clone @@ -654,7 +654,7 @@ impl FusedIterator for Chain B: FusedIterator, {} -#[unstable(feature = "trusted_len", issue = "0")] +#[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for Chain where A: TrustedLen, B: TrustedLen, {} @@ -876,7 +876,7 @@ unsafe impl TrustedRandomAccess for Zip impl FusedIterator for Zip where A: FusedIterator, B: FusedIterator, {} -#[unstable(feature = "trusted_len", issue = "0")] +#[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for Zip where A: TrustedLen, B: TrustedLen, {} @@ -981,7 +981,7 @@ impl ExactSizeIterator for Map impl FusedIterator for Map where F: FnMut(I::Item) -> B {} -#[unstable(feature = "trusted_len", issue = "0")] +#[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for Map where I: TrustedLen, F: FnMut(I::Item) -> B {} @@ -1222,7 +1222,7 @@ unsafe impl TrustedRandomAccess for Enumerate #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for Enumerate where I: FusedIterator {} -#[unstable(feature = "trusted_len", issue = "0")] +#[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for Enumerate where I: TrustedLen, {} diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index ab55ee9d9d7b0..7c96be2facb48 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -482,7 +482,7 @@ macro_rules! range_incl_exact_iter_impl { macro_rules! range_trusted_len_impl { ($($t:ty)*) => ($( - #[unstable(feature = "trusted_len", issue = "0")] + #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for ops::Range<$t> { } )*) } diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index a56a864f6180d..2b0dd63a5714a 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -679,8 +679,8 @@ impl<'a, I: FusedIterator + ?Sized> FusedIterator for &'a mut I {} /// /// This trait must only be implemented when the contract is upheld. /// Consumers of this trait must inspect `.size_hint()`’s upper bound. -#[unstable(feature = "trusted_len", issue = "0")] +#[unstable(feature = "trusted_len", issue = "37572")] pub unsafe trait TrustedLen : Iterator {} -#[unstable(feature = "trusted_len", issue = "0")] +#[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<'a, I: TrustedLen + ?Sized> TrustedLen for &'a mut I {} diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 28845ef5e8c11..063adc2ac9f8a 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -834,7 +834,7 @@ impl<'a, A> ExactSizeIterator for Iter<'a, A> {} #[unstable(feature = "fused", issue = "35602")] impl<'a, A> FusedIterator for Iter<'a, A> {} -#[unstable(feature = "trusted_len", issue = "0")] +#[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<'a, A> TrustedLen for Iter<'a, A> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -872,7 +872,7 @@ impl<'a, A> ExactSizeIterator for IterMut<'a, A> {} #[unstable(feature = "fused", issue = "35602")] impl<'a, A> FusedIterator for IterMut<'a, A> {} -#[unstable(feature = "trusted_len", issue = "0")] +#[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<'a, A> TrustedLen for IterMut<'a, A> {} /// An iterator over the item contained inside an [`Option`]. @@ -904,7 +904,7 @@ impl ExactSizeIterator for IntoIter {} #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for IntoIter {} -#[unstable(feature = "trusted_len", issue = "0")] +#[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for IntoIter {} ///////////////////////////////////////////////////////////////////////////// diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 8985e7c8251e1..bae1eda7c4a9b 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -886,7 +886,7 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> {} #[unstable(feature = "fused", issue = "35602")] impl<'a, T> FusedIterator for Iter<'a, T> {} -#[unstable(feature = "trusted_len", issue = "0")] +#[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<'a, A> TrustedLen for Iter<'a, A> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -927,7 +927,7 @@ impl<'a, T> ExactSizeIterator for IterMut<'a, T> {} #[unstable(feature = "fused", issue = "35602")] impl<'a, T> FusedIterator for IterMut<'a, T> {} -#[unstable(feature = "trusted_len", issue = "0")] +#[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<'a, A> TrustedLen for IterMut<'a, A> {} /// An iterator over the value in a [`Ok`] variant of a [`Result`]. This struct is @@ -967,7 +967,7 @@ impl ExactSizeIterator for IntoIter {} #[unstable(feature = "fused", issue = "35602")] impl FusedIterator for IntoIter {} -#[unstable(feature = "trusted_len", issue = "0")] +#[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for IntoIter {} ///////////////////////////////////////////////////////////////////////////// diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 64d38c54c4767..871b63145ca6d 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -988,7 +988,7 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> {} #[unstable(feature = "fused", issue = "35602")] impl<'a, T> FusedIterator for Iter<'a, T> {} -#[unstable(feature = "trusted_len", issue = "0")] +#[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<'a, T> TrustedLen for Iter<'a, T> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1112,7 +1112,7 @@ impl<'a, T> ExactSizeIterator for IterMut<'a, T> {} #[unstable(feature = "fused", issue = "35602")] impl<'a, T> FusedIterator for IterMut<'a, T> {} -#[unstable(feature = "trusted_len", issue = "0")] +#[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<'a, T> TrustedLen for IterMut<'a, T> {} /// An internal abstraction over the splitting iterators, so that From 9366ba31668af3575ecadb3b35d2b67e138c3605 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Nov 2016 14:58:32 +1100 Subject: [PATCH 32/33] Reorder `hir::Expr` fields. On 64-bit platforms this reduces the size of `Expr` from 96 bytes to 88 bytes. --- src/librustc/hir/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index c451a789193aa..5ff69a789ed59 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -840,8 +840,8 @@ pub enum UnsafeSource { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)] pub struct Expr { pub id: NodeId, - pub node: Expr_, pub span: Span, + pub node: Expr_, pub attrs: ThinVec, } From 43452a36efae22492ffef157ce44f05346bde1b0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 4 Nov 2016 15:04:16 +1100 Subject: [PATCH 33/33] Shrink `Expr_::ExprStruct`. On 64-bit platforms this reduces the size of `Expr_` from 64 bytes to 56 bytes, and reduces the size of `Expr` from 88 bytes to 80 bytes. --- src/librustc/hir/lowering.rs | 4 ++-- src/librustc/hir/mod.rs | 2 +- src/librustc_const_eval/eval.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 620ee30c95628..7567c405bcaec 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1239,7 +1239,7 @@ impl<'a> LoweringContext<'a> { }), outputs.iter().map(|out| self.lower_expr(&out.expr)).collect(), inputs.iter().map(|&(_, ref input)| self.lower_expr(input)).collect()), ExprKind::Struct(ref path, ref fields, ref maybe_expr) => { - hir::ExprStruct(self.lower_path(path), + hir::ExprStruct(P(self.lower_path(path)), fields.iter().map(|x| self.lower_field(x)).collect(), maybe_expr.as_ref().map(|x| self.lower_expr(x))) } @@ -1743,7 +1743,7 @@ impl<'a> LoweringContext<'a> { e: Option>, attrs: ThinVec) -> P { let def = self.resolver.resolve_generated_global_path(&path, false); - let expr = self.expr(sp, hir::ExprStruct(path, fields, e), attrs); + let expr = self.expr(sp, hir::ExprStruct(P(path), fields, e), attrs); self.resolver.record_resolution(expr.id, def); expr } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 5ff69a789ed59..5f57ceac353cc 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -946,7 +946,7 @@ pub enum Expr_ { /// /// For example, `Foo {x: 1, y: 2}`, or /// `Foo {x: 1, .. base}`, where `base` is the `Option`. - ExprStruct(Path, HirVec, Option>), + ExprStruct(P, HirVec, Option>), /// An array literal constructed from one repeated element. /// diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index c02cca0da7225..ad9e718617a52 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -314,7 +314,7 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }, })) .collect::>()?; - PatKind::Struct(path.clone(), field_pats, false) + PatKind::Struct((**path).clone(), field_pats, false) } hir::ExprArray(ref exprs) => {